Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sleep support for Nova Fitness SDS011 sensor #2387

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions code/espurna/config/sensors.h
Original file line number Diff line number Diff line change
Expand Up @@ -1001,6 +1001,19 @@
#define SDS011_TX_PIN 12
#endif

#ifndef SDS011_REPORTING_MODE
#define SDS011_REPORTING_MODE 1 // Mode 0 = query, 1 = active. Default mode is 'active' where data is
#endif // read from software serial instead of querying the sensor.

#ifndef SDS011_CUSTOM_WORKING_PERIOD
#define SDS011_CUSTOM_WORKING_PERIOD 300 // Duration of the cycle in seconds. Each cycle works as follows:
#endif // for each working period, 30 seconds will be reserved for waking up
// the sensor, measuring and at the end of cycle, a new reading will be
// provided. For example, for a working period of 300 second (5 minutes)
// the sensor will wake up after 4.5 minutes, work for 0.5 minutes
// (completing the working period of 5 minutes) and sleep for another
// 4.5 minutes. This is the recommended setting.

//------------------------------------------------------------------------------
// SenseAir CO2 sensor
// Enable support by passing SENSEAIR_SUPPORT=1 build flag
Expand Down
1 change: 1 addition & 0 deletions code/espurna/sensors/BaseSensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class BaseSensor {
return sensor::Unit::KilowattHour;
case MAGNITUDE_PM1dot0:
case MAGNITUDE_PM2dot5:
case MAGNITUDE_PM10:
return sensor::Unit::MicrogrammPerCubicMeter;
case MAGNITUDE_CO:
case MAGNITUDE_CO2:
Expand Down
85 changes: 45 additions & 40 deletions code/espurna/sensors/SDS011Sensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#pragma once

#include <Arduino.h>
#include <SoftwareSerial.h>
#include "SdsDustSensor.h"

#include "BaseSensor.h"

Expand All @@ -30,7 +30,7 @@ class SDS011Sensor : public BaseSensor {
}

~SDS011Sensor() {
if (_serial) delete _serial;
if (_sensor) delete _sensor;
}

// ---------------------------------------------------------------------
Expand Down Expand Up @@ -66,10 +66,24 @@ class SDS011Sensor : public BaseSensor {

if (!_dirty) return;

if (_serial) delete _serial;
if (_sensor) delete _sensor;

_serial = new SoftwareSerial(_pin_rx, _pin_tx);
_serial->begin(9600);
_sensor = new SdsDustSensor(_pin_rx, _pin_tx);
_sensor->begin(9600);

#if SDS011_REPORTING_MODE == 0
_sensor->setQueryReportingMode();
#elif SDS011_REPORTING_MODE == 1
_sensor->setActiveReportingMode();
_sensor->setContinuousWorkingPeriod();
#if SDS011_CUSTOM_WORKING_PERIOD > 0
_sensor->setCustomWorkingPeriod(SDS011_CUSTOM_WORKING_PERIOD / 60);
#endif
#endif

DEBUG_MSG_P(PSTR("[SDS011] %s\n"), _sensor->queryFirmwareVersion().toString().c_str());
DEBUG_MSG_P(PSTR("[SDS011] %s\n"), _sensor->queryReportingMode().toString().c_str());
DEBUG_MSG_P(PSTR("[SDS011] %s\n"), _sensor->queryWorkingPeriod().toString().c_str());

_ready = true;
_dirty = false;
Expand Down Expand Up @@ -121,53 +135,44 @@ class SDS011Sensor : public BaseSensor {
// ---------------------------------------------------------------------

void _read() {
byte buffer;
int value;
int len = 0;
int pm10_serial = 0;
int pm25_serial = 0;
int checksum_is = 0;
int checksum_ok = 0;

while ((_serial->available() > 0) && (_serial->available() >= (10-len))) {
buffer = _serial->read();
value = int(buffer);
switch (len) {
case (0): if (value != 170) { len = -1; }; break;
case (1): if (value != 192) { len = -1; }; break;
case (2): pm25_serial = value; checksum_is = value; break;
case (3): pm25_serial += (value << 8); checksum_is += value; break;
case (4): pm10_serial = value; checksum_is += value; break;
case (5): pm10_serial += (value << 8); checksum_is += value; break;
case (6): checksum_is += value; break;
case (7): checksum_is += value; break;
case (8): if (value == (checksum_is % 256)) { checksum_ok = 1; } else { len = -1; }; break;
case (9): if (value != 171) { len = -1; }; break;
}
#if SDS011_REPORTING_MODE == 0
PmResult pm = _sensor->queryPm();
#elif SDS011_REPORTING_MODE == 1
PmResult pm = _sensor->readPm();
#endif

if (!pm.isOk()) {
switch (pm.status) {
case Status::NotAvailable:
#if SDS011_CUSTOM_WORKING_PERIOD != -1
if (_p2dot5 == 0 && _p10 == 0) {
_error = SENSOR_ERROR_WARM_UP;
return;
}

len++;

if (len == 10) {
if(checksum_ok == 1) {
_p10 = (float)pm10_serial/10.0;
_p2dot5 = (float)pm25_serial/10.0;
len = 0; checksum_ok = 0; pm10_serial = 0.0; pm25_serial = 0.0; checksum_is = 0;
_error = SENSOR_ERROR_OK;
} else {
return;
#endif
case Status::InvalidChecksum:
_error = SENSOR_ERROR_CRC;
}
return;
default:
_error = SENSOR_ERROR_OTHER;
return;
}

yield();
}

_error = SENSOR_ERROR_OK;

_p10 = pm.pm10;
_p2dot5 = pm.pm25;
}

double _p2dot5 = 0;
double _p10 = 0;
unsigned int _pin_rx;
unsigned int _pin_tx;
SoftwareSerial * _serial = NULL;
SdsDustSensor * _sensor = NULL;

};

Expand Down
1 change: 1 addition & 0 deletions code/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ lib_deps =
https://github.com/ThingPulse/esp8266-oled-ssd1306#3398c97
Adafruit SI1145 Library@~1.1.1
https://github.com/BoschSensortec/BSEC-Arduino-library.git#c5503e0
https://github.com/lewapek/sds-dust-sensors-arduino-library#154c711

# ------------------------------------------------------------------------------
# COMMON ENVIRONMENT SETTINGS:
Expand Down