From 658b90d193f61805b9001fa249b420073d17c957 Mon Sep 17 00:00:00 2001 From: Antonio Vanegas Date: Wed, 26 May 2021 22:27:09 +0200 Subject: [PATCH] added SPS30 via i2c support and some method refactors --- src/Sensors.cpp | 119 +++++++++++++++++++++++++++++++++--------------- src/Sensors.hpp | 15 +++--- 2 files changed, 90 insertions(+), 44 deletions(-) diff --git a/src/Sensors.cpp b/src/Sensors.cpp index 3ec21612..bf1c358e 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -63,8 +63,10 @@ void Sensors::init(int pms_type, int pms_rx, int pms_tx) { #ifdef M5COREINK Wire.begin(25,26); // M5CoreInk hat pines (header on top) #endif + Wire.begin(); - DEBUG("-->[SENSORS] try to load temp and humidity sensor.."); + DEBUG("-->[SENSORS] try to load I2C sensor.."); + sps30I2CInit(); am2320Init(); sht31Init(); bme280Init(); @@ -204,7 +206,7 @@ int Sensors::getPmDeviceTypeSelected() { } /****************************************************************************** -* S E N S O R P R I V A T E M E T H O D S +* U A R T S E N S O R P R I V A T E M E T H O D S ******************************************************************************/ /** @@ -220,11 +222,11 @@ bool Sensors::pmGenericRead() { pm25 = txtMsg[6] * 256 + byte(txtMsg[7]); pm10 = txtMsg[8] * 256 + byte(txtMsg[9]); if (pm25 > 1000 && pm10 > 1000) { - onPmSensorError("-->[E][PMSENSOR] out of range pm25 > 1000"); + onSensorError("-->[E][PMSENSOR] out of range pm25 > 1000"); } else return true; } else { - onPmSensorError("-->[E][PMSENSOR] invalid Generic sensor header!"); + onSensorError("-->[E][PMSENSOR] invalid Generic sensor header!"); } } return false; @@ -243,11 +245,11 @@ bool Sensors::pmPanasonicRead() { pm25 = txtMsg[6] * 256 + byte(txtMsg[5]); pm10 = txtMsg[10] * 256 + byte(txtMsg[9]); if (pm25 > 2000 && pm10 > 2000) { - onPmSensorError("-->[E][PMSENSOR] out of range pm25 > 2000"); + onSensorError("-->[E][PMSENSOR] out of range pm25 > 2000"); } else return true; } else { - onPmSensorError("-->[E][PMSENSOR] invalid Panasonic sensor header!"); + onSensorError("-->[E][PMSENSOR] invalid Panasonic sensor header!"); } return false; } @@ -265,11 +267,11 @@ bool Sensors::pmSDS011Read() { pm25 = (txtMsg[3] * 256 + byte(txtMsg[2])) / 10; pm10 = (txtMsg[5] * 256 + byte(txtMsg[4])) / 10; if (pm25 > 1000 && pm10 > 1000) { - onPmSensorError("-->[E][PMSENSOR] out of range pm25 > 1000"); + onSensorError("-->[E][PMSENSOR] out of range pm25 > 1000"); } else return true; } else { - onPmSensorError("-->[E][PMSENSOR] invalid Generic sensor header!"); + onSensorError("-->[E][PMSENSOR] invalid Generic sensor header!"); } } return false; @@ -291,7 +293,7 @@ String Sensors::hwSerialRead(unsigned int lenght_buffer) { } } if (try_sensor_read > SENSOR_RETRY) { - onPmSensorError("-->[E][PMSENSOR] sensor read fail!"); + onSensorError("-->[E][PMSENSOR] sensor read fail!"); } return txtMsg; } @@ -300,7 +302,7 @@ String Sensors::hwSerialRead(unsigned int lenght_buffer) { * @brief Sensirion SPS30 particulate meter sensor read. * @return true if reads succes */ -bool Sensors::pmSensirionRead() { +bool Sensors::sps30Read() { uint8_t ret, error_cnt = 0; delay(35); //Delay for sincronization do { @@ -312,7 +314,7 @@ bool Sensors::pmSensirionRead() { } delay(1000); } else if (ret != ERR_OK) { - pmSensirionErrtoMess((char *)"-->[W][SPS30] Error during reading values: ", ret); + sps30ErrToMess((char *)"-->[W][SPS30] Error during reading values: ", ret); return false; } } while (ret != ERR_OK); @@ -325,7 +327,7 @@ bool Sensors::pmSensirionRead() { pm10 = round(val.MassPM10); if (pm25 > 1000 && pm10 > 1000) { - onPmSensorError("-->[E][SPS30] Sensirion out of range pm25 > 1000"); + onSensorError("-->[E][SPS30] Sensirion out of range pm25 > 1000"); return false; } @@ -368,7 +370,7 @@ bool Sensors::pmSensorRead() { break; case Sensirion: - return pmSensirionRead(); + return sps30Read(); break; case SDS011: @@ -389,6 +391,10 @@ bool Sensors::pmSensorRead() { } } +/****************************************************************************** +* I 2 C S E N S O R R E A D M E T H O D S +******************************************************************************/ + void Sensors::am2320Read() { float humi1 = am2320.readHumidity(); float temp1 = am2320.readTemperature(); @@ -490,20 +496,20 @@ void Sensors::dhtRead() { } } -void Sensors::onPmSensorError(const char *msg) { +void Sensors::onSensorError(const char *msg) { DEBUG(msg); if (_onErrorCb) _onErrorCb(msg); } -void Sensors::pmSensirionErrtoMess(char *mess, uint8_t r) { +void Sensors::sps30ErrToMess(char *mess, uint8_t r) { char buf[80]; sps30.GetErrDescription(r, buf, 80); DEBUG("-->[E][SENSIRION]", buf); } -void Sensors::pmSensirionErrorloop(char *mess, uint8_t r) { +void Sensors::sps30Errorloop(char *mess, uint8_t r) { if (r) - pmSensirionErrtoMess(mess, r); + sps30ErrToMess(mess, r); else DEBUG(mess); } @@ -566,7 +572,7 @@ bool Sensors::pmSensorAutoDetect(int pms_type) { delay(1000); // sync serial if (pms_type == Sensirion) { - if (pmSensirionInit()) { + if (sps30UARTInit()) { device_selected = "SENSIRION"; device_type = Sensirion; return true; @@ -673,43 +679,89 @@ bool Sensors::CO2CM1106Init() { return true; } -bool Sensors::pmSensirionInit() { +bool Sensors::sps30UARTInit() { // Begin communication channel - DEBUG("-->[SPS30] starting SPS30 sensor.."); - if (!devmode) sps30.EnableDebugging(0); + DEBUG("-->[SPS30] starting SPS30 (UART) sensor.."); + + // set driver debug level + sps30.EnableDebugging(devmode); // Begin communication channel; if (!sps30.begin(SENSOR_COMMS)) { - pmSensirionErrorloop((char *)"-->[E][SPS30] could not initialize communication channel.", 0); + sps30Errorloop((char *)"-->[E][SPS30] could not initialize communication channel.", 0); return false; } // check for SPS30 connection - if (!sps30.probe()) - pmSensirionErrorloop((char *)"-->[E][SPS30] could not probe / connect with SPS30.", 0); + if (!sps30.probe()) { + sps30Errorloop((char *)"-->[E][SPS30] could not probe with SPS30.", 0); + return false; + } else { - DEBUG("-->[SPS30] Detected SPS30."); - pmSensirionDeviceInfo(); + DEBUG("-->[SPS30] Detected SPS30 via UART."); + sps30DeviceInfo(); } // reset SPS30 connection if (!sps30.reset()) - pmSensirionErrorloop((char *)"-->[E][SPS30] could not reset.", 0); + sps30Errorloop((char *)"-->[E][SPS30] could not reset.", 0); // start measurement if (sps30.start() == true) { DEBUG("-->[SPS30] Measurement OK"); return true; } else - pmSensirionErrorloop((char *)"-->[E][SPS30] Could NOT start measurement", 0); + sps30Errorloop((char *)"-->[E][SPS30] Could NOT start measurement", 0); + + return false; +} + +bool Sensors::sps30I2CInit() { + if (device_type == Sensirion) return false; + + DEBUG("-->[SPS30] starting SPS30 (I2C) sensor.."); + + // set driver debug level + sps30.EnableDebugging(devmode); + // Begin communication channel; + if (sps30.begin(&Wire) == false) { + sps30Errorloop((char *)"-->[E][SPS30] Could not set I2C communication channel.", 0); + return false; + } + + // check for SPS30 connection + if (!sps30.probe()) { + sps30Errorloop((char *)"-->[E][SPS30] Could not probe with SPS30.", 0); + return false; + } + else { + DEBUG("-->[SPS30] Detected SPS30 via I2C."); + sps30DeviceInfo(); + } + + // reset SPS30 connection + if (!sps30.reset()) + sps30Errorloop((char *)"-->[E][SPS30] could not reset.", 0); + - if (SENSOR_COMMS == I2C_COMMS) { + // start measurement + if (sps30.start()) { + delay(100); + sps30Read(); + DEBUG("-->[SPS30] Measurement OK"); + device_selected = "SENSIRION"; + device_type = Sensirion; if (sps30.I2C_expect() == 4) DEBUG("-->[E][SPS30] Due to I2C buffersize only PM values \n"); + return true; } + else + sps30Errorloop((char *)"-->[E][SPS30] Could NOT start measurement.", 0); + return false; } + /** * @brief : read and display Sensirion device info */ -void Sensors::pmSensirionDeviceInfo() { +void Sensors::sps30DeviceInfo() { char buf[32]; uint8_t ret; SPS30_version v; @@ -773,13 +825,6 @@ void Sensors::bme280Init() { void Sensors::bme680Init() { DEBUG("-->[BME280] starting BME680 sensor.."); if (!bme680.begin()) return; - - // Set up oversampling and filter in// There's no need to delay() until millis() >= endTime: bme.endReading() - // takes care of that. It's okay for parallel work to take longer than - // BME680's measurement time. - - // Obtain measurement results from BME680. Note that this operation isn't - // instantaneous even if milli() >= endTime due to I2C/SPI latency.itialization bme680.setTemperatureOversampling(BME680_OS_8X); bme680.setHumidityOversampling(BME680_OS_2X); bme680.setPressureOversampling(BME680_OS_4X); diff --git a/src/Sensors.hpp b/src/Sensors.hpp index 5785f9b0..5260fe32 100644 --- a/src/Sensors.hpp +++ b/src/Sensors.hpp @@ -215,13 +215,14 @@ class Sensors { bool CO2Mhz19Init(); bool CO2CM1106Init(); - bool pmSensirionInit(); - bool pmSensirionRead(); - void pmSensirionErrtoMess(char *mess, uint8_t r); - void pmSensirionErrorloop(char *mess, uint8_t r); - void pmSensirionDeviceInfo(); - - void onPmSensorError(const char *msg); + bool sps30I2CInit(); + bool sps30UARTInit(); + bool sps30Read(); + void sps30ErrToMess(char *mess, uint8_t r); + void sps30Errorloop(char *mess, uint8_t r); + void sps30DeviceInfo(); + + void onSensorError(const char *msg); bool serialInit(int pms_type, long speed_baud, int pms_rx, int pms_tx); String hwSerialRead(unsigned int lenght_buffer);