dok-net / esp_sds011 Goto Github PK
View Code? Open in Web Editor NEWThis project forked from kadamski/arduino_sds011
ESP8266/ESP32 Arduino library for the SDS011 dust sensor
License: MIT License
This project forked from kadamski/arduino_sds011
ESP8266/ESP32 Arduino library for the SDS011 dust sensor
License: MIT License
Hi Dirk and thanks for your surprisingly functional library.
I hooked up one of my SDS011 sensors and am reading quite absurd values. Both pm2.5 and pm10 read about 200~300 every time. Assuming that the measurements are in ug/m³, this is a tad bit high ;)
Does this indeed sound weird, or is my assumption wrong?
Moreover - could you provide a sketch that runs in continuous mode with just single measurements? The async is throwing me a bit off and for troubleshooting I'd love a simple sketch which measures continuously. I could probably hack it myself but if you have something..
Cheers! Steven
(Not sure if this is a problem in the library or if I should post this somewhere else. Pls let me know and I will remove the post).
I started from the measure.ino example but modified setup to look like this:
void setup()
{
Serial.begin(115200);
#ifdef ESP32
serialSDS.begin(9600, SERIAL_8N1, SDS_PIN_RX, SDS_PIN_TX);
delay(100);
#else
serialSDS.begin(9600, SDS_PIN_RX, SDS_PIN_TX, SWSERIAL_8N1, false, 192);
#endif
Serial.println("SDS011 start/stop and reporting sample");
measure(); // moved the loop code to a separate method
Serial.println("Measure complete");
stop_SDS(); // the fan spins down
Serial.println("SDS stopped");
delay(1000);
esp_sleep_enable_timer_wakeup(25 * uS_TO_S_FACTOR); //sleep 25 secs
esp_deep_sleep_start();
// SDS011 fan starts as soon as the ESP32 goes to sleep...
}
stop_SDS() seems to put the SDS011 to sleep (fan spins down) but as soon as the ESP32 goes to deep sleep the SDS011 fan starts spinning again. Am I wrong in expecting the SDS011 to go to sleep until the ESP32 wakes up again after 25 secs?
Hi
I have noticed blocking issue in _read_response
in case when TX line from ESP to SDS is being cut/disconnected. After power on SDS011 with factory settings will send readings. _read_response
will block in such case. Response format is different than data frame format and code execution will be blocked by switch command https://github.com/dok-net/esp_sds011/blob/master/src/Sds011.cpp#L200
I guess that it will happen also when to serial will be attached other device than SDS011 which will be sending data stream not matching frame format expected by _read_response
.
I guess there should be some kind of global timeout, not only per byte to avoid ESP from being totally unresponsive in such case.
Default rampup time is 10 second (10 packets). According to Laser Dust Sensor Control Protocol from Novafitness, after wakeup 30 seconds is needed to wait before taking measurements (https://nettigo.pl/attachments/415 note to sleep command on page 4). Shouldn't it be changed?
Hello,
I'm working on using an SDS011 as part of a LoRaWAN-based air quality monitor and I'm having trouble getting the readings.
I'm using a Heltec LoRa WiFi 32 v2 board. The sample code below is uploaded via the Arduino IDE, my own code is uploaded via PlatformIO.org - obviously this shouldn't make a difference but I want to make sure I'm as close to your original code and setup as possible!
Due to the way that the LoRaWAN library works, I've taken the code from https://github.com/dok-net/esp_sds011/blob/main/examples/measure/measure.ino and moved it into a dedicated function which is then called as part of a LoRaWAN "update and send" function which is called from the loop()
function.
To replicate this, I've created a stripped back version of my code (See below) however I'm still seeing the same issue, namely that the device id and firmware version are returned (so I know I'm talking to the sensor correctly), however the measurements are never put into the variables.
The only change I've made is to move the int pm25
and int pm10
variables out of the sds011.on_query_data_auto_completed
function and into the top of my code so I can use them as values elsewhere, but otherwise the code remains intact and the output is the countdown along with the occasional:
09:21:03.009 -> Start wakeup SDS011
09:21:03.141 -> End wakeup SDS011
09:21:03.141 -> started SDS011 (is running = 1)
09:21:03.141 -> SDS011 measurement capture start failed
09:21:04.137 -> 29
09:21:05.131 -> 28
09:21:06.127 -> 27
09:21:07.123 -> 26
09:21:08.118 -> 25
09:21:09.147 -> 24
09:21:10.141 -> 23
09:21:11.135 -> 22
09:21:12.130 -> 21
09:21:13.129 -> 20
09:21:14.125 -> 19
09:21:15.120 -> 18
09:21:16.148 -> 17
09:21:17.143 -> 16
09:21:18.138 -> 15
09:21:19.133 -> 14
09:21:20.129 -> 13
09:21:21.123 -> 12
09:21:22.118 -> 11
09:21:23.146 -> 10
09:21:24.141 -> 9
09:21:25.136 -> 8
09:21:26.131 -> 7
09:21:27.125 -> 6
09:21:28.119 -> 5
09:21:29.146 -> 4
09:21:30.139 -> 3
09:21:31.133 -> 2
09:21:32.128 -> 1
09:21:33.123 -> 0
09:21:33.123 -> Start sleep SDS011
09:21:33.223 -> End sleep SDS011
09:21:33.223 -> stopped SDS011 (is running = 0)
09:21:34.221 -> 209
09:21:35.216 -> 208
09:21:36.211 -> 207
09:21:36.211 -> Begin Handling SDS011 query data
09:21:36.211 -> n = 0
09:21:36.211 -> End Handling SDS011 query data
Any help you can provide on why these measurements do not appear to be taken correctly would be appreciated!
My code is as follows:
#include <SoftwareSerial.h>
#include <esp_sds011.h>
/******************************* Air Quality Sensor **********************************************/
#define SDSTX 12 //pin number for TX output from ESP32 - RX into SDS011
#define SDSRX 13 //pin number for RX input into ESP32 - TX from SDS011
HardwareSerial& SDSserial(Serial1);
Sds011Async< HardwareSerial > sds011(SDSserial);
// The example stops the sensor for 210s, then runs it for 30s, then repeats.
// At tablesizes 20 and below, the tables get filled during duty cycle
// and then measurement completes.
// At tablesizes above 20, the tables do not get completely filled
// during the 30s total runtime, and the rampup / 4 timeout trips,
// thus completing the measurement at whatever number of data points
// were recorded in the tables.
constexpr int pm_tablesize = 20;
int pm25_table[pm_tablesize];
int pm10_table[pm_tablesize];
int pm25 = 0;
int pm10 = 0;
//
bool is_SDS_running = true;
void start_SDS() {
Serial.println(F("Start wakeup SDS011"));
if (sds011.set_sleep(false)) { is_SDS_running = true; }
Serial.println(F("End wakeup SDS011"));
}
void stop_SDS() {
Serial.println(F("Start sleep SDS011"));
if (sds011.set_sleep(true)) { is_SDS_running = false; }
Serial.println(F("End sleep SDS011"));
}
void run_aq_sensor() {
// Per manufacturer specification, place the sensor in standby to prolong service life.
// At an user-determined interval (here 210s down plus 30s duty = 4m), run the sensor for 30s.
// Quick response time is given as 10s by the manufacturer, thus the library drops the
// measurements obtained during the first 10s of each run.
constexpr uint32_t down_s = 210;
stop_SDS();
Serial.print(F("stopped SDS011 (is running = "));
Serial.print(is_SDS_running);
Serial.println(')');
uint32_t deadline = millis() + down_s * 1000;
while (static_cast<int32_t>(deadline - millis()) > 0) {
delay(1000);
Serial.println(static_cast<int32_t>(deadline - millis()) / 1000);
sds011.perform_work();
}
constexpr uint32_t duty_s = 30;
start_SDS();
Serial.print(F("started SDS011 (is running = "));
Serial.print(is_SDS_running);
Serial.println(')');
sds011.on_query_data_auto_completed([](int n) {
Serial.println(F("Begin Handling SDS011 query data"));
Serial.print(F("n = ")); Serial.println(n);
if (sds011.filter_data(n, pm25_table, pm10_table, pm25, pm10) &&
!isnan(pm10) && !isnan(pm25)) {
Serial.print(F("PM10: "));
Serial.println(float(pm10) / 10);
Serial.print(F("PM2.5: "));
Serial.println(float(pm25) / 10);
}
Serial.println(F("End Handling SDS011 query data"));
});
if (!sds011.query_data_auto_async(pm_tablesize, pm25_table, pm10_table)) {
Serial.println(F("SDS011 measurement capture start failed"));
}
deadline = millis() + duty_s * 1000;
while (static_cast<int32_t>(deadline - millis()) > 0) {
delay(1000);
Serial.println(static_cast<int32_t>(deadline - millis()) / 1000);
sds011.perform_work();
}
}
/******************************* Air Quality Sensor **********************************************/
void setup(){
Serial.begin(115200);
/************* SDS011 ************************/
SDSserial.begin(9600, SERIAL_8N1, SDSRX, SDSTX);
delay(100);
Serial.println(F("SDS011 start/stop and reporting sample"));
start_SDS();
Serial.print(F("SDS011 is running = "));
Serial.println(is_SDS_running);
String firmware_version;
uint16_t device_id;
if (!sds011.device_info(firmware_version, device_id)) {
Serial.println(F("Sds011::firmware_version() failed"));
}
else
{
Serial.print(F("Sds011 firmware version: "));
Serial.println(firmware_version);
Serial.print(F("Sds011 device id: "));
Serial.println(device_id, 16);
}
Sds011::Report_mode report_mode;
if (!sds011.get_data_reporting_mode(report_mode)) {
Serial.println(F("Sds011::get_data_reporting_mode() failed"));
}
if (Sds011::REPORT_ACTIVE != report_mode) {
Serial.println(F("Turning on Sds011::REPORT_ACTIVE reporting mode"));
if (!sds011.set_data_reporting_mode(Sds011::REPORT_ACTIVE)) {
Serial.println(F("Sds011::set_data_reporting_mode(Sds011::REPORT_ACTIVE) failed"));
}
}
/*************** END SDS011 **********************/
}
void loop(){
run_aq_sensor();
}
When I try to compile it in the Arduino IDE for an ESP32 board, I get this error.
Arduino: 1.8.12 (Linux), Board: "ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 921600, None"
In file included from /home/kevin/Arduino/Feinstaub2/Feinstaub2.ino:2:0:
/home/kevin/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.h:226:20: error: enclosing class of constexpr non-static member function 'bool SoftwareSerial::isValidGPIOpin(int8_t) const' is not a literal type
constexpr bool isValidGPIOpin(int8_t pin) const;
^
/home/kevin/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.h:87:7: note: 'SoftwareSerial' is not literal because:
class SoftwareSerial : public Stream {
^
/home/kevin/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.h:87:7: note: 'SoftwareSerial' has a non-trivial destructor
/home/kevin/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.h:227:20: error: enclosing class of constexpr non-static member function 'bool SoftwareSerial::isValidRxGPIOpin(int8_t) const' is not a literal type
constexpr bool isValidRxGPIOpin(int8_t pin) const;
^
/home/kevin/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.h:228:20: error: enclosing class of constexpr non-static member function 'bool SoftwareSerial::isValidTxGPIOpin(int8_t) const' is not a literal type
constexpr bool isValidTxGPIOpin(int8_t pin) const;
^
/home/kevin/Arduino/libraries/EspSoftwareSerial/src/SoftwareSerial.h:230:20: error: enclosing class of constexpr non-static member function 'bool SoftwareSerial::hasRxGPIOPullUp(int8_t) const' is not a literal type
constexpr bool hasRxGPIOPullUp(int8_t pin) const;
^
Mehrere Bibliotheken wurden für "WiFi.h" gefunden
Benutzt: /home/kevin/.arduino15/packages/esp32/hardware/esp32/1.0.6/libraries/WiFi
Nicht benutzt: /home/kevin/.local/share/umake/ide/arduino/libraries/WiFi
exit status 1
Fehler beim Kompilieren für das Board ESP32 Dev Module.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.