diff --git a/include/sensor_sds018.cpp b/include/sensor_sds018.cpp new file mode 100644 index 0000000..a21fe60 --- /dev/null +++ b/include/sensor_sds018.cpp @@ -0,0 +1,155 @@ +#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; +} + +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(); + } +} \ No newline at end of file diff --git a/include/sensor_sds018.h b/include/sensor_sds018.h new file mode 100644 index 0000000..31e3b17 --- /dev/null +++ b/include/sensor_sds018.h @@ -0,0 +1,52 @@ +#ifndef SENSOR_SDS018_H +#define SENSOR_SDS018_H + +#include "sensordata.h" +#include + + +#include + + +class Sensor_SDS018 +{ + +private: + HomieNode *sensorNode; //reference to HomieNode + + struct sensordata data_pm25; + struct sensordata data_pm10; + + int pin_rx; + int pin_tx; + + bool init_ok; + + #define BAUD_RATE_SDS018 9600 + SoftwareSerial *sds018_swSerial; + + bool sds018_dustok; + + unsigned long lastread_sds018=0; //to save last read time for both readings + + void readSDS018(); + + void loop_pm25(); + void loop_pm10(); + void readSDS018(); + +public: + Sensor_SDS018(int prx, int ptx); + + void init(); + void setSettings_pm10(float minchange, unsigned long senddelaymax, unsigned long readdelay); + void setSettings_pm25(float minchange, unsigned long senddelaymax, unsigned long readdelay); + void advertise(HomieNode& p_sensorNode); + void sensorloop(); + + bool mhz19calibrationHandler(const HomieRange& range, const String& value); + +}; + +#endif + diff --git a/platformio.ini b/platformio.ini index 927668f..6fbff6a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -151,10 +151,10 @@ build_flags = -D SENSOR_MHZ19B_readdelay=10*1000 -D SENSOR_SDS018 - -D SDS018_SERIAL_RX=D7 - -D SDS018_SERIAL_TX=D8 - -D dataSDS018_pm25_minchange=4 - -D dataSDS018_pm10_minchange=4 + -D SENSOR_SDS018_SERIAL_RX=D7 + -D SENSOR_SDS018_SERIAL_TX=D8 + -D SENSOR_SDS018_PM10_minchange=4 + -D SENSOR_SDS018_PM25_minchange=4 lib_deps = klevytskyi/MHZ19@0.0.1 diff --git a/src/main.cpp b/src/main.cpp index be633d2..7b22426 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -205,29 +205,26 @@ #ifdef SENSOR_SDS018 - struct sensordata dataSDS018_pm25; - struct sensordata dataSDS018_pm10; - - // SDS018 example: https://github.com/crystaldust/sds018/blob/master/sds018.ino - - //SDS18 dust sensor for 2.5µm and 10µm - //Needs 5V - - bool sds018_dustok=false; - float value_pm25=-1; - float value_pm10=-1; - - #ifndef SOFTWARESERIAL_H - #include - #define SOFTWARESERIAL_H + #include "sensor_sds018.cpp" + Sensor_SDS018 sensor_sds018(SENSOR_SDS018_SERIAL_RX,SENSOR_SDS018_SERIAL_TX); + #ifndef SENSOR_SDS018_PM10_minchange + #define SENSOR_SDS018_PM10_minchange 10.0 + #endif + #ifndef SENSOR_SDS018_PM10_senddelaymax + #define SENSOR_SDS018_PM10_senddelaymax 1000*60*5 + #endif + #ifndef SENSOR_SDS018_PM10_readdelay + #define SENSOR_SDS018_PM10_readdelay 1000*10 + #endif + #ifndef SENSOR_SDS018_PM25_minchange + #define SENSOR_SDS018_PM25_minchange 10.0 + #endif + #ifndef SENSOR_SDS018_PM25_senddelaymax + #define SENSOR_SDS018_PM25_senddelaymax 1000*60*5 + #endif + #ifndef SENSOR_SDS018_PM25_readdelay + #define SENSOR_SDS018_PM25_readdelay 1000*10 #endif - - SoftwareSerial sds018_swSerial; - #define BAUD_RATE_SDS018 9600 - - unsigned long lastread_sds018=0; //to save last read time for both readings - - void readSDS018(); #endif #ifdef SENSOR_TCS34725 @@ -384,14 +381,9 @@ void setup() { #ifdef SENSOR_SDS018 - Serial.println("initializing sds018"); - sds018_swSerial.begin(BAUD_RATE_SDS018, SWSERIAL_8N1, SDS018_SERIAL_RX, SDS018_SERIAL_TX, false, 256); - #ifdef dataSDS018_pm25_minchange - dataSDS018_pm25.minchange=dataSDS018_pm25_minchange; - #endif - #ifdef dataSDS018_pm10_minchange - dataSDS018_pm10.minchange=dataSDS018_pm10_minchange; - #endif + sensor_sds018.init(); + sensor_sds018.setSettings_pm10(SENSOR_SDS018_PM10_minchange,SENSOR_SDS018_PM10_senddelaymax,SENSOR_SDS018_PM10_readdelay); + sensor_sds018.setSettings_pm25(SENSOR_SDS018_PM25_minchange,SENSOR_SDS018_PM25_senddelaymax,SENSOR_SDS018_PM25_readdelay); #endif #ifdef SENSOR_TCS34725 @@ -516,8 +508,7 @@ void setup() { #endif #ifdef SENSOR_SDS018 - sensorNode.advertise("dust_pm25"); - sensorNode.advertise("dust_pm10"); + sensor_sds018.advertise(sensorNode); #endif #ifdef SENSOR_TCS34725 @@ -555,75 +546,6 @@ void loop() { Homie.loop(); } -#ifdef SENSOR_SDS018 -void loop_SDS018_pm25() -{ - sensordata &d=dataSDS018_pm25; - - bool _changed=false; - if (millis() >= (d.lastreadtime+d.readdelay)) { - if (millis() >= (lastread_sds018+d.readdelay)) { - readSDS018(); //reads values into value_pm25 und value_pm10 - } - //Homie.getLogger() << "read pm25: " << value_pm25 << ".read pm10: " << value_pm10 << " status=" << dust_ok << endl; - if (fabs(d.lastsentvalue-value_pm25)>=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"); - checkESPStatus(); - - Homie.getLogger() << "read pm25: " << value_pm25 << " status=" << sds018_dustok << endl; - if (sds018_dustok){ //send no dust values if sensor not ok - sensorNode.setProperty("dust_pm25").send(String(value_pm25)); - }else{ - Homie.getLogger() << "sds018 dust not ok. didnt sent" << endl; - } - - d.lastsentvalue=value_pm25; - - d.lastsent=millis(); - } -} -void loop_SDS018_pm10() -{ - sensordata &d=dataSDS018_pm10; - - bool _changed=false; - if (millis() >= (d.lastreadtime+d.readdelay)) { - if (millis() >= (lastread_sds018+d.readdelay)) { - readSDS018(); //reads values into value_pm25 und value_pm10 - } - //Homie.getLogger() << "read pm25: " << value_pm25 << ".read pm10: " << value_pm10 << " status=" << dust_ok << endl; - if (fabs(d.lastsentvalue-value_pm10)>=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"); - checkESPStatus(); - - Homie.getLogger() << "read pm10: " << value_pm10 << " status=" << sds018_dustok << endl; - if (sds018_dustok){ //send no dust values if sensor not ok - sensorNode.setProperty("dust_pm10").send(String(value_pm10)); - }else{ - Homie.getLogger() << "sds018 dust not ok. didnt sent" << endl; - } - - d.lastsentvalue=value_pm10; - - d.lastsent=millis(); - } -} -#endif - #ifdef SENSOR_TCS34725 void loop_TCS34725_lux() { @@ -952,52 +874,6 @@ void checkESPStatus() } -#ifdef SENSOR_SDS018 -void 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]; - - value_pm25 = ( ( pm25High * 256.0 ) + pm25Low ) / 10.0; - value_pm10 = ( ( pm10High * 256.0 ) + pm10Low ) / 10.0; - - sds018_dustok=true; - - /*Serial.print( "PM2.5: " ); - Serial.print( pm25 ); - Serial.print( "\nPM10 :" ); - Serial.print( pm10 ); - Serial.println();*/ - } - } - - sds018_swSerial.flush(); - } -} -#endif - #ifdef SENSOR_ANEMOMETER