Code Monkey home page Code Monkey logo

sds-dust-sensors-arduino-library's Introduction

Nova Fitness SDS dust sensors arduino library

Supports Nova Fitness SDS011, SDS021 however should work for other Nova Fitness SDS sensors as well. This library attempts to provide easy-to-use abstraction over Laser Dust Sensor Control Protocol V1.3. Each response coming from sensor is validated whether it has correct head, command id, checksum and tail. Library also handles automatic retries in case of not available / failed response from sensor.

Quickstart

#include "SdsDustSensor.h"

int rxPin = D1;
int txPin = D2;
SdsDustSensor sds(rxPin, txPin);
// SdsDustSensor sds(Serial1); // if you are on a SAMD based board

void setup() {
  Serial.begin(9600);
  sds.begin();

  Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
  Serial.println(sds.setActiveReportingMode().toString()); // ensures sensor is in 'active' reporting mode
  Serial.println(sds.setContinuousWorkingPeriod().toString()); // ensures sensor has continuous working period - default but not recommended
}

void loop() {
  PmResult pm = sds.readPm();
  if (pm.isOk()) {
    Serial.print("PM2.5 = ");
    Serial.print(pm.pm25);
    Serial.print(", PM10 = ");
    Serial.println(pm.pm10);

    // if you want to just print the measured values, you can use toString() method as well
    Serial.println(pm.toString());
  } else {
    Serial.print("Could not read values from sensor, reason: ");
    Serial.println(pm.statusToString());
  }

  delay(500);
}

For more examples see examples folder.

Initialization

Communication with sensor can be handled by SoftwareSerial or HardwareSerial. You can pass SoftwareSerial or HardwareSerial directly to the constructor or provide rx & tx pins (library will use SoftwareSerial then).

Using tx and rx pins

Communication will be implicitly handled by SoftwareSerial.

int rxPin = D1;
int txPin = D2;
SdsDustSensor sds(rxPin, txPin); // you can tune retry mechanism with additional parameters: retryDelayMs and maxRetriesNotAvailable
sds.begin(); // you can pass custom baud rate as parameter (9600 by default)

This constructor is not available on SAMD based boards. SAMD boards should provide more than enough HardwareSerial ports / SERCOM ports.

Explicit SoftwareSerial

int rxPin = D1;
int txPin = D2;
SoftwareSerial softwareSerial(rxPin, txPin);
SdsDustSensor sds(softwareSerial); // you can tune retry mechanism with additional parameters: retryDelayMs and maxRetriesNotAvailable
sds.begin(); // you can pass custom baud rate as parameter (9600 by default)

This constructor is not available on SAMD based boards. SAMD boards should provide more than enough HardwareSerial ports / SERCOM ports.

Explicit HardwareSerial

SdsDustSensor sds(Serial1); // passing HardwareSerial as parameter, you can tune retry mechanism with additional parameters: retryDelayMs and maxRetriesNotAvailable
sds.begin(); // you can pass custom baud rate as parameter (9600 by default)

Supported operations

All operations listed in Laser Dust Sensor Control Protocol V1.3 are fully supported. They are listed below:

  • read PM2.5, PM10 values (reads data from software serial, does not write anything to the serial, all other operations write date to the sensor and expect response - sensor should be set to "active" reporting mode),
  • query PM2.5, PM10 values (in opposite to above, this one sends command to sensor and it responds with PM2.5 and PM10 values - sensor should be set to "query" reporting mode),
  • query reporting mode,
  • set reporting mode to "active",
  • set reporting mode to "query",
  • set new device id,
  • query working state,
  • set working state to "sleeping",
  • set working state to "working",
  • query working period,
  • set "continuous" working period (factory default - sensor sends pm values every 1 second),
  • set "custom" working period (recommended setting - 1-30min cycles),
  • check firmware version (year, month, day).

Additionally you can read device id from every sensor response.

Reading PM2.5 and PM10 values

The following function (readPm()) checks whether there is available data sent from sensor, it does not send any request to sensor so it has to be in 'active' reporting mode.

PmResult result = sds.readPm();
result.pm25; // float
result.pm10; // float

Querying PM2.5 and PM10 values

In opposite to above function, this one sends request to sensor and expects the response. Sensor should be in 'query' reporting mode.

PmResult result = sds.queryPm();
result.pm25; // float
result.pm10; // float

Setting custom working period - recommended over continuous

In order to set custom working period you need to specify single argument - duration (minutes) of the cycle. One cycle means working 30 sec, doing measurement and sleeping for duration-30 [sec]. This setting is recommended when using 'active' reporting mode.

int cycleMinutes = 4;
WorkingPeriodResult result = sds.setCustomWorkingPeriod(cycleMinutes);
result.period; // 4
result.isContinuous(); // false
result.toString();

Setting reporting mode to 'query'

When 'query' mode is active the sensor will not send data automatically, you need to send sds.queryPm() command on order to measure PM values.

ReportingModeResult result = sds.setQueryReportingMode();
result.mode; // MODE::QUERY

Setting sensor state to 'sleeping'

WorkingStateResult result = sds.sleep();
result.isWorking(); // false

Waking up

Safe wakeup tries to perform wakeup twice to assure proper response from sensor. When waking up after sleep sensor seems to respond with random bytes or not to respond at all. Despite incorrect response it seems to wake up correctly (fan starts working). Second wakeup forces sensor to send proper response. Because of the fact that sensor seems to work correctly (despite invalid response), you can use unsafe method if you don't care about the response.

Safe wakeup

WorkingStateResult result = sds.wakeup();
result.isWorking(); // true

Unsafe wakeup

WorkingStateResult result = sds.wakeupUnsafe();
result.isWorking(); // true

Other functions

Responses format of other functions can be found in src folder.

Helpful methods

Additionally with every sensor result you can:

  • access result status result.status, which can be one of {Ok, NotAvailable, InvalidChecksum, InvalidResponseId, InvalidHead, InvalidTail},
  • easily check whether response is correct with result.isOk() method,
  • convert status to string with result.statusToString() method.

You can also access result.deviceId() (pointer to the 1st (of 2) device id byte) and result.rawBytes (pointer to raw sensor response - byte array).

Additional notes and observations

Power consumption and modes

"Query" reporting mode probably consumes less power when sleeping than "Active" because the sensor doesn't have to know when it should wake up (doesn't have schedule any internal tasks).

References

sds-dust-sensors-arduino-library's People

Contributors

cyberman54 avatar kolen avatar lewapek avatar lukamicoder avatar mellbratt avatar noerw avatar per1234 avatar sankara avatar thepotatocannon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

sds-dust-sensors-arduino-library's Issues

Compiling error

Trying compile an example queryReportingMode.ino there is a lots of problems:
ex.
src/SdsDustSensorResults.h:62:12: error: 'Mode' is not a class or namespace
case Mode::Active: return "Mode: active";
src/SdsDustSensorResults.h: In constructor 'WorkingStateResult::WorkingStateResult(const Status&, byte*)':

Compilation fails with SoftwareSerial.h not found. Library.json version doesn't match tag 1.4.0?

When I try to install this library using the library manager, it fails saying "SoftwareSerial.h" is not found. I looked into the codebase and I clearly see that you have #ifndef statements to validate if SoftwareSerial is required before including it. So I opened up the downloaded code and found that it was different from what I saw on Github. I was able to workaround the issue then by manually downloading the codebase and installing it as zip.

I did further research and found you have specified the library version as 1.3.2 in library.json whereas the changes that has the #ifndef statements were made after v1.3.2 tag was released. The latest tag seems to be 1.4.0. I'll follow this up with a PR to change the library version (assuming my diagnosis is correct).

sds011 stuck in custom mode

Hey, i tried the custom timing mode and now the sensor kind of seems like its stuck in it. Ofc i tried to upload other programs like the quickstart but the behaviour of the sensor doesnt change, furthermore there are quite many reading errors.

ESP32 hardware serial UART2

could someone help me how to assign GPIO pins under ESP32 to Serial2 together with this library ?
Sorry for beginners question here...
Thanks
Kai

Add esp32 to the SoftwareSerial.h #ifdef

The esp32 also doesn't have the SoftwareSerial.h library, it just works without it though.
Also you should add the esp32 to the compatibility list in the properties, at the moment there's only the esp8266.

WakingUp

Hi @lewapek!
I've just try to run this program.
But my sensor still set on rest mode and doesn't work. How can I set it on wakeup mode?
Sorry for the question, but I'm new with Arduino and c++ to.

Consistent high readings using this code

Hi,

i'm just experimenting a bit with an sds011 sensor and this code. First I hooked up the sds to the accompanying usb adaptor together with this tool: https://github.com/karlchen86/SDS011 and got these readings:

Type: set mode: query
PM2.5: 2.00, PM10: 3.00
PM2.5: 1.90, PM10: 2.80
PM2.5: 1.80, PM10: 2.70
PM2.5: 1.70, PM10: 3.10
PM2.5: 1.70, PM10: 3.00
PM2.5: 1.60, PM10: 3.10

Which seem quite ok since I'm testing indoors.
However while testing this code, I'm getting consistently way higher readings:

Using example sketch:


16:18:08.071 -> pm25: 88.00, pm10: 95.00
16:18:09.035 -> PM2.5 = 91.10, PM10 = 98.30
16:18:09.068 -> pm25: 91.10, pm10: 98.30
16:18:10.031 -> PM2.5 = 92.40, PM10 = 99.70
16:18:10.065 -> pm25: 92.40, pm10: 99.70
16:18:11.027 -> PM2.5 = 93.60, PM10 = 101.00

I've got 2 SDS011 sensors and both share the same behaviour. Could you maybe explain the difference? Do you maybe use a different calculation method?

invalid initialization of non-const reference of type 'HardwareSerial&' , sds(rxPin, txPin);

When I try to compile the example for a ES32 board, I get this error in the Arduino IDE.

Feinstaub:33:31: error: invalid initialization of non-const reference of type 'HardwareSerial&' from an rvalue of type 'HardwareSerial'
 SdsDustSensor sds(rxPin, txPin);
                               ^
In file included from /home/kevin/.arduino15/packages/esp32/hardware/esp32/1.0.6/cores/esp32/Arduino.h:154:0,
                 from sketch/Feinstaub.ino.cpp:1:
/home/kevin/.arduino15/packages/esp32/hardware/esp32/1.0.6/cores/esp32/HardwareSerial.h:56:5: note:   after user-defined conversion: HardwareSerial::HardwareSerial(int)
     HardwareSerial(int uart_nr);
     ^
In file included from /home/kevin/Arduino/Feinstaub/Feinstaub.ino:2:0:
/home/kevin/Arduino/libraries/Nova_Fitness_Sds_dust_sensors_library/src/SdsDustSensor.h:60:3: note:   initializing argument 1 of 'SdsDustSensor::SdsDustSensor(HardwareSerial&, int, int)'
   SdsDustSensor(HardwareSerial &hardwareSerial,
   ^

Line 31-33 are the following:

int rxPin = 21;
int txPin = 22;
SdsDustSensor sds(rxPin, txPin);

Issue when waking up

Hello @lewapek,
thank you very much for your library.

I tried to use it, but run into a weird issue.
If using the continous mode without sleeping everything works fine.
But as soon as I put the sensor into sleep mode and wake it up I get weird responses, leading the sds-dust-sensors-arduino-library to return an InvalidHead response.

For debugging purposes I implemented my own "library" to investigate further.
Putting my sensor to sleep works.
Waking it up returns seemingly random 5 bytes, for example, when waking the sensor up after a 30 seconds sleep, this is what the sensor responds:

0: ad
0: 50
0: 10
0: 5e
0: dd

The 0: is indicating the index.
As the AA is missing, no new message is identified and thus the index is 0 all the time.

From this point on all communication works as specified, e.g. sending another wake up, returns the following bytes

0: aa
1: c5
2: 6
3: 1
4: 1
5: 0
6: ec
7: e1
8: d5
9: ab
=> Message received: AA C5 6 1 1 0 EC E1 D5 AB 

Did you observe a similar behaviour or do you have any idea what might be wrong with my sensor?

Issue with The Things Uno (LoraWAN Leonardo).

First of all thanks for sharing this library which I use on an Arduino Leonardo or, te be more specific, on a The Things Uno board which is a Leonardo with integrated LoRaWAN.

Using the (unmodified) hardware.Serial.ino demo sketch, without the first measurement works fine and shows the PM10 and PM25 values in the serial monitor. Every following measurement shows bot PM values as 0.00 (zero). After a reset or boot the same issue is shown: only the first measurement is correct. The SDS011 sensor seems to be okay because it works fine in another setup with an Arduino Uno.

Is this a known issue or am I doing something wrong and can you advice me how to solve this?

Compilation fails on Arduino Nano 33 BLE (Sense)

Hello, and first of all thanks for your great and useful library!

By compiling code containing reference to "SdsDustSensor.h" on Arduino IDE 1.8.42.0 using card "Arduino Nano 33 BLE" I get the following error:

............\Documents\Arduino\libraries\Nova_Fitness_Sds_dust_sensors_library\src/SdsDustSensorResults.h:6:10: fatal error: SoftwareSerial.h: No such file or directory

#include <SoftwareSerial.h>

I've checked the code and in "Serials.h" found the lines

#ifndef ARDUINO_SAMD_VARIANT_COMPLIANCE // there is no SoftwareSerial available (needed) on SAMD boards.
#include <SoftwareSerial.h>
#endif
#include <HardwareSerial.h>

My suspect is, the Nano 33 BLE is a different category than ARDUINO_SAMD, and as with ARDUINO_SAMD the "SoftwareSerial.h" library is missing.

Invalid firmware version

Sensor board sometimes returns incorrect firmware version with status OK.
Some of tested sds011 sensors returned 1.0.0 version [year.month.day].

Solution:
version should be checked against possible ranges (at least month and day) and result in different status (not ok - it may require new status)

Query mode example missing evry other reading

No idea why but I want to get a reading every minute and it seems like I'm geting one evry 5 minutes and failures in beetwen:

I'm using NodeMCU 1.0 board, It's actually Amica v2 and latest release of your library.

14:51:48.941 -> �⸮� ⸮-⸮⸮⸮Firmware version [year.month.day]: 18.11.16
14:51:50.074 -> Mode: query
14:52:21.621 -> Could not read values from sensor, reason: Not available
14:52:22.650 -> Sensor is sleeping
14:53:55.226 -> PM2.5 = 1.90, PM10 = 3.40
14:53:55.261 -> pm25: 1.90, pm10: 3.40
14:53:55.743 -> Sensor is sleeping
14:55:27.314 -> Could not read values from sensor, reason: Not available
14:55:28.341 -> Sensor is sleeping
14:57:00.915 -> PM2.5 = 2.00, PM10 = 2.80
14:57:00.950 -> pm25: 2.00, pm10: 2.80
14:57:01.428 -> Sensor is sleeping
14:58:32.991 -> Could not read values from sensor, reason: Not available
14:58:34.026 -> Sensor is sleeping
15:00:06.609 -> PM2.5 = 2.00, PM10 = 3.70
15:00:06.609 -> pm25: 2.00, pm10: 3.70
15:00:07.124 -> Sensor is sleeping
15:01:38.674 -> Could not read values from sensor, reason: Not available
15:01:39.708 -> Sensor is sleeping
15:03:12.275 -> PM2.5 = 2.40, PM10 = 5.00
15:03:12.310 -> pm25: 2.40, pm10: 5.00
15:03:12.824 -> Sensor is sleeping
15:04:44.375 -> Could not read values from sensor, reason: Not available
15:04:45.402 -> Sensor is sleeping

Uploaded example code:

#include "SdsDustSensor.h"

int rxPin = D1;
int txPin = D2;
SdsDustSensor sds(rxPin, txPin);

void setup() {
  Serial.begin(9600);
  sds.begin();

  Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
  Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
}

void loop() {
  sds.wakeup();
  delay(30000); // working 30 seconds

  PmResult pm = sds.queryPm();
  if (pm.isOk()) {
    Serial.print("PM2.5 = ");
    Serial.print(pm.pm25);
    Serial.print(", PM10 = ");
    Serial.println(pm.pm10);

    // if you want to just print the measured values, you can use toString() method as well
    Serial.println(pm.toString());
  } else {
    Serial.print("Could not read values from sensor, reason: ");
    Serial.println(pm.statusToString());
  }

  WorkingStateResult state = sds.sleep();
  if (state.isWorking()) {
    Serial.println("Problem with sleeping the sensor.");
  } else {
    Serial.println("Sensor is sleeping");
    delay(60000); // wait 1 minute
  }
}

Can You help?

Library not working well with hardware serial

Trying to use the library with Adafruit's Feather m0 LoRa, a SAMD based board that has several assignable hardware serial ports but doesn't play well with the software serial library. I've tried to make some adaptations but have gotten stuck. Any plans to update the library and accommodate streams that aren't software serial?

Using hardwareserial crashing in sds.begin() on arduino-espressif32 framework

I am on arduino-espressif32 framework, thus using HardwareSerial.
I don't get the library run on top of this, it's crashing in sds.begin() with a Guru Meditation error:

17:44:31.126 > [I][main.cpp:371] setup(): init fine-dust-sensor
17:44:31.132 > Guru Meditation Error: Core  1 panic'ed (IllegalInstruction). Exception was unhandled.
17:44:31.334 >   #0  0x400d9534:0x3ffd09a0 in SdsDustSensor::execute(Command const&) at .pio/libdeps/usb/Nova Fitness Sds dust sensors library/src/SdsDustSensor.h:165
17:44:31.334 > Rebooting...

My serial initialization code is:

HardwareSerial sds_Serial(2); // use UART #2
SdsDustSensor sds(sds_Serial);

void setup {
  sds_Serial.begin(9600, SERIAL_8N1, 19, 23);
  sds.begin();
  ...
}

Any hints or suggestions what's wrong here?

Incompatibility with SD.h

Hello,

Thanks for your repository, I was able to use it to read from my sensor.

I wanted to save those readings to the microSD card attached to Arduino. However, by just including in the code #include <SD.h>, the Arduino simply doesn't work anymore (I cannot even read anything from the Serial, I'm guessing that's because setup() is executed). The constructor I'm using for the sensor is SdsDustSensor sds(10, 11);

Can you give any help trying to debug this, please? I'm guessing some part is shared across these 2 libraries... Have you ever had this problem? How do you usually save the readings from the sensor?

Thanks.

Query reporting mode

Hello,
If I don't use a serial monitor can I set the Query reporting mode without the command "Serial.println" present in the file in the examples folder? : Serial.println(sds.setQueryReportingMode().toString()); ?

I would to set the SDS011 sensor in query reporting mode, wakeup the sensor, read the PM value and sleep the sensor.

Can I use this command?

ReportingModeResult result = sds.setQueryReportingMode(); or exist a command without result?

sds.wakeup(); (like file in the example folder)

PmResult result = sds.queryPm();

WorkingStateResult result = sds.sleep(); or exist a command without result like sds.wakeup();?

In a first test, if I use the serial monitor, initially I read strange values in the serial monitor.
Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.