sensoresp/include/sensor_sds018.cpp

157 lines
4.0 KiB
C++

#include "sensor_sds018.h"
// SDS018 example: https://github.com/crystaldust/sds018/blob/master/sds018.ino
//SDS18 dust sensor for 2.5µm and 10µm
//Needs 5V
Sensor_SDS018::Sensor_SDS018(int prx,int ptx)
{
pin_rx=prx;
pin_tx=ptx;
sds018_swSerial = new SoftwareSerial();
}
void Sensor_SDS018::init() //Things to be done during setup()
{
Serial.println("initializing sds018");
sds018_swSerial->begin(BAUD_RATE_SDS018, SWSERIAL_8N1, pin_rx, pin_tx, false, 256);
init_ok=true;
}
//Also called during setup()
void Sensor_SDS018::setSettings_pm10(float minchange, unsigned long senddelaymax, unsigned long readdelay)
{
data_pm10.minchange=minchange;
data_pm10.senddelaymax=senddelaymax;
data_pm10.readdelay=readdelay;
}
void Sensor_SDS018::setSettings_pm25(float minchange, unsigned long senddelaymax, unsigned long readdelay)
{
data_pm25.minchange=minchange;
data_pm25.senddelaymax=senddelaymax;
data_pm25.readdelay=readdelay;
}
//Called during setup
void Sensor_SDS018::advertise(HomieNode& p_sensorNode)
{
sensorNode = &p_sensorNode;
sensorNode->advertise("dust_pm25");
sensorNode->advertise("dust_pm10");
}
void Sensor_SDS018::sensorloop()
{
if (init_ok) {
loop_pm10();
loop_pm25();
}
}
void Sensor_SDS018::loop_pm25()
{
sensordata &d=data_pm25;
bool _changed=false;
if (millis() >= (d.lastreadtime+d.readdelay)) {
if (millis() >= (lastread_sds018+d.readdelay)) {
readSDS018(); //reads values into data_pm10 and data_pm25
}
if (fabs(d.lastsentvalue-d.value)>=d.minchange){
_changed=true;
}
d.lastreadtime=millis();
}
if (_changed || millis() >= (d.lastsent+d.senddelaymax)) {
Serial.print("Sending SDS018_pm25. reason=");
if (_changed) Serial.println("change"); else Serial.println("time");
Homie.getLogger() << "read pm25: " << d.value << " status=" << sds018_dustok << endl;
if (sds018_dustok){ //send no dust values if sensor not ok
sensorNode->setProperty("dust_pm25").send(String(d.value));
}else{
Homie.getLogger() << "sds018 dust not ok. didnt sent" << endl;
}
d.lastsentvalue=d.value;
d.lastsent=millis();
}
}
void Sensor_SDS018::loop_pm10()
{
sensordata &d=data_pm10;
bool _changed=false;
if (millis() >= (d.lastreadtime+d.readdelay)) {
if (millis() >= (lastread_sds018+d.readdelay)) {
readSDS018(); //reads values into data_pm10 and data_pm25
}
if (fabs(d.lastsentvalue-d.value)>=d.minchange){
_changed=true;
}
d.lastreadtime=millis();
}
if (_changed || millis() >= (d.lastsent+d.senddelaymax)) {
Serial.print("Sending SDS018_pm10. reason=");
if (_changed) Serial.println("change"); else Serial.println("time");
Homie.getLogger() << "read pm10: " << d.value << " status=" << sds018_dustok << endl;
if (sds018_dustok){ //send no dust values if sensor not ok
sensorNode->setProperty("dust_pm10").send(String(d.value));
}else{
Homie.getLogger() << "sds018 dust not ok. didnt sent" << endl;
}
d.lastsentvalue=d.value;
d.lastsent=millis();
}
}
void Sensor_SDS018::readSDS018()
{
lastread_sds018=millis();
// https://github.com/crystaldust/sds018/blob/master/sds018.ino
uint8_t mData = 0;
uint8_t mPkt[10] = {0};
uint8_t mCheck = 0;
while( sds018_swSerial->available() > 0 ) {
//Serial.println("serial available");
for( int i=0; i<10; ++i ) {
mPkt[i] = sds018_swSerial->read();
//Serial.println( mPkt[i], HEX );
}
if( 0xC0 == mPkt[1] ) {
Serial.println("read density");
// Read dust density.
// Check
uint8_t sum = 0;
for( int i=2; i<=7; ++i ) {
sum += mPkt[i];
}
if( sum == mPkt[8] ) {
uint8_t pm25Low = mPkt[2];
uint8_t pm25High = mPkt[3];
uint8_t pm10Low = mPkt[4];
uint8_t pm10High = mPkt[5];
data_pm25.value = ( ( pm25High * 256.0 ) + pm25Low ) / 10.0;
data_pm10.value = ( ( pm10High * 256.0 ) + pm10Low ) / 10.0;
sds018_dustok=true;
}
}
sds018_swSerial->flush();
}
}