From d1285cb4934c589dd70c97f203286207d103480a Mon Sep 17 00:00:00 2001 From: tyeth Date: Fri, 4 Apr 2025 15:37:07 +0100 Subject: [PATCH 01/17] Remove final SPI Flash forked copy from CI --- .github/workflows/build-clang-doxy.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-clang-doxy.yml b/.github/workflows/build-clang-doxy.yml index 4d00deb85..a240e12de 100644 --- a/.github/workflows/build-clang-doxy.yml +++ b/.github/workflows/build-clang-doxy.yml @@ -523,7 +523,6 @@ jobs: run: | git clone --quiet https://github.com/pstolarz/OneWireNg.git /home/runner/Arduino/libraries/OneWireNg git clone --quiet https://github.com/pstolarz/Arduino-Temperature-Control-Library.git /home/runner/Arduino/libraries/Arduino-Temperature-Control-Library - git clone --quiet https://github.com/brentru/Adafruit_SPIFlash.git /home/runner/Arduino/libraries/Adafruit_SPIFlash git clone --quiet https://github.com/adafruit/Adafruit_TinyUSB_Arduino /home/runner/Arduino/libraries/Adafruit_TinyUSB_Arduino - name: Download stable Nanopb id: download-nanopb From b93f131dc0d09f23ab6b3b4ebe357381943f9869 Mon Sep 17 00:00:00 2001 From: tyeth Date: Fri, 4 Apr 2025 16:36:14 +0100 Subject: [PATCH 02/17] Closes #724 - Add SGP30 to offline mode --- src/components/i2c/controller.cpp | 5 ++ src/components/i2c/controller.h | 1 + src/components/i2c/drivers/drvSgp30.h | 104 ++++++++++++++++++++++++++ src/components/i2c/drivers/drvSgp40.h | 4 +- 4 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 src/components/i2c/drivers/drvSgp30.h diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 1eaf24238..08bf1705e 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -223,6 +223,11 @@ static const std::map I2cFactory = { const char *driver_name) -> drvBase * { return new drvScd30(i2c, addr, mux_channel, driver_name); }}, + {"sgp30", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvSgp30(i2c, addr, mux_channel, driver_name); + }}, {"sgp40", [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, const char *driver_name) -> drvBase * { diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index 04e4b4662..80396decc 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -50,6 +50,7 @@ #include "drivers/drvScd30.h" #include "drivers/drvScd4x.h" #include "drivers/drvSen5x.h" +#include "drivers/drvSgp30.h" #include "drivers/drvSgp40.h" #include "drivers/drvSht3x.h" #include "drivers/drvSht4x.h" diff --git a/src/components/i2c/drivers/drvSgp30.h b/src/components/i2c/drivers/drvSgp30.h new file mode 100644 index 000000000..a94f6f068 --- /dev/null +++ b/src/components/i2c/drivers/drvSgp30.h @@ -0,0 +1,104 @@ +/*! + * @file drvSgp30.h + * + * Device driver for the SGP30 VOC/gas sensor. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Tyeth Gundry 2025 for Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef DRV_SGP30_H +#define DRV_SGP30_H + +#include "drvBase.h" +#include +#include + +/**************************************************************************/ +/*! + @brief Class that provides a driver interface for the SGP30 sensor. +*/ +/**************************************************************************/ +class drvSgp30 : public drvBase { +public: + /*******************************************************************************/ + /*! + @brief Constructor for a SGP30 sensor. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + /*******************************************************************************/ + drvSgp30(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) { + // Initialization handled by drvBase constructor + } + + /*******************************************************************************/ + /*! + @brief Initializes the SGP30 sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + /*******************************************************************************/ + bool begin() override { + _sgp30 = new Adafruit_SGP30(); + if (!_sgp30->begin(_i2c)) { + return false; + } + + // TODO: update to use setCalibration() and pass in temp/humidity + + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the sensor's current equivalent/estimated CO2 value. + @param co2Event + Pointer to an Adafruit_Sensor event. + @returns True if the temperature was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventECO2(sensors_event_t *co2Event) { + bool result = _sgp30->IAQmeasure(); + if (result) { + co2Event->eCO2 = (float)_sgp30->eCO2; + } + return result; + } + + /*******************************************************************************/ + /*! + @brief Gets the SGP30's current VOC reading. + @param vocIndexEvent + Adafruit Sensor event for VOC Index (1-500, 100 is normal) + @returns True if the sensor value was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventVOCIndex(sensors_event_t *vocIndexEvent) { + bool result = _sgp30->IAQmeasure(); + if (result) { + vocIndexEvent->voc_index = (float)_sgp30->TVOC; + } + return result; + } + +protected: + Adafruit_SGP30 *_sgp30; ///< SGP30 driver object +}; + +#endif // WipperSnapper_I2C_Driver_SGP30 diff --git a/src/components/i2c/drivers/drvSgp40.h b/src/components/i2c/drivers/drvSgp40.h index 3cf7fcdca..2255b3a39 100644 --- a/src/components/i2c/drivers/drvSgp40.h +++ b/src/components/i2c/drivers/drvSgp40.h @@ -99,7 +99,7 @@ class drvSgp40 : public drvBase { } protected: - Adafruit_SGP40 *_sgp40; ///< SEN5X driver object + Adafruit_SGP40 *_sgp40; ///< SGP40 driver object }; -#endif // WipperSnapper_I2C_Driver_SEN5X +#endif // WipperSnapper_I2C_Driver_SGP40 From aec73718bf80a8a361f85eeff1ea6536c329240a Mon Sep 17 00:00:00 2001 From: Tyeth Gundry Date: Fri, 25 Apr 2025 01:59:36 +0100 Subject: [PATCH 03/17] Adds HTU31D Closes #721 --- src/components/i2c/controller.cpp | 5 ++ src/components/i2c/controller.h | 1 + src/components/i2c/drivers/drvHtu31d.h | 90 ++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 src/components/i2c/drivers/drvHtu31d.h diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 08bf1705e..033762690 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -123,6 +123,11 @@ static const std::map I2cFactory = { const char *driver_name) -> drvBase * { return new drvHtu21d(i2c, addr, mux_channel, driver_name); }}, + {"htu31d", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvHtu31d(i2c, addr, mux_channel, driver_name); + }}, {"ina219", [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, const char *driver_name) -> drvBase * { diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index 80396decc..20350c0b1 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -30,6 +30,7 @@ #include "drivers/drvDs2484.h" #include "drivers/drvEns160.h" #include "drivers/drvHts221.h" +#include "drivers/drvHtu31d.h" #include "drivers/drvHtu21d.h" #include "drivers/drvIna219.h" #include "drivers/drvLc709203f.h" diff --git a/src/components/i2c/drivers/drvHtu31d.h b/src/components/i2c/drivers/drvHtu31d.h new file mode 100644 index 000000000..efda5f232 --- /dev/null +++ b/src/components/i2c/drivers/drvHtu31d.h @@ -0,0 +1,90 @@ +/*! + * @file drvHtu31d.h + * + * Device driver for an HTU31D Humidity and Temperature sensor. + */ + +#ifndef DRV_HTU31D_H +#define DRV_HTU31D_H + +#include "drvBase.h" +#include + +/**************************************************************************/ +/*! + @brief Class that provides a sensor driver for the HTU31D humidity and + temperature sensor. +*/ +/**************************************************************************/ +class drvHtu31d : public drvBase { + +public: + /*******************************************************************************/ + /*! + @brief Constructor for an HTU31D sensor. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + /*******************************************************************************/ + drvHtu31d(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) { + // Initialization handled by drvBase constructor + } + + /*******************************************************************************/ + /*! + @brief Destructor for an HTU31D sensor. + */ + /*******************************************************************************/ + ~drvHtu31d() { delete _htu31d; } + + /*******************************************************************************/ + /*! + @brief Initializes the HTU31D sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + + */ + /*******************************************************************************/ + bool begin() { + // attempt to initialize the HTU31D using the I2C interface + _htu31d = new Adafruit_HTU31D(); + return _htu31d->begin(_address, _i2c); + } + + /*******************************************************************************/ + /*! + @brief Gets the HTU31D's current temperature. + @param tempEvent + Pointer to an Adafruit_Sensor event. + @returns True if the temperature was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventAmbientTemp(sensors_event_t *tempEvent) { + return _htu31d->getEvent(nullptr, tempEvent); + } + + /*******************************************************************************/ + /*! + @brief Gets the HTU31D's current humidity. + @param humidEvent + Pointer to an Adafruit_Sensor event. + @returns True if the humidity was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventRelativeHumidity(sensors_event_t *humidEvent) { + return _htu31d->getEvent(humidEvent, nullptr); + } + +protected: + Adafruit_HTU31D *_htu31d; ///< Pointer to an HTU31D object +}; +#endif // DRV_HTU31D_H \ No newline at end of file From 57a0b8916d3d3b34f266915993bf47a2fbff8d0a Mon Sep 17 00:00:00 2001 From: Tyeth Gundry Date: Fri, 25 Apr 2025 01:59:57 +0100 Subject: [PATCH 04/17] BSP 3.20 --- platformio.ini | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index 6e3048d18..592b697ee 100644 --- a/platformio.ini +++ b/platformio.ini @@ -84,9 +84,7 @@ lib_deps = ; Common build environment for ESP32 platform [common:esp32] -; platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip -; platform = https://github.com/pioarduino/platform-espressif32#develop -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20/platform-espressif32.zip lib_ignore = WiFiNINA, WiFi101 monitor_filters = esp32_exception_decoder, time ; upload_speed = 921600 From 19b58a8d84e0d8c50e0b92a1e77d913be450bef1 Mon Sep 17 00:00:00 2001 From: tyeth Date: Tue, 29 Apr 2025 16:13:17 +0100 Subject: [PATCH 05/17] Add HDC302x --- platformio.ini | 1 + src/components/i2c/controller.cpp | 5 + src/components/i2c/controller.h | 1 + src/components/i2c/drivers/drvHdc302x.h | 133 ++++++++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 src/components/i2c/drivers/drvHdc302x.h diff --git a/platformio.ini b/platformio.ini index 592b697ee..90e742fe1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,6 +34,7 @@ lib_deps = adafruit/Adafruit HTS221 adafruit/Adafruit HTU21DF Library adafruit/Adafruit HTU31D Library + adafruit/Adafruit HDC302x adafruit/Adafruit LTR390 Library adafruit/Adafruit LTR329 and LTR303 adafruit/Adafruit PCT2075 diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 033762690..4204cf184 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -128,6 +128,11 @@ static const std::map I2cFactory = { const char *driver_name) -> drvBase * { return new drvHtu31d(i2c, addr, mux_channel, driver_name); }}, + {"hdc302x", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvHdc302x(i2c, addr, mux_channel, driver_name); + }}, {"ina219", [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, const char *driver_name) -> drvBase * { diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index 20350c0b1..14ea7a517 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -29,6 +29,7 @@ #include "drivers/drvDps310.h" #include "drivers/drvDs2484.h" #include "drivers/drvEns160.h" +#include "drivers/drvHdc302x.h" #include "drivers/drvHts221.h" #include "drivers/drvHtu31d.h" #include "drivers/drvHtu21d.h" diff --git a/src/components/i2c/drivers/drvHdc302x.h b/src/components/i2c/drivers/drvHdc302x.h new file mode 100644 index 000000000..ad18108d1 --- /dev/null +++ b/src/components/i2c/drivers/drvHdc302x.h @@ -0,0 +1,133 @@ +/*! + * @file drvHdc302x.h + * + * Device driver for an HDC302X Humidity and Temperature sensor. + */ + +#ifndef DRV_HDC302X_H +#define DRV_HDC302X_H + +#include "drvBase.h" +#include + +/**************************************************************************/ +/*! + @brief Class that provides a sensor driver for the HDC302X humidity and + temperature sensor. This implementation uses the 1 Hz data rate. +*/ +/**************************************************************************/ +class drvHdc302x : public drvBase { + +public: + /*******************************************************************************/ + /*! + @brief Constructor for an HDC302X sensor. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + /*******************************************************************************/ + drvHdc302x(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) { + // Initialization handled by drvBase constructor + } + + /*******************************************************************************/ + /*! + @brief Destructor for an HDC302X sensor. + */ + /*******************************************************************************/ + ~drvHdc302x() { delete _hdc302x; } + + /*******************************************************************************/ + /*! + @brief Initializes the HDC302X sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + + */ + /*******************************************************************************/ + bool begin() { + // attempt to initialize the HDC302X using the I2C interface + _hdc302x = new Adafruit_HDC302x(); + if (!_hdc302x->begin(_address, _i2c)) + return false; + + // set the HDC302X's data rate to 1 Hz lowest noise + _hdc302x->setAutoMode(EXIT_AUTO_MODE); + // discard first reading (It returned -45c for me once) + _hdc302x->readTemperatureHumidityOnDemand(_temp, _humidity, + TRIGGERMODE_LP0); + return true; + } + + /*******************************************************************************/ + /*! + @brief Reads the HDC302X's temperature and humidity data. + @returns True if the data was read successfully, False otherwise. + */ + /*******************************************************************************/ + bool ReadSensorData() { + uint16_t status = _hdc302x->readStatus(); + if (status & 0x0010) { + WS_DEBUG_PRINTLN(F("Device Reset Detected")); + return false; + } + + if (status & 0x0001) { + WS_DEBUG_PRINTLN( + F("Checksum Verification Fail (incorrect checksum received)")); + return false; + } + + if (!_hdc302x->readTemperatureHumidityOnDemand(_temp, _humidity, + TRIGGERMODE_LP0)) { + WS_DEBUG_PRINTLN(F("Failed to read temperature and humidity.")); + return false; + } + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the HDC302X's current temperature. + @param tempEvent + Pointer to an Adafruit_Sensor event. + @returns True if the temperature was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventAmbientTemp(sensors_event_t *tempEvent) { + if (ReadSensorData() == false) + return false; + tempEvent->temperature = _temp; + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the HDC302X's current humidity. + @param humidEvent + Pointer to an Adafruit_Sensor event. + @returns True if the humidity was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventRelativeHumidity(sensors_event_t *humidEvent) { + if (ReadSensorData() == false) + return false; + humidEvent->relative_humidity = _humidity; + return true; + } + +protected: + Adafruit_HDC302x *_hdc302x; ///< Pointer to an HDC302X object + double _temp = 0.0; ///< Holds data for the HDC302X's temperature sensor + double _humidity = 0.0; ///< Holds data for the HDC302X's humidity sensor +}; +#endif // DRV_HDC302X_H \ No newline at end of file From 602bbd65cbbc13ce25a46c6cf0484fd363e13187 Mon Sep 17 00:00:00 2001 From: tyeth Date: Tue, 29 Apr 2025 16:18:11 +0100 Subject: [PATCH 06/17] Add LPS28DFW --- platformio.ini | 1 + src/components/i2c/controller.cpp | 5 + src/components/i2c/controller.h | 1 + src/components/i2c/drivers/drvLps28dfw.h | 155 +++++++++++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 src/components/i2c/drivers/drvLps28dfw.h diff --git a/platformio.ini b/platformio.ini index 90e742fe1..96584b83b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -62,6 +62,7 @@ lib_deps = adafruit/Adafruit VEML7700 Library adafruit/Adafruit LC709203F adafruit/Adafruit LPS2X + adafruit/Adafruit LPS28 adafruit/Adafruit LPS35HW adafruit/Adafruit seesaw Library adafruit/Adafruit BME680 Library diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 4204cf184..6ea985a8a 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -158,6 +158,11 @@ static const std::map I2cFactory = { const char *driver_name) -> drvBase * { return new drvLps25hb(i2c, addr, mux_channel, driver_name); }}, + {"lps28dfw", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvLps28dfw(i2c, addr, mux_channel, driver_name); + }}, {"ltr329", [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, const char *driver_name) -> drvBase * { diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index 14ea7a517..dacb2e670 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -37,6 +37,7 @@ #include "drivers/drvLc709203f.h" #include "drivers/drvLps22hb.h" #include "drivers/drvLps25hb.h" +#include "drivers/drvLps28dfw.h" #include "drivers/drvLps3xhw.h" #include "drivers/drvLtr329_Ltr303.h" #include "drivers/drvLtr390.h" diff --git a/src/components/i2c/drivers/drvLps28dfw.h b/src/components/i2c/drivers/drvLps28dfw.h new file mode 100644 index 000000000..3f6e89098 --- /dev/null +++ b/src/components/i2c/drivers/drvLps28dfw.h @@ -0,0 +1,155 @@ +/*! + * @file drvLps28dfw.h + * + * Device driver for a LPS28DFW precision pressure sensor breakout. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Tyeth Gundry 2025 for Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef DRV_LPS28DFW_H +#define DRV_LPS28DFW_H + +#include "drvBase.h" +#include + +/**************************************************************************/ +/*! + @brief Class that provides a sensor driver for the LPS28DFW temperature + and pressure sensor. +*/ +/**************************************************************************/ +class drvLps28dfw : public drvBase { + +public: + /*******************************************************************************/ + /*! + @brief Constructor for an LPS28DFW sensor. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + /*******************************************************************************/ + drvLps28dfw(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) { + // Initialization handled by drvBase constructor + } + + /*******************************************************************************/ + /*! + @brief Destructor for an LPS28DFW sensor. + */ + /*******************************************************************************/ + ~drvLps28dfw() { delete _lps28; } + + /*******************************************************************************/ + /*! + @brief Initializes the LPS28DFW sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + /*******************************************************************************/ + bool begin() { + _lps28 = new Adafruit_LPS28(); + // attempt to initialize LPS28DFW + if (!_lps28->begin(_i2c, _address)) + return false; + + // Set up sample rate and filter initialization + if (!_lps28->setDataRate(LPS28_ODR_ONESHOT)) { + WS_DEBUG_PRINTLN("Failed to set data rate"); + return false; + } + if (!_lps28->setAveraging(LPS28_AVG_512)) { + WS_DEBUG_PRINTLN("Failed to set averaging"); + return false; + } + if (!_lps28->setFullScaleMode(true)) { + WS_DEBUG_PRINTLN("Failed to set 4060hPa max mode"); + return false; + } + + return true; + } + + /*******************************************************************************/ + /*! + @brief Reads the sensor and stores the data in the object. + @returns True if the sensor was read successfully, False otherwise. + */ + /*******************************************************************************/ + bool readSensor() { + // grab one reading to seed the sensor + if (!_lps28->triggerOneShot()) { + return false; + } + + // Wait (block up to 100ms) until data is ready + for (uint8_t i = 0; i < 100; i++) { + if (_lps28->getStatus() & LPS28_STATUS_PRESS_READY) { + if (_temp == NULL) { + _temp = _lps28->getTemperatureSensor(); + } + if (_pressure == NULL) { + _pressure = _lps28->getPressureSensor(); + } + return true; + } + delay(1); + } + return false; + } + + /*******************************************************************************/ + /*! + @brief Gets the LPS28DFW's current temperature. + @param tempEvent + Pointer to an Adafruit_Sensor event. + @returns True if the temperature was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventAmbientTemp(sensors_event_t *tempEvent) { + if (!readSensor()) + return false; + _temp->getEvent(tempEvent); + return true; + } + + /*******************************************************************************/ + /*! + @brief Reads a pressure sensor and converts + the reading into the expected SI unit. + @param pressureEvent + Pointer to an Adafruit_Sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventPressure(sensors_event_t *pressureEvent) { + if (!readSensor()) + return false; + _pressure->getEvent(pressureEvent); + return true; + } + +protected: + Adafruit_LPS28 *_lps28 = nullptr; ///< LPS28DFW object + Adafruit_Sensor *_temp = + NULL; ///< Ptr to an adafruit_sensor representing the temperature + Adafruit_Sensor *_pressure = + NULL; ///< Ptr to an adafruit_sensor representing the pressure +}; + +#endif // DRV_LPS28DFW_H \ No newline at end of file From e547559b3fd148781f44d24958c1a0822cf595b3 Mon Sep 17 00:00:00 2001 From: tyeth Date: Tue, 29 Apr 2025 16:21:35 +0100 Subject: [PATCH 07/17] Add VCNL4200 --- platformio.ini | 1 + src/components/i2c/controller.cpp | 5 + src/components/i2c/controller.h | 1 + src/components/i2c/drivers/drvVncl4200.h | 111 +++++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 src/components/i2c/drivers/drvVncl4200.h diff --git a/platformio.ini b/platformio.ini index 96584b83b..85ce202dd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -44,6 +44,7 @@ lib_deps = adafruit/Adafruit Si7021 Library adafruit/Adafruit VCNL4020 Library adafruit/Adafruit VCNL4040 + adafruit/Adafruit VCNL4200 Library adafruit/Adafruit MCP3421 adafruit/Adafruit MCP9808 Library adafruit/Adafruit MCP9600 Library diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 6ea985a8a..dc3404334 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -338,6 +338,11 @@ static const std::map I2cFactory = { const char *driver_name) -> drvBase * { return new drvVncl4040(i2c, addr, mux_channel, driver_name); }}, + {"vncl4200", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvVncl4200(i2c, addr, mux_channel, driver_name); + }}, {"vl53l0x", [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, const char *driver_name) -> drvBase * { diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index dacb2e670..f2555ab89 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -70,6 +70,7 @@ #include "drivers/drvVl6180x.h" #include "drivers/drvVncl4020.h" #include "drivers/drvVncl4040.h" +#include "drivers/drvVncl4200.h" #define SCAN_DEVICE \ "UNKNOWN_SCAN" ///< Name for I2C devices found by an i2c scan diff --git a/src/components/i2c/drivers/drvVncl4200.h b/src/components/i2c/drivers/drvVncl4200.h new file mode 100644 index 000000000..549bac88d --- /dev/null +++ b/src/components/i2c/drivers/drvVncl4200.h @@ -0,0 +1,111 @@ +/*! + * @file drvVncl4200.h + * + * Device driver for the VCNL4200 light + proximity sensor. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Tyeth Gundry 2025 for Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ +#ifndef DRV_VCNL4200_H +#define DRV_VCNL4200_H + +#include "drvBase.h" +#include + +/**************************************************************************/ +/*! + @brief Class that provides a driver interface for a VCNL4200 sensor. +*/ +/**************************************************************************/ +class drvVncl4200 : public drvBase { +public: + /*******************************************************************************/ + /*! + @brief Constructor for a VCNL4200 sensor. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + /*******************************************************************************/ + drvVncl4200(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) { + // Initialization handled by drvBase constructor + } + + /*******************************************************************************/ + /*! + @brief Destructor for an VCNL4200 sensor. + */ + /*******************************************************************************/ + ~drvVncl4200() { delete _vcnl4200; } + + /*******************************************************************************/ + /*! + @brief Initializes the VCNL4200 sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + /*******************************************************************************/ + bool begin() { + _vcnl4200 = new Adafruit_VCNL4200(); + bool status = false; + // Attempt to initialize and configure VCNL4200 + if (!_vcnl4200->begin(_address, _i2c)) { + return false; + } + status = _vcnl4200->setALSshutdown(false); + status &= _vcnl4200->setProxShutdown(false); + status &= _vcnl4200->setProxHD(true); // 16bit instead of 12bit + status &= _vcnl4200->setALSIntegrationTime(VCNL4200_ALS_IT_400MS); + status &= _vcnl4200->setProxDuty(VCNL4200_PS_DUTY_1_160); + status &= _vcnl4200->setProxLEDCurrent(VCNL4200_LED_I_200MA); + status &= _vcnl4200->setProxIntegrationTime(VCNL4200_PS_IT_9T); + return status; + } + + /*******************************************************************************/ + /*! + @brief Performs a light sensor read using the Adafruit + Unified Sensor API. + @param lightEvent + Light sensor reading, in lux. + @returns True if the sensor event was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventLight(sensors_event_t *lightEvent) { + // Get sensor event populated in lux via AUTO integration and gain + lightEvent->light = _vcnl4200->readALSdata(); + return true; + } + + /*******************************************************************************/ + /*! + @brief Reads the VCNL4200's proximity value into an event (no unit). + @param proximityEvent + Pointer to an Adafruit_Sensor event. + @returns True if the proximity was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventProximity(sensors_event_t *proximityEvent) { + proximityEvent->data[0] = (float)_vcnl4200->readProxData(); + return true; + } + +protected: + Adafruit_VCNL4200 *_vcnl4200; ///< Pointer to VCNL4200 light sensor object +}; + +#endif // DRV_VCNL4200_H \ No newline at end of file From 943b717776f3fe806f45d6295da818edf0f3355f Mon Sep 17 00:00:00 2001 From: tyeth Date: Tue, 29 Apr 2025 16:28:04 +0100 Subject: [PATCH 08/17] Add INA260 --- library.properties | 2 +- platformio.ini | 1 + src/components/i2c/controller.cpp | 5 ++ src/components/i2c/controller.h | 1 + src/components/i2c/drivers/drvIna260.h | 103 +++++++++++++++++++++++++ 5 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/components/i2c/drivers/drvIna260.h diff --git a/library.properties b/library.properties index d6840cbca..53a75ad48 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=SdFat - Adafruit Fork, Adafruit SPIFlash, Adafruit NeoPixel, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, RTClib, StreamUtils, Adafruit SHT4x Library +depends=SdFat - Adafruit Fork, Adafruit SPIFlash, Adafruit NeoPixel, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, RTClib, StreamUtils, Adafruit SHT4x Library diff --git a/platformio.ini b/platformio.ini index 85ce202dd..8fc8ab659 100644 --- a/platformio.ini +++ b/platformio.ini @@ -31,6 +31,7 @@ lib_deps = adafruit/Adafruit DPS310 adafruit/Adafruit DS248x adafruit/Adafruit INA219 + adafruit/Adafruit INA260 Library adafruit/Adafruit HTS221 adafruit/Adafruit HTU21DF Library adafruit/Adafruit HTU31D Library diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index dc3404334..06e5f7f40 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -138,6 +138,11 @@ static const std::map I2cFactory = { const char *driver_name) -> drvBase * { return new drvIna219(i2c, addr, mux_channel, driver_name); }}, + {"ina260", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvIna260(i2c, addr, mux_channel, driver_name); + }}, {"lc709203f", [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, const char *driver_name) -> drvBase * { diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index f2555ab89..dbf46b832 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -34,6 +34,7 @@ #include "drivers/drvHtu31d.h" #include "drivers/drvHtu21d.h" #include "drivers/drvIna219.h" +#include "drivers/drvIna260.h" #include "drivers/drvLc709203f.h" #include "drivers/drvLps22hb.h" #include "drivers/drvLps25hb.h" diff --git a/src/components/i2c/drivers/drvIna260.h b/src/components/i2c/drivers/drvIna260.h new file mode 100644 index 000000000..a2affc502 --- /dev/null +++ b/src/components/i2c/drivers/drvIna260.h @@ -0,0 +1,103 @@ +/*! + * @file drvIna260.h + * + * Device driver for the INA260 DC Current and Voltage Monitor + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Tyeth Gundry 2025 for Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ +#ifndef DRV_INA260_H +#define DRV_INA260_H + +#include "drvBase.h" +#include + +/**************************************************************************/ +/*! + @brief Class that provides a driver interface for a INA260 sensor. +*/ +/**************************************************************************/ +class drvIna260 : public drvBase { +public: + /*******************************************************************************/ + /*! + @brief Constructor for a INA260 sensor. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + /*******************************************************************************/ + drvIna260(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) { + // Initialization handled by drvBase constructor + } + + /*******************************************************************************/ + /*! + @brief Destructor for an INA260 sensor. + */ + /*******************************************************************************/ + ~drvIna260() { delete _ina260; } + + /*******************************************************************************/ + /*! + @brief Initializes the INA260 sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + /*******************************************************************************/ + bool begin() { + _ina260 = new Adafruit_INA260(); + if (!_ina260->begin(_address, _i2c)) { + WS_DEBUG_PRINTLN("INA260 failed to initialise!"); + return false; + } + // TODO: use setCalibration() + + return true; + } + + /*******************************************************************************/ + /*! + @brief Reads a voltage sensor and converts the + reading into the expected SI unit. + @param voltageEvent + voltage sensor reading, in volts. + @returns True if the sensor event was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventVoltage(sensors_event_t *voltageEvent) { + voltageEvent->voltage = _ina260->readBusVoltage(); + return true; + } + + /** + * @brief Get the current sensor event. + * + * @param currentEvent Pointer to the current sensor event. + * + * @returns True if the sensor event was obtained successfully, False + * otherwise. + */ + bool getEventCurrent(sensors_event_t *currentEvent) { + currentEvent->current = _ina260->readCurrent(); + return true; + } + +protected: + Adafruit_INA260 *_ina260; ///< Pointer to INA260 sensor object +}; + +#endif // DRV_INA260_H \ No newline at end of file From 2c6713d14983064fd39ca2f27746f7a051aeb5c0 Mon Sep 17 00:00:00 2001 From: tyeth Date: Tue, 29 Apr 2025 16:46:08 +0100 Subject: [PATCH 09/17] Add SEN6x --- platformio.ini | 1 + src/components/i2c/controller.cpp | 30 +++ src/components/i2c/controller.h | 1 + src/components/i2c/drivers/drvSen6x.h | 314 ++++++++++++++++++++++++++ 4 files changed, 346 insertions(+) create mode 100644 src/components/i2c/drivers/drvSen6x.h diff --git a/platformio.ini b/platformio.ini index 8fc8ab659..8dc44d949 100644 --- a/platformio.ini +++ b/platformio.ini @@ -80,6 +80,7 @@ lib_deps = https://github.com/pstolarz/OneWireNg.git https://github.com/Sensirion/arduino-sht.git https://github.com/Sensirion/arduino-i2c-sen5x.git + https://github.com/Sensirion/arduino-i2c-sen66.git https://github.com/adafruit/WiFiNINA.git https://github.com/Starmbi/hp_BH1750.git https://github.com/adafruit/RTClib.git diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 06e5f7f40..700f42c24 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -303,6 +303,36 @@ static const std::map I2cFactory = { const char *driver_name) -> drvBase * { return new drvSen5x(i2c, addr, mux_channel, driver_name); }}, + {"sen60", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvSen6x(i2c, addr, mux_channel, driver_name); + }}, + {"sen63c", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvSen6x(i2c, addr, mux_channel, driver_name); + }}, + {"sen65", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvSen6x(i2c, addr, mux_channel, driver_name); + }}, + {"sen66", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvSen6x(i2c, addr, mux_channel, driver_name); + }}, + {"sen68", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvSen6x(i2c, addr, mux_channel, driver_name); + }}, + {"sen6x", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvSen6x(i2c, addr, mux_channel, driver_name); + }}, {"shtc3", [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, const char *driver_name) -> drvBase * { diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index dbf46b832..0e3fcf143 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -54,6 +54,7 @@ #include "drivers/drvScd30.h" #include "drivers/drvScd4x.h" #include "drivers/drvSen5x.h" +#include "drivers/drvSen6x.h" #include "drivers/drvSgp30.h" #include "drivers/drvSgp40.h" #include "drivers/drvSht3x.h" diff --git a/src/components/i2c/drivers/drvSen6x.h b/src/components/i2c/drivers/drvSen6x.h new file mode 100644 index 000000000..faaaf2f07 --- /dev/null +++ b/src/components/i2c/drivers/drvSen6x.h @@ -0,0 +1,314 @@ +/*! + * @file drvSen6x.h + * + * Device driver for the SEN66 Particulate Matter, Temperature, Humidity, VOC, + * NOX, and CO2 sensor. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Tyeth Gundry 2022 for Adafruit Industries. + * Modified (c) by Martin Ebner 2024 https://github.com/MartinEbnerSensirion + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef DRV_SEN6X_H +#define DRV_SEN6X_H + +#include "drvBase.h" +#include +#include + +/**************************************************************************/ +/*! + @brief Class that provides a driver interface for the SEN6X sensor. +*/ +/**************************************************************************/ +class drvSen6x : public drvBase { + + const float OVERFLOW_SEN6X = (0xFFFF / 10); // maxes out at u_int16 / 10 + +public: + /*******************************************************************************/ + /*! + @brief Constructor for a SEN6X sensor. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + /*******************************************************************************/ + drvSen6x(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) { + _massConcentrationPm1p0 = NAN; + _massConcentrationPm2p5 = NAN; + _massConcentrationPm4p0 = NAN; + _massConcentrationPm10p0 = NAN; + _ambientHumidity = NAN; + _ambientTemperature = NAN; + _vocIndex = NAN; + _noxIndex = NAN; + _co2 = 0uL; + } + + /*******************************************************************************/ + /*! + @brief Initializes the SEN6X sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + /*******************************************************************************/ + bool begin() { + _sen = new SensirionI2cSen66(); + _sen->begin(*_i2c, (uint8_t)_address); + u_int16_t error_stop = _sen->deviceReset(); + if (error_stop != 0) { + return false; + } + // Wait 1 second for sensors to start recording + 100ms for reset command + delay(1100); + u_int16_t error_start = _sen->startContinuousMeasurement(); + if (error_start != 0) { + return false; + } + + return true; + } + + /*******************************************************************************/ + /*! + @brief Checks if sensor was read within last 1s, or is the first read. + @returns True if the sensor was recently read, False otherwise. + */ + bool HasBeenReadInLastSecond() { + return _lastRead != 0 && millis() - _lastRead < 1000; + } + + /*******************************************************************************/ + /*! + @brief Checks if the sensor is ready to be read + @returns True if the sensor is ready, False otherwise. + */ + /*******************************************************************************/ + bool IsSensorReady() { + bool isDataReady = false; + uint8_t padding = 0x0; + for (int i = 0; i < 2; i++) { + uint16_t error = _sen->getDataReady(padding, isDataReady); + if (error == 0 && isDataReady) { + return true; + } + delay(100); + } + return false; + } + + /*******************************************************************************/ + /*! + @brief Reads the sensor. + @returns True if the sensor was read successfully, False otherwise. + */ + /*******************************************************************************/ + bool ReadSensorData() { + // dont read sensor more than once per second + if (HasBeenReadInLastSecond()) { + return true; + } + + if (!IsSensorReady()) { + return false; + } + + uint16_t error = _sen->readMeasuredValues( + _massConcentrationPm1p0, _massConcentrationPm2p5, + _massConcentrationPm4p0, _massConcentrationPm10p0, _ambientHumidity, + _ambientTemperature, _vocIndex, _noxIndex, _co2); + if (error != 0) { + return false; + } + _lastRead = millis(); + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the SEN6X's current temperature. + @param tempEvent + Pointer to an Adafruit_Sensor event. + @returns True if the temperature was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventAmbientTemp(sensors_event_t *tempEvent) { + if (!ReadSensorData() || _ambientTemperature == NAN) { + return false; + } + tempEvent->temperature = _ambientTemperature; + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the SEN6X's current relative humidity reading. + @param humidEvent + Pointer to an Adafruit_Sensor event. + @returns True if the humidity was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventRelativeHumidity(sensors_event_t *humidEvent) { + if (!ReadSensorData() || _ambientHumidity == NAN) { + return false; + } + humidEvent->relative_humidity = _ambientHumidity; + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the SEN6X's current NOX reading. + Note: If this value is unknown, which is true for SEN54, + NAN is returned. During the first 10..11 seconds after + power-on or device reset, this value will be NAN as well. + @param noxIndexEvent + Adafruit Sensor event for NOx Index (0-500, 1 is normal) + @returns True if the sensor value was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventNOxIndex(sensors_event_t *noxIndexEvent) { + if (!ReadSensorData() || _noxIndex == NAN) { + return false; + } + noxIndexEvent->nox_index = _noxIndex; + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the SEN6X's current VOC reading. + @param vocIndexEvent + Adafruit Sensor event for VOC Index (1-500, 100 is normal) + @returns True if the sensor value was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventVOCIndex(sensors_event_t *vocIndexEvent) { + if (!ReadSensorData() || _vocIndex == NAN) { + return false; + } + vocIndexEvent->voc_index = _vocIndex; + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the SEN6X sensor's PM1.0 STD reading. + @param pm10StdEvent + Adafruit Sensor event for PM1.0 + @returns True if the sensor value was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventPM10_STD(sensors_event_t *pm10StdEvent) { + if (!ReadSensorData() || _massConcentrationPm1p0 == NAN || + _massConcentrationPm1p0 == OVERFLOW_SEN6X) { + return false; + } + pm10StdEvent->pm10_std = _massConcentrationPm1p0; + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the SEN6X sensor's PM2.5 STD reading. + @param pm25StdEvent + Adafruit Sensor event for PM2.5 + @returns True if the sensor value was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventPM25_STD(sensors_event_t *pm25StdEvent) { + if (!ReadSensorData() || _massConcentrationPm2p5 == NAN || + _massConcentrationPm2p5 == OVERFLOW_SEN6X) { + return false; + } + pm25StdEvent->pm25_std = _massConcentrationPm2p5; + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the SEN6X sensor's PM4.0 STD reading. + @param pm40StdEvent + Adafruit Sensor event for PM4.0 + @returns True if the sensor value was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventPM40_STD(sensors_event_t *pm40StdEvent) { + if (!ReadSensorData() || _massConcentrationPm4p0 == NAN || + _massConcentrationPm4p0 == OVERFLOW_SEN6X) { + return false; + } + pm40StdEvent->data[0] = _massConcentrationPm4p0; + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the SEN6X sensor's PM10.0 STD reading. + @param pm100StdEvent + Adafruit Sensor event for PM10.0 + @returns True if the sensor value was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventPM100_STD(sensors_event_t *pm100StdEvent) { + if (!ReadSensorData() || _massConcentrationPm10p0 == NAN || + _massConcentrationPm10p0 == OVERFLOW_SEN6X) { + return false; + } + pm100StdEvent->pm100_std = _massConcentrationPm10p0; + return true; + } + + /*******************************************************************************/ + /*! + @brief Gets the SEN6X sensor's CO2 reading. + @param co2Event + Adafruit Sensor event for CO2 + @returns True if the sensor value was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventCO2(sensors_event_t *co2Event) { + if (!ReadSensorData() || _co2 == 0xFFFF) { + return false; + } + co2Event->CO2 = _co2; + return true; + } + +protected: + SensirionI2cSen66 *_sen = nullptr; ///< SEN6X driver object + float _massConcentrationPm1p0; ///< PM1.0 mass concentration + float _massConcentrationPm2p5; ///< PM2.5 mass concentration + float _massConcentrationPm4p0; ///< PM4.0 mass concentration + float _massConcentrationPm10p0; ///< PM10.0 mass concentration + float _ambientHumidity; ///< Ambient humidity + float _ambientTemperature; ///< Ambient temperature + float _vocIndex; ///< VOC index + float _noxIndex; ///< NOx index + uint16_t _co2; ///< CO2 value + ulong _lastRead; ///< Last time the sensor was read +}; + +#endif // DRV_SEN6X_H \ No newline at end of file From 45da7d327d310fb6c5c6de9a9ec2729c96b5c396 Mon Sep 17 00:00:00 2001 From: tyeth Date: Tue, 29 Apr 2025 16:51:54 +0100 Subject: [PATCH 10/17] Mention RP2350 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5044a03b2..a0fcf3f07 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Pre-compiled binaries and UF2 files for supported hardware are provided on the [ |--|--| |[ESP32-x](https://github.com/espressif/arduino-esp32)| ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6 | |[ESP8266](https://github.com/esp8266/Arduino)| ESP8266 | -|[RP2040](https://github.com/earlephilhower/arduino-pico)| RP2040 MCU w/WiFi (i.e: Pico W) | +|[RP2](https://github.com/earlephilhower/arduino-pico)| RP2040/RP2350 MCU w/WiFi (i.e: Pico W) | |[ATSAMD](https://github.com/adafruit/ArduinoCore-samd/)| SAMD51 MCU w/separate WiFi Co-Processor (i.e: Adafruit "AirLift")| ## Contributing to Adafruit.io and WipperSnapper From 922653cbc282f52f2cd48067939bff879580e0ca Mon Sep 17 00:00:00 2001 From: Tyeth Gundry Date: Tue, 29 Apr 2025 16:59:25 +0100 Subject: [PATCH 11/17] clang --- src/components/i2c/controller.cpp | 10 +++++----- src/components/i2c/controller.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 700f42c24..2d6b12039 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -243,11 +243,11 @@ static const std::map I2cFactory = { const char *driver_name) -> drvBase * { return new drvScd30(i2c, addr, mux_channel, driver_name); }}, - {"sgp30", - [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, - const char *driver_name) -> drvBase * { - return new drvSgp30(i2c, addr, mux_channel, driver_name); - }}, + {"sgp30", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvSgp30(i2c, addr, mux_channel, driver_name); + }}, {"sgp40", [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, const char *driver_name) -> drvBase * { diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index 0e3fcf143..5c3346f4b 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -31,8 +31,8 @@ #include "drivers/drvEns160.h" #include "drivers/drvHdc302x.h" #include "drivers/drvHts221.h" -#include "drivers/drvHtu31d.h" #include "drivers/drvHtu21d.h" +#include "drivers/drvHtu31d.h" #include "drivers/drvIna219.h" #include "drivers/drvIna260.h" #include "drivers/drvLc709203f.h" From 09a925b18118168f6fe108d7e0def4b12cc1d03a Mon Sep 17 00:00:00 2001 From: tyeth Date: Mon, 12 May 2025 15:37:00 +0100 Subject: [PATCH 12/17] Add SEN66 auto detection addresses --- src/components/i2c/controller.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 2d6b12039..5d891c49e 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -448,6 +448,7 @@ static const std::unordered_map> {0x62, {"scd40"}}, {0x68, {"mcp3421"}}, {0x69, {"sen50"}}, + {0x6B, {"sen66"}}, {0x70, {"pct2075", "shtc3"}}, {0x71, {"pct2075"}}, {0x72, {"pct2075"}}, From a1dd63da466e56231d98f592b4775ac5a25674dc Mon Sep 17 00:00:00 2001 From: tyeth Date: Mon, 12 May 2025 15:37:12 +0100 Subject: [PATCH 13/17] Add INA260 autodetection --- src/components/i2c/controller.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 5d891c49e..b50e72861 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -425,10 +425,10 @@ static const std::unordered_map> {0x2A, {"nau7802"}}, {0x38, {"aht20", "max17048"}}, {0x39, {"tsl2591"}}, - {0x40, {"htu21d", "ina219", "ms8607", "si7021", "stemma_soil"}}, - {0x41, {"ina219"}}, - {0x44, {"sht3x", "sht4x"}}, - {0x45, {"sht3x"}}, + {0x40, {"htu21d", "ina219", "ina260", "ms8607", "si7021", "stemma_soil"}}, + {0x41, {"ina219", "ina260"}}, + {0x44, {"ina260", "sht3x", "sht4x"}}, + {0x45, {"ina260", "sht3x"}}, {0x48, {"adt7410", "pct2075", "tmp117"}}, {0x49, {"adt7410", "pct2075", "tmp117", "tsl2591"}}, {0x4A, {"adt7410", "pct2075", "tmp117"}}, From 799d422f4779949a4b3cf0ccaeeb284fd44f720e Mon Sep 17 00:00:00 2001 From: tyeth Date: Mon, 12 May 2025 15:38:07 +0100 Subject: [PATCH 14/17] Add VCNL4200 autodetection --- src/components/i2c/controller.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index b50e72861..57081c0a4 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -437,6 +437,7 @@ static const std::unordered_map> {0x4D, {"pct2075"}}, {0x4E, {"pct2075"}}, {0x4F, {"pct2075"}}, + {0x51, {"vcnl4200"}}, {0x52, {"ens160"}}, {0x53, {"ens160", "ltr390"}}, {0x59, {"sgp40"}}, From 4aaa036992a111e78ff71e697a0163e6d934a696 Mon Sep 17 00:00:00 2001 From: tyeth Date: Mon, 12 May 2025 15:39:14 +0100 Subject: [PATCH 15/17] Add LPS28DFW autodetection --- src/components/i2c/controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 57081c0a4..1a3036a53 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -441,8 +441,8 @@ static const std::unordered_map> {0x52, {"ens160"}}, {0x53, {"ens160", "ltr390"}}, {0x59, {"sgp40"}}, - {0x5C, {"bh1750", "lps22hb", "lps25hb"}}, - {0x5D, {"lps22hb", "lps25hb"}}, + {0x5C, {"bh1750", "lps22hb", "lps25hb", "lps28dfw"}}, + {0x5D, {"lps22hb", "lps25hb", "lps28dfw"}}, {0x5F, {"hts2221"}}, {0x60, {"mpl115a2", "vncl4040"}}, {0x61, {"scd30"}}, From 9355d0493e3ea01f9b2f08e7cde188792474c480 Mon Sep 17 00:00:00 2001 From: tyeth Date: Mon, 12 May 2025 15:40:40 +0100 Subject: [PATCH 16/17] Add HDC302x autodetection --- src/components/i2c/controller.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 1a3036a53..bd189f5c0 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -427,8 +427,10 @@ static const std::unordered_map> {0x39, {"tsl2591"}}, {0x40, {"htu21d", "ina219", "ina260", "ms8607", "si7021", "stemma_soil"}}, {0x41, {"ina219", "ina260"}}, - {0x44, {"ina260", "sht3x", "sht4x"}}, - {0x45, {"ina260", "sht3x"}}, + {0x44, {"hdc302x", "ina260", "sht3x", "sht4x"}}, + {0x45, {"hdc302x", "ina260", "sht3x"}}, + {0x46, {"hdc302x"}}, + {0x47, {"hdc302x"}}, {0x48, {"adt7410", "pct2075", "tmp117"}}, {0x49, {"adt7410", "pct2075", "tmp117", "tsl2591"}}, {0x4A, {"adt7410", "pct2075", "tmp117"}}, From 92ecd216602e6a5fbe89ca51fe7e1d369efd80d8 Mon Sep 17 00:00:00 2001 From: tyeth Date: Mon, 12 May 2025 15:41:33 +0100 Subject: [PATCH 17/17] Add HTU31D autodetection --- src/components/i2c/controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index bd189f5c0..b0431c32a 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -425,8 +425,8 @@ static const std::unordered_map> {0x2A, {"nau7802"}}, {0x38, {"aht20", "max17048"}}, {0x39, {"tsl2591"}}, - {0x40, {"htu21d", "ina219", "ina260", "ms8607", "si7021", "stemma_soil"}}, - {0x41, {"ina219", "ina260"}}, + {0x40, {"htu21d", "htu31d", "ina219", "ina260", "ms8607", "si7021", "stemma_soil"}}, + {0x41, {"htu31d", "ina219", "ina260"}}, {0x44, {"hdc302x", "ina260", "sht3x", "sht4x"}}, {0x45, {"hdc302x", "ina260", "sht3x"}}, {0x46, {"hdc302x"}},