#ifdef SENSOR_SDS018 #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(); } } #endif