diff --git a/README.md b/README.md index b73607b2..5750fe60 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # Air Quality Sensors Library -Generic sensor manager, abstractions and bindings of multiple sensors [libraries](https://github.com/kike-canaries/canairio_sensorlib/blob/master/platformio.ini#L18-L34): Honeywell, Plantower, Panasonic, Sensirion, etc. and CO2 sensors. Also it's handling others environment sensors. This library is for general purpose, but also is the sensors library base of [CanAirIO project](https://canair.io/docs). +Generic sensor manager, abstractions and bindings of multiple sensors [libraries](https://github.com/kike-canaries/canairio_sensorlib/blob/master/unified-lib-deps.ini): Honeywell, Plantower, Panasonic, Sensirion, etc. and CO2 sensors. Also it's handling others environment sensors. This library is for general purpose, but also is the sensors library base of [CanAirIO project](https://canair.io/docs). For developers also you can check the complete library documentation [here](http://hpsaturn.com/canairio_sensorlib_doc/html/index.html) @@ -25,7 +25,7 @@ For developers also you can check the complete library documentation [here](http | Panasonic SN-GCJA5L | Yes | Yes | Auto | STABLE | | Plantower models | Yes | --- | Auto | STABLE | | Nova SDS011 | Yes | --- | Auto | STABLE | -| IKEA Vindriktning | Yes | --- | Select | TESTING| +| IKEA Vindriktning | Yes | --- | Select | STABLE | | Sensirion SPS30 | Yes | Yes | Select / Auto | STABLE | NOTE: Panasonic via UART in ESP8266 maybe needs select in detection @@ -49,8 +49,10 @@ NOTE: Panasonic via UART in ESP8266 maybe needs select in detection | SHT31 | i2c | Auto | STABLE | | AHT10 | i2c | Auto | STABLE | | BME280 | i2c | Auto | STABLE | -| BMP280 | i2c | Auto | TESTING | +| BMP280 | i2c | Auto | STABLE | | BME680 | i2c | Auto | STABLE | +| DfRobot SEN0469 NH3 | i2c | Auto | TESTING | +| DFRobot SEN0466 CO | i2c | Auto | TESTING | | DHTxx | TwoWire | Auto | DISABLED | NOTE: DHT22 is supported but is not recommended. Please see the documentation. @@ -60,8 +62,8 @@ NOTE: DHT22 is supported but is not recommended. Please see the documentation. | Platform | Variants | Notes | Status | |:----------------------- |:-----:|:-------:|:----------:| | ESP32 | WROVER* | ESP32Devkit and similar (recommended) | STABLE | -| ESP32S3 | LilyGo TDisplay | In testing | UNSTABLE | -| ESP32C3 | Devkit v3 | In testing | UNSTABLE | +| ESP32S3 | LilyGo TDisplay | In testing | STABLE | +| ESP32C3 | Devkit v3 | In testing | STABLE | | ESP8266 | 12 | D1MINI tested and similar (old) | STABLE | | Atmelsam | seeed_wio_terminal | Only works via i2c on left port | STABLE | | Arduino | Atmel | Some third party libraries fails | IN PROGRESS | @@ -72,9 +74,9 @@ NOTE: DHT22 is supported but is not recommended. Please see the documentation. - Unified variables and getters for all sensors - Auto UART port selection (Hw, Sw, UART1, UART2, etc) -- Multiple i2c reads and one UART sensor read support +- Multiple i2c sensors and one UART sensor supported at the same time - Two I2C channel supported (Wire and Wire1) -- Real time registry of sensors unit registered (see multivariable) +- Real time registry of sensor units (see multivariable) - Get vendor names of all devices detected - Preselected main stream UART pins from popular boards - Auto config UART port for Plantower, Honeywell and Panasonic sensors @@ -85,9 +87,8 @@ NOTE: DHT22 is supported but is not recommended. Please see the documentation. - Get unit symbol and name and each sub-sensor - Get the main group type: NONE, PM, CO2 and ENV. - Basic debug mode support toggle in execution -- Basic power saving management with sample time > 30s on SPS30 -Full list of all sub libraries supported [here](https://github.com/kike-canaries/canairio_sensorlib/blob/master/library.json#L72-L89) +Full list of all sub libraries supported [here](https://github.com/kike-canaries/canairio_sensorlib/blob/master/unified-lib-deps.ini) # Quick implementation @@ -170,7 +171,6 @@ In this [demo](https://www.youtube.com/watch?v=uxlmP905-FE) on a simple sketch y [![CanAirIO Sensors Lib DEMO with M5CoreInk](https://img.youtube.com/vi/i15iEF47CbY/0.jpg)](https://youtu.be/i15iEF47CbY) - ## Multivariable alternative implementation The last version added new getters to have the current status of each unit of each sensor connected to the device in real time. Also you can retrieve the list of device names and other stuff: @@ -231,16 +231,14 @@ void setup() { void loop() { sensors.loop(); // read sensor data and showed it } -``` - +``` -## UART detection demo +## UART detection demo [![CanAirIO auto configuration demo](https://img.youtube.com/vi/hmukAmG5Eec/0.jpg)](https://www.youtube.com/watch?v=hmukAmG5Eec) CanAirIO sensorlib auto configuration demo on [Youtube](https://www.youtube.com/watch?v=hmukAmG5Eec) - # Wiring The current version of library supports 3 kinds of wiring connection, UART, i2c and TwoWire, in the main boards the library using the defaults pins of each board, but in some special cases the pins are: @@ -251,20 +249,20 @@ The current version of library supports 3 kinds of wiring connection, UART, i2c The library has [pre-defined some UART pin configs](https://github.com/kike-canaries/canairio_sensorlib/blob/master/src/Sensors.hpp#L19-L52), these are selected on compiling time. Maybe you don't need change anything with your board, and maybe the nexts alternatives works for you: -| Board model | TX | RX | Notes +| Board model | TX | RX | Notes | |:---------------|:---:|:---:|:------------------:| | ESP32GENERIC | 1 | 3 | ESP32 Pio defaults | TTGOT7 / ESP32DEVKIT / D1MINI / NODEFINED | 16 | 17 | CanAirIO devices ** | TTGO_TDISPLAY | 12 | 13 | | | M5COREINK | 14 | 13 | | | TTGO TQ | 18 | 13 | | -| HELTEC | 18 | 17 | | +| HELTEC | 18 | 17 | | | WEMOSOLED | 15 | 13 | | | ESP32PICOD4 | 3 | 1 | | ** This pines are when you compile your project without specific any build variable or you board isn't in the list. -### Custom UART: +### Custom UART Also you could define a custom UART pins in the init() method and select specific sensors model, like this: @@ -280,27 +278,22 @@ We are using the default pins for each board, some times it's pins are 21,22, pl For now we are using it only for DHT sensors in PIN 23. For more info please review the next lines [here](https://github.com/kike-canaries/canairio_sensorlib/blob/master/src/Sensors.hpp#L19-L52). - # Examples ### PlatformIO (recommended) -#### Compiling and Installing - We recommended PlatformIO because is more easy than Arduino IDE. For this, please install first [PlatformIO](http://platformio.org/) and its command line tools (Windows, MacOs and Linux), **pio** command, then connect your compatible board to the USB and run the next command: ```python -pio run --target upload +pio run -e esp32 --target upload ``` ### Arduino IDE -Only import the `ino` file of the sample and install the libraries listed on `library.json` and this library. +Only import the `ino` file of the sample and install the libraries listed on `library.json` and this library. Complete list of libraries used [here](https://github.com/kike-canaries/canairio_sensorlib/blob/master/unified-lib-deps.ini) ### Arduino CLI -#### Prerequisites - For run the examples, you first need to install **arduino-cli** or the **Arduino IDE** with the libraries referenced in **lib_deps** on the file [platformio.ini](https://github.com/kike-canaries/canairio_sensorlib/blob/master/platformio.ini), becuase **Arduino don't install it automatically** like PlatformIO. Then put CanAirIO sensor library in your library directory, you can download it from [releases](https://github.com/kike-canaries/canairio_sensorlib/releases) section. Also you need to add the **alternative links** for supporting the ESP32 boards: @@ -316,9 +309,7 @@ board_manager: additional_urls: - https://arduino.esp8266.com/stable/package_esp8266com_index.json - https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json -``` - -#### Compiling and Installing +``` From `arduino-cli` you can run the basic example in a ESP32 board following these steps: @@ -352,7 +343,6 @@ Also you can make a donation, be a patreon or buy a device: - **Buy a device**: [CanAirIO Bike in Tindie](https://www.tindie.com/products/hpsaturn/canairio-bike/) - [Inviting us **a coffee**](https://www.buymeacoffee.com/hpsaturn) - # TODO - [x] Auto detection for UART sensors (Honeywell, Panasonic and Plantower) @@ -370,6 +360,7 @@ Also you can make a donation, be a patreon or buy a device: - [x] SenseAir S8 via UART support - [x] Multivariable selection (getNextUnit(),getUnitName(),etc) - [x] Two I2C channel supported for M5Stack Devices (M5StickC tested) +- [x] Added CO and NH3 sensors - [ ] Sea level setting for Pressure sensors and others - [ ] Support to second UART port diff --git a/examples/DfRobot_Multigas/dfr_multigas.ino b/examples/DfRobot_Multigas/dfr_multigas.ino new file mode 100644 index 00000000..f114af85 --- /dev/null +++ b/examples/DfRobot_Multigas/dfr_multigas.ino @@ -0,0 +1,55 @@ +/** + * @file main.cpp + * @date June 2018 - 2021 + * @brief Particle meter sensor tests + * @license GPL3 + * + * Full documentation: + * https://github.com/kike-canaries/canairio_sensorlib#canairio-air-quality-sensors-library + * + * Full implementation for WiFi and Bluetooth Air Quality fixed and mobile station: + * https://github.com/kike-canaries/canairio_firmware#canairio-firmware + * + * CanAirIO project: + * https://canair.io + */ + +#include + +#include + +void onSensorDataOk() { + Serial.println("-->[MAIN] NH3: " + String(sensors.getNH3())); + Serial.println("-->[MAIN] CO: " + String(sensors.getCO())); +} + +void onSensorDataError(const char* msg) { + Serial.println(msg); +} + +/****************************************************************************** +* M A I N +******************************************************************************/ + +void setup() { + Serial.begin(115200); + delay(200); + Serial.println("\n== Sensor test setup ==\n"); + + Serial.println("-->[SETUP] Detecting sensors.."); + + sensors.setSampleTime(5); // config sensors sample time interval + sensors.setOnDataCallBack(&onSensorDataOk); // all data read callback + sensors.setOnErrorCallBack(&onSensorDataError); // [optional] error callback + sensors.setDebugMode(false); // [optional] debug mode + sensors.detectI2COnly(true); // force to only i2c sensors + + sensors.init(SENSORS::SDFRCO); // detect CO sensor + sensors.init(SENSORS::SDFRNH3); // detect NH3 sensor + + delay(500); +} + +void loop() { + sensors.loop(); // read sensor data and showed it +} \ No newline at end of file diff --git a/library.json b/library.json index 16040a14..ddd0ec80 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "CanAirIO Air Quality Sensors Library", - "version": "0.6.7", + "version": "0.6.8", "homepage":"https://canair.io", "keywords": [ @@ -88,6 +88,7 @@ {"name":"S8_UART", "owner":"jcomas", "version":"1.0.1"}, {"name":"Sensirion Core","owner":"sensirion","version":"0.6.0"}, {"name":"Sensirion I2C SCD4x","owner":"sensirion","version":"0.4.0"}, + {"name":"DFRobot_MultiGasSensor","owner":"phzi","version":"2.0.0"}, {"name":"DHT_nonblocking", "version":"https://github.com/hpsaturn/DHT_nonblocking.git#ec6e5b9"}, {"name":"AHTxx", "version":"https://github.com/enjoyneering/AHTxx.git#eb21571"}, diff --git a/library.properties b/library.properties index e25d9fe7..ae26f78e 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ name=CanAirIO Air Quality Sensors Library -version=0.6.7 +version=0.6.8 author=@hpsaturn, CanAirIO project maintainer=Antonio Vanegas url=https://github.com/kike-canaries/canairio_sensorlib sentence=Air quality particle meter and CO2 sensors manager for multiple models. paragraph=Generic sensor manager, abstratctions and bindings of multiple air sensors libraries: Honeywell, Plantower, Panasonic, Sensirion, Nova, etc. and CO2 sensors. Also it handling others environment sensors. This library is for general purpose but also is the sensors library base of CanAirIO project. category=sensors -depends=AM232X,Adafruit Unified Sensor,sps30,Adafruit BME280 Library,AHT10,Adafruit BusIO,Adafruit SHT31 Library,DHT_nonblocking,MH-Z19,SparkFun SCD30 Arduino Library,CM1106_UART,SN-GCJA5,Adafruit BME680 Library,S8_UART,Sensirion I2C SCD4x +depends=AM232X,Adafruit Unified Sensor,sps30,Adafruit BME280 Library,AHT10,Adafruit BusIO,Adafruit SHT31 Library,DHT_nonblocking,MH-Z19,SparkFun SCD30 Arduino Library,CM1106_UART,SN-GCJA5,Adafruit BME680 Library,S8_UART,Sensirion I2C SCD4x,DFRobot_MultiGasSensor license=GPL-3.0-only diff --git a/platformio.ini b/platformio.ini index b253b881..ae2152fc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,6 +15,7 @@ monitor_speed = 115200 monitor_filters = time build_flags = -D CORE_DEBUG_LEVEL=0 + -D ARDUINO_ESP32_DEV=1 ; -D DHT11_ENABLED=1 // Deprecated, please change this old sensor ; -D DHT_SENSOR_TYPE=2 ; -D DHT_SENSOR_PIN=19 @@ -55,7 +56,6 @@ extends = esp32_common build_src_filter = -<*> + build_flags = ${env.build_flags} - -D ESP32C3=1 [env:esp32c3] extends = esp32_common @@ -69,7 +69,6 @@ board = esp32-s3-devkitc-1 board_build.mcu = esp32s3 board_build.f_cpu = 240000000L build_src_filter = -<*> + -;platform_packages = framework-arduinoespressif32@https://github.com/espressif/arduino-esp32.git#2.0.3 build_flags = ${env.build_flags} -DBOARD_HAS_PSRAM diff --git a/src/Sensors.cpp b/src/Sensors.cpp index 4cfdb4fe..0b4aeedd 100644 --- a/src/Sensors.cpp +++ b/src/Sensors.cpp @@ -64,22 +64,23 @@ bool Sensors::readAllSensors() { dataReady = pmSensorRead(); DEBUG("-->[SLIB] UART data ready \t:", dataReady ? "true" : "false"); } - enableWire1(); + enableWire1(); CO2scd30Read(); GCJA5Read(); sps30Read(); CO2scd4xRead(); - am2320Read(); + am2320Read(); sht31Read(); bme280Read(); bmp280Read(); - bme680Read(); - aht10Read(); - + bme680Read(); + aht10Read(); + DFRobotCORead(); + DFRobotNH3Read(); #ifdef DHT11_ENABLED dhtRead(); #endif - + disableWire1(); printValues(); @@ -114,7 +115,8 @@ void Sensors::init(u_int pms_type, int pms_rx, int pms_tx) { if (!i2conly && !sensorSerialInit(pms_type, pms_rx, pms_tx)) { DEBUG("-->[SLIB] UART sensors detected\t:", "0"); } - startI2C(); + + startI2C(); CO2scd30Init(); sps30I2CInit(); GCJA5Init(); @@ -122,10 +124,12 @@ void Sensors::init(u_int pms_type, int pms_rx, int pms_tx) { bmp280Init(); bme280Init(); bme680Init(); - am2320Init(); - sht31Init(); - aht10Init(); - + am2320Init(); + sht31Init(); + aht10Init(); + DFRobotCOInit(); + DFRobotNH3Init(); + #ifdef DHT11_ENABLED dhtInit(); #endif @@ -320,6 +324,16 @@ float Sensors::getPressure() { return pres; } +float Sensors::getNH3() { + return nh3; +} + +float Sensors::getCO() { + return co; +} + + + /** * @brief UART only: check if the UART sensor is registered * @return bool true if the UART sensor is registered, false otherwise. @@ -536,7 +550,11 @@ float Sensors::getUnitValue(UNIT unit) { case ALT: return alt; case GAS: - return gas; + return gas; + case NH3: + return nh3; + case CO: + return co; default: return 0.0; } @@ -563,7 +581,7 @@ void Sensors::printUnitsRegistered(bool debug) { */ void Sensors::printSensorsRegistered(bool debug) { if (!debug) return; - Serial.printf("-->[SLIB] Sensors i2c count \t: %i (", sensors_registered_count); + Serial.printf("-->[SLIB] Sensors count \t: %i (", sensors_registered_count); int i = 0; while (sensors_registered[i++] != 0) { Serial.print(sensors_device_names[sensors_registered[i-1]]); @@ -970,6 +988,20 @@ void Sensors::GCJA5Read() { unitRegister(UNIT::PM10); } +void Sensors::DFRobotNH3Read() { + if (!dfrNH3.begin()) return; + nh3 = dfrNH3.readGasConcentrationPPM(); + unitRegister(UNIT::NH3); + +} + +void Sensors::DFRobotCORead() { + if (!dfrCO.begin()) return; + co = dfrCO.readGasConcentrationPPM(); + unitRegister(UNIT::CO); + +} + #ifdef DHT11_ENABLED DHT_nonblocking dht_sensor(DHT_SENSOR_PIN, DHT_SENSOR_TYPE); /** @@ -1546,6 +1578,28 @@ void Sensors::GCJA5Init() { sensorRegister(SENSORS::SGCJA5); } +void Sensors::DFRobotCOInit() { + sensorAnnounce(SENSORS::SDFRCO); + dfrCO = DFRobot_GAS_I2C(&Wire, 0x78); // Be sure that your group of i2c address is 7 + if (!dfrCO.begin()) return; + //Mode of obtaining data: the main controller needs to request the sensor for data + dfrCO.changeAcquireMode(dfrCO.PASSIVITY); + //Turn on temperature compensation: gas.ON : turn on + dfrNH3.setTempCompensation(dfrCO.ON); + sensorRegister(SENSORS::SDFRCO); +} + +void Sensors::DFRobotNH3Init() { + sensorAnnounce(SENSORS::SDFRNH3); + dfrNH3 = DFRobot_GAS_I2C(&Wire, 0x7A); // 0x77 y 0x75 used by bme680. Be sure that your group of i2c address is 7 + if (!dfrNH3.begin()) return; + //Mode of obtaining data: the main controller needs to request the sensor for data + dfrNH3.changeAcquireMode(dfrNH3.PASSIVITY); + //Turn on temperature compensation: gas.ON : turn on + dfrNH3.setTempCompensation(dfrNH3.ON); + sensorRegister(SENSORS::SDFRNH3); +} + // Altitude compensation for CO2 sensors without Pressure atm or Altitude compensation void Sensors::CO2correctionAlt() { @@ -1590,6 +1644,8 @@ void Sensors::resetAllVariables() { alt = 0.0; gas = 0.0; pres = 0.0; + nh3 = 0; + co = 0; } void Sensors::DEBUG(const char *text, const char *textb) { diff --git a/src/Sensors.hpp b/src/Sensors.hpp index e3665620..4d37ffe4 100644 --- a/src/Sensors.hpp +++ b/src/Sensors.hpp @@ -16,13 +16,14 @@ #include #include #include +#include #ifdef DHT11_ENABLED #include #endif -#define CSL_VERSION "0.6.7" -#define CSL_REVISION 374 +#define CSL_VERSION "0.6.8" +#define CSL_REVISION 375 /*************************************************************** * S E T U P E S P 3 2 B O A R D S A N D F I E L D S @@ -96,8 +97,11 @@ X(PRESS, "hPa", "P") \ X(ALT, "m", "Alt") \ X(GAS, "Ohm", "Gas") \ + X(NH3, "ppm", "NH3") \ + X(CO, "ppm", "CO") \ X(UCOUNT, "COUNT", "UCOUNT") + #define X(unit, symbol, name) unit, typedef enum UNIT : size_t { SENSOR_UNITS } UNIT; #undef X @@ -120,6 +124,8 @@ typedef enum UNIT : size_t { SENSOR_UNITS } UNIT; X(SAHTXX, "AHTXX", 3) \ X(SAM232X, "AM232X", 3) \ X(SDHTX, "DHTX", 3) \ + X(SDFRCO, "DFRCO", 3) \ + X(SDFRNH3, "DFRNH3", 3) \ X(SCOUNT, "SCOUNT", 3) #define X(utype, uname, umaintype) utype, @@ -144,7 +150,7 @@ class Sensors { bool devmode; // Initial sample time for all sensors - int sample_time = 5; + int sample_time = 10; // temperature offset (for final temp output) float toffset = 0.0; @@ -204,9 +210,15 @@ class Sensors { // SCD4x sensor SensirionI2CScd4x scd4x; - // IKA Vindriktn sensor + // IKEA Vindriktn sensor PM1006 *pm1006; + // DFRobot gravity NH3 sensor addr 0x74 + DFRobot_GAS_I2C dfrCO; + + // DFRobot gravity NH3 sensor addr 0x77 + DFRobot_GAS_I2C dfrNH3; + void init(u_int pms_type = 0, int pms_rx = PMS_RX, int pms_tx = PMS_TX); void loop(); @@ -250,13 +262,17 @@ class Sensors { float getAltitude(); float getGas(); + + float getNH3(); + + float getCO(); void setTempOffset(float offset); void setCO2AltitudeOffset(float altitude); void setSeaLevelPressure(float hpa); - + void setCO2RecalibrationFactor(int ppmValue); void detectI2COnly(bool enable); @@ -333,12 +349,15 @@ class Sensors { float temp = 0.0; // Temperature (°C) float pres = 0.0; // Pressure float alt = 0.0; - float gas = 0.0; - + float gas = 0.0; // + uint16_t CO2Val; // CO2 in ppm float CO2humi = 0.0; // humidity of CO2 sensor float CO2temp = 0.0; // temperature of CO2 sensor + float nh3; // Amonium in ppm + float co; // Carbon monoxide + void am2320Init(); void am2320Read(); @@ -378,6 +397,11 @@ class Sensors { bool dhtIsReady(float *temperature, float *humidity); #endif + void DFRobotNH3Init(); + void DFRobotNH3Read(); + void DFRobotCOInit(); + void DFRobotCORead(); + // UART sensors methods: bool sensorSerialInit(u_int pms_type, int rx, int tx); diff --git a/unified-lib-deps.ini b/unified-lib-deps.ini index 22aca273..e7028ccd 100644 --- a/unified-lib-deps.ini +++ b/unified-lib-deps.ini @@ -13,6 +13,7 @@ lib_deps = jcomas/S8_UART@1.0.1 sensirion/Sensirion Core@0.6.0 sensirion/Sensirion I2C SCD4x@0.4.0 + phzi/DFRobot_MultiGasSensor@2.0.0 https://github.com/enjoyneering/AHTxx.git#eb21571 https://github.com/hpsaturn/DHT_nonblocking.git#ec6e5b9 https://github.com/paulvha/SN-GCJA5.git#f261968