diff --git a/ChangeLog.md b/ChangeLog.md index 6ec3be6c8..534365b79 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -15,10 +15,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Applied markdown lint to markdown files - Bumped TinyGSM dependency - Changed datatypes for modem voltage outputs. +- Switched from Soligen fork of ADS1115 library to the standard Adafruit version. ### Added - Added support for Yosemitech Y513 Blue Green Algae Sensor thanks to @aufdenkampe +- Added support for Alphasense CO2 Sensor thanks to @aufdenkampe ### Removed diff --git a/examples/menu_a_la_carte/ReadMe.md b/examples/menu_a_la_carte/ReadMe.md index e104351e8..dffa232f9 100644 --- a/examples/menu_a_la_carte/ReadMe.md +++ b/examples/menu_a_la_carte/ReadMe.md @@ -58,6 +58,7 @@ ___ - [Sensors and Measured Variables](#sensors-and-measured-variables) - [The processor as a sensor](#the-processor-as-a-sensor) - [Maxim DS3231 RTC as a sensor](#maxim-ds3231-rtc-as-a-sensor) + - [Alphasense CO2](#alphasense-co2) - [AOSong AM2315](#aosong-am2315) - [AOSong DHT](#aosong-dht) - [Apogee SQ-212 Quantum Light Sensor](#apogee-sq-212-quantum-light-sensor) @@ -604,6 +605,14 @@ As above, we create both the sensor and the variables measured by it. ___ +### Alphasense CO2 + +@see @ref sensor_alphasense_co2 + +[//]: # ( @menusnip{alphasense_co2} ) + +___ + ### AOSong AM2315 Here is the code for the AOSong AM2315 temperature and humidity sensor. diff --git a/examples/menu_a_la_carte/menu_a_la_carte.ino b/examples/menu_a_la_carte/menu_a_la_carte.ino index 0df44d01f..70546992d 100644 --- a/examples/menu_a_la_carte/menu_a_la_carte.ino +++ b/examples/menu_a_la_carte/menu_a_la_carte.ino @@ -815,6 +815,30 @@ Variable* ds3231Temp = #endif +#if defined(BUILD_SENSOR_ALPHASENSE_CO2) +// ========================================================================== +// Alphasense CO2 Sensor +// ========================================================================== +/** Start [alphasense_co2] */ +#include + +// NOTE: Use -1 for any pins that don't apply or aren't being used. +const int8_t AlphasenseCO2Power = sensorPowerPin; // Power pin +const uint8_t AlphasenseCO2ADSi2c_addr = + 0x48; // The I2C address of the ADS1115 ADC + +// Create an Alphasense CO2 sensor object +AlphasenseCO2 alphasenseCO2(AlphasenseCO2Power, AlphasenseCO2ADSi2c_addr); + +// Create PAR and raw voltage variable pointers for the CO2 +Variable* asCO2 = new AlphasenseCO2_CO2(&alphasenseCO2, + "12345678-abcd-1234-ef00-1234567890ab"); +Variable* asco2voltage = new AlphasenseCO2_Voltage( + &alphasenseCO2, "12345678-abcd-1234-ef00-1234567890ab"); +/** End [alphasense_co2] */ +#endif + + #if defined(BUILD_SENSOR_AO_SONG_AM2315) // ========================================================================== // AOSong AM2315 Digital Humidity and Temperature Sensor @@ -2618,6 +2642,10 @@ Variable* variableList[] = { #if defined(ARDUINO_ARCH_AVR) || defined(MS_SAMD_DS3231) ds3231Temp, #endif +#if defined(BUILD_SENSOR_ALPHASENSE_CO2) + asCO2, + asco2voltage, +#endif #if defined(BUILD_SENSOR_AO_SONG_AM2315) am2315Humid, am2315Temp, diff --git a/src/sensors/AlphasenseCO2.cpp b/src/sensors/AlphasenseCO2.cpp index 43f1969c2..7b76eb8a7 100644 --- a/src/sensors/AlphasenseCO2.cpp +++ b/src/sensors/AlphasenseCO2.cpp @@ -6,7 +6,8 @@ * Part of the EnviroDIY ModularSensors library for Arduino * @author Written by Anthony Aufdenkampe * and Bella Henkel - * Adapted from ApogeeSQ212.h and https://github.com/bellahenkel/Soil-Sensing-Device + * Adapted from ApogeeSQ212.h and + * https://github.com/bellahenkel/Soil-Sensing-Device * * @brief Implements the AlphasenseCO2 class. */ @@ -17,11 +18,13 @@ // The constructor - need the power pin and the data pin -AlphasenseCO2::AlphasenseCO2(int8_t powerPin, - uint8_t i2cAddress, uint8_t measurementsToAverage) - : Sensor("AlphasenseCO2", ALPHASENSE_CO2_NUM_VARIABLES, ALPHASENSE_CO2_WARM_UP_TIME_MS, - ALPHASENSE_CO2_STABILIZATION_TIME_MS, ALPHASENSE_CO2_MEASUREMENT_TIME_MS, powerPin, - -1, measurementsToAverage, ALPHASENSE_CO2_INC_CALC_VARIABLES), +AlphasenseCO2::AlphasenseCO2(int8_t powerPin, uint8_t i2cAddress, + uint8_t measurementsToAverage) + : Sensor("AlphasenseCO2", ALPHASENSE_CO2_NUM_VARIABLES, + ALPHASENSE_CO2_WARM_UP_TIME_MS, + ALPHASENSE_CO2_STABILIZATION_TIME_MS, + ALPHASENSE_CO2_MEASUREMENT_TIME_MS, powerPin, -1, + measurementsToAverage, ALPHASENSE_CO2_INC_CALC_VARIABLES), _i2cAddress(i2cAddress) {} // Destructor @@ -42,10 +45,10 @@ String AlphasenseCO2::getSensorLocation(void) { bool AlphasenseCO2::addSingleMeasurementResult(void) { // Variables to store the results in - int16_t adcCounts = -9999; - float adcVoltage = -9999; - float co2Current = -9999; - float calibResult = -9999; + int16_t adcCounts = -9999; + float adcVoltage = -9999; + float co2Current = -9999; + float calibResult = -9999; // Check a measurement was *successfully* started (status bit 6 set) // Only go on to get a result if it was @@ -90,9 +93,11 @@ bool AlphasenseCO2::addSingleMeasurementResult(void) { if (adcVoltage < 3.6 && adcVoltage > -0.3) { // Skip results out of range - // Convert voltage to current (mA) - assuming a 250 Ohm resistor is in series + // Convert voltage to current (mA) - assuming a 250 Ohm resistor is + // in series co2Current = (adcVoltage / 250) * 1000; - // Convert current to ppm (using a formula recommended by the sensor manufacturer) + // Convert current to ppm (using a formula recommended by the sensor + // manufacturer) calibResult = 312.5 * co2Current - 1250; MS_DBG(F(" calibResult:"), calibResult); } else { diff --git a/src/sensors/AlphasenseCO2.h b/src/sensors/AlphasenseCO2.h index 3600918e9..2ce0d4d80 100644 --- a/src/sensors/AlphasenseCO2.h +++ b/src/sensors/AlphasenseCO2.h @@ -4,23 +4,24 @@ * Part of the EnviroDIY ModularSensors library for Arduino * @author Written by Anthony Aufdenkampe * and Bella Henkel - * Adapted from ApogeeSQ212.h and https://github.com/bellahenkel/Soil-Sensing-Device + * Adapted from ApogeeSQ212.h and + * https://github.com/bellahenkel/Soil-Sensing-Device * Edited by Sara Geleskie Damiano * * @brief Contains the AlphasenseCO2 sensor class and the variable subclasses * AlphasenseCO2_CO2 and AlphasenseCO2_Voltage. * - * These are used for the Alphasense IRC-A1 Nondispersive Infrared (NDIR) - * Carbon Dioxide (CO2) sensor. This library will almost certainly also work with - * the Alphasense IRC-AT CO2 sensor (which uses a thermopile detector), although the - * warmup and stabilization times might be different. + * These are used for the Alphasense IRC-A1 Nondispersive Infrared (NDIR) + * Carbon Dioxide (CO2) sensor. This library will almost certainly also work + * with the Alphasense IRC-AT CO2 sensor (which uses a thermopile detector), + * although the warmup and stabilization times might be different. * -* This depends on the Adafruit ADS1X15 v2.x library. + * This depends on the Adafruit ADS1X15 v2.x library. */ /* clang-format off */ /** * @defgroup sensor_alphasense_co2 Alphasense IRC-A1 CO2 - * Classes for the Alphasense IRC-A1 Nondispersive Infrared (NDIR) + * Classes for the Alphasense IRC-A1 Nondispersive Infrared (NDIR) * Carbon Dioxide (CO2) sensor. * * @ingroup analog_group @@ -37,13 +38,13 @@ * * To convert the sensor's analog 4-20 mA signal to a high resolution digital * signal, the sensor must be attached to an analog-to-digital converter with - * an resistor in series. Furthermore, + * an resistor in series. Furthermore, * https://www.alphasense.com/products/ndir-safety/ * https://www.alphasense.com/wp-content/uploads/2018/04/IRC-A1.pdf * https://www.alphasense.com/wp-content/uploads/2017/09/NDIR-Transmitter.pdf * https://www.alphasense.com/wp-content/uploads/2022/10/AAN_202-04_App-Note_V0.pdf * https://www.alphasense.com/wp-content/uploads/2022/10/AAN_201-06_App-Note_V0.pdf - * + * * See the * [ADS1115](@ref analog_group) for details on the ADC conversion. * @@ -88,12 +89,38 @@ /** @ingroup sensor_alphasense_co2 */ /**@{*/ -// Sensor Specific Defines -/// @brief Sensor::_numReturnedValues; the Alphasense CO2 sensor can report 2 values, raw -/// voltage and calculated CO2. +/** + * @anchor sensor_alphasense_co2_var_counts + * @name Sensor Variable Counts + * The number of variables that can be returned by the Apogee SQ-212 + */ +/**@{*/ +/// @brief Sensor::_numReturnedValues; the Alphasense CO2 sensor can report 2 +/// values, raw voltage and calculated CO2. #define ALPHASENSE_CO2_NUM_VARIABLES 2 /// @brief Sensor::_incCalcValues; CO2 is calculated from the raw voltage. #define ALPHASENSE_CO2_INC_CALC_VARIABLES 1 +/**@}*/ + +/** + * @anchor sensor__alphasense_co2_config + * @name Configuration Defines + * Defines to set the calibration of the Alphasense CO2 sensor and the address + * of the ADD. + */ +/**@{*/ +#if !defined(ALPHASENSE_CO2_CALIBRATION_FACTOR) || defined(DOXYGEN) +/** + * @brief The calibration factor between output in volts and CO2 + * (microeinsteinPerSquareMeterPerSecond) 1 µmol mˉ² sˉ¹ per mV (reciprocal of + * sensitivity) + */ +#define ALPHASENSE_CO2_CALIBRATION_FACTOR 1 +#endif + +/// The assumed address of the ADS1115, 1001 000 (ADDR = GND) +#define ADS1115_ADDRESS 0x48 +/**@}*/ /** * @anchor sensor_alphasense_co2_timing @@ -102,24 +129,24 @@ */ /**@{*/ /** - * @brief Sensor::_warmUpTime_ms; - * The TI ADS1x15 to warm up time is 2 ms, and we get + * @brief Sensor::_warmUpTime_ms; + * The TI ADS1x15 to warm up time is 2 ms, and we get * Alphasense CO2 sensor readings in <200 ms second. */ #define ALPHASENSE_CO2_WARM_UP_TIME_MS 200 /** - * @brief Sensor::_stabilizationTime_ms; + * @brief Sensor::_stabilizationTime_ms; * The manufacturer provides the following stablization times: - * - To final zero ± 100ppm: < 30 s @ 20°C + * - To final zero ± 100ppm: < 30 s @ 20°C * - To specification: < 30 minutes @ 20°C * We found that values leveled off after ~35 s. See: - * https://github.com/bellahenkel/Soil-Sensing-Device/tree/main/examples/getValuesCO2 * + * https://github.com/bellahenkel/Soil-Sensing-Device/tree/main/examples/getValuesCO2 */ #define ALPHASENSE_CO2_STABILIZATION_TIME_MS 35000 /** * @brief Sensor::_measurementTime_ms; * The Alphasense IRC-A1 CO2 sensor will return a new number every 200 ms, - * but there appears to be a cyclic response with a ~7 sec period, + * but there appears to be a cyclic response with a ~7 sec period, * so we recommend averaging 1 s measurements over 28 seconds (3 periods) */ #define ALPHASENSE_CO2_MEASUREMENT_TIME_MS 1000 @@ -138,6 +165,15 @@ * {{ @ref AlphasenseCO2_CO2 }} */ /**@{*/ +#ifdef MS_USE_ADS1015 +/// @brief Decimals places in string representation; CO2 should have 0 when +/// using an ADS1015. +#define ALPHASENSE_CO2_RESOLUTION 0 +#else +/// @brief Decimals places in string representation; CO2 should have 4 when +/// using an ADS1115. +#define ALPHASENSE_CO2_RESOLUTION 4 +#endif /// Variable number; CO2 is stored in sensorValues[0]. #define ALPHASENSE_CO2_VAR_NUM 0 /// @brief Variable name in [ODM2 controlled @@ -151,15 +187,6 @@ /// @brief Default variable short code; "AlphasenseCO2ppm" #define ALPHASENSE_CO2_DEFAULT_CODE "AlphasenseCO2ppm" -#ifdef MS_USE_ADS1015 -/// @brief Decimals places in string representation; CO2 should have 0 when -/// using an ADS1015. -#define ALPHASENSE_CO2_RESOLUTION 0 -#else -/// @brief Decimals places in string representation; CO2 should have 4 when -/// using an ADS1115. -#define ALPHASENSE_CO2_RESOLUTION 4 -#endif /**@}*/ /** @@ -202,34 +229,23 @@ /**@}*/ /** - * @brief The calibration factor between output in volts and CO2 - * (microeinsteinPerSquareMeterPerSecond) 1 µmol mˉ² sˉ¹ per mV (reciprocal of - * sensitivity) - */ -#ifndef ALPHASENSE_CO2_CALIBRATION_FACTOR -#define ALPHASENSE_CO2_CALIBRATION_FACTOR 1 -#endif - -/// The assumed address of the ADS1115, 1001 000 (ADDR = GND) -#define ADS1115_ADDRESS 0x48 - -/** - * @brief The Sensor sub-class for the [Alphasense IRC-A1 CO2](@ref sensor_alphasense_co2) sensor + * @brief The Sensor sub-class for the [Alphasense IRC-A1 CO2](@ref + * sensor_alphasense_co2) sensor * * @ingroup sensor_alphasense_co2 */ class AlphasenseCO2 : public Sensor { public: /** - * @brief Construct a new Alphasense IRC-A1 CO2 object - need the power pin and the - * on the ADS1x15. Designed to read differential voltage between - * ads channels 2 and 3 + * @brief Construct a new Alphasense IRC-A1 CO2 object - need the power pin + * and the on the ADS1x15. Designed to read differential voltage between ads + * channels 2 and 3 * * @note ModularSensors only supports connecting the ADS1x15 to the primary * hardware I2C instance defined in the Arduino core. Connecting the ADS to * a secondary hardware or software I2C instance is *not* supported! * - * @param powerPin The pin on the mcu controlling power to the + * @param powerPin The pin on the mcu controlling power to the * Alphasense CO2 sensor. Use -1 if it is continuously powered. * - The Alphasense CO2 sensor requires 2-5 V DC; current draw 20-60 mA * - The ADS1115 requires 2.0-5.5V but is assumed to be powered at 3.3V @@ -239,20 +255,19 @@ class AlphasenseCO2 : public Sensor { * average before giving a "final" result from the sensor; optional with a * default value of 7 [seconds], which is one period of the cycle. * @note The ADS is expected to be either continuously powered or have - * its power controlled by the same pin as the Alphasense CO2 sensor. This library does - * not support any other configuration. + * its power controlled by the same pin as the Alphasense CO2 sensor. This + * library does not support any other configuration. */ - AlphasenseCO2(int8_t powerPin, - uint8_t i2cAddress = ADS1115_ADDRESS, - uint8_t measurementsToAverage = 7); + AlphasenseCO2(int8_t powerPin, uint8_t i2cAddress = ADS1115_ADDRESS, + uint8_t measurementsToAverage = 7); /** * @brief Destroy the AlphasenseCO2 object - no action needed */ ~AlphasenseCO2(); /** - * @brief Report the I1C address of the ADS and the channel that the Alphasense CO2 sensor - * is attached to. + * @brief Report the I1C address of the ADS and the channel that the + * Alphasense CO2 sensor is attached to. * * @return **String** Text describing how the sensor is attached to the mcu. */ @@ -264,6 +279,9 @@ class AlphasenseCO2 : public Sensor { bool addSingleMeasurementResult(void) override; private: + /** + * @brief Internal reference to the I2C address of the TI-ADS1x15 + */ uint8_t _i2cAddress; }; @@ -289,15 +307,17 @@ class AlphasenseCO2_CO2 : public Variable { * @param varCode A short code to help identify the variable in files; * optional with a default value of "radiationIncomingPAR". */ - explicit AlphasenseCO2_CO2(AlphasenseCO2* parentSense, const char* uuid = "", - const char* varCode = ALPHASENSE_CO2_DEFAULT_CODE) + explicit AlphasenseCO2_CO2( + AlphasenseCO2* parentSense, const char* uuid = "", + const char* varCode = ALPHASENSE_CO2_DEFAULT_CODE) : Variable(parentSense, (const uint8_t)ALPHASENSE_CO2_VAR_NUM, (uint8_t)ALPHASENSE_CO2_RESOLUTION, ALPHASENSE_CO2_VAR_NAME, ALPHASENSE_CO2_UNIT_NAME, varCode, uuid) {} /** * @brief Construct a new AlphasenseCO2_CO2 object. * - * @note This must be tied with a parent AlphasenseCO2 before it can be used. + * @note This must be tied with a parent AlphasenseCO2 before it can be + * used. */ AlphasenseCO2_CO2() : Variable((const uint8_t)ALPHASENSE_CO2_VAR_NUM, @@ -335,17 +355,21 @@ class AlphasenseCO2_Voltage : public Variable { AlphasenseCO2* parentSense, const char* uuid = "", const char* varCode = ALPHASENSE_CO2_VOLTAGE_DEFAULT_CODE) : Variable(parentSense, (const uint8_t)ALPHASENSE_CO2_VOLTAGE_VAR_NUM, - (uint8_t)ALPHASENSE_CO2_VOLTAGE_RESOLUTION, ALPHASENSE_CO2_VOLTAGE_VAR_NAME, + (uint8_t)ALPHASENSE_CO2_VOLTAGE_RESOLUTION, + ALPHASENSE_CO2_VOLTAGE_VAR_NAME, ALPHASENSE_CO2_VOLTAGE_UNIT_NAME, varCode, uuid) {} /** * @brief Construct a new AlphasenseCO2_Voltage object. * - * @note This must be tied with a parent AlphasenseCO2 before it can be used. + * @note This must be tied with a parent AlphasenseCO2 before it can be + * used. */ AlphasenseCO2_Voltage() : Variable((const uint8_t)ALPHASENSE_CO2_VOLTAGE_VAR_NUM, - (uint8_t)ALPHASENSE_CO2_VOLTAGE_RESOLUTION, ALPHASENSE_CO2_VOLTAGE_VAR_NAME, - ALPHASENSE_CO2_VOLTAGE_UNIT_NAME, ALPHASENSE_CO2_VOLTAGE_DEFAULT_CODE) {} + (uint8_t)ALPHASENSE_CO2_VOLTAGE_RESOLUTION, + ALPHASENSE_CO2_VOLTAGE_VAR_NAME, + ALPHASENSE_CO2_VOLTAGE_UNIT_NAME, + ALPHASENSE_CO2_VOLTAGE_DEFAULT_CODE) {} /** * @brief Destroy the AlphasenseCO2_Voltage object - no action needed. */ diff --git a/src/sensors/ApogeeSQ212.cpp b/src/sensors/ApogeeSQ212.cpp index e84ea02ad..a39fd8b96 100644 --- a/src/sensors/ApogeeSQ212.cpp +++ b/src/sensors/ApogeeSQ212.cpp @@ -44,9 +44,9 @@ String ApogeeSQ212::getSensorLocation(void) { bool ApogeeSQ212::addSingleMeasurementResult(void) { // Variables to store the results in - int16_t adcCounts = -9999; - float adcVoltage = -9999; - float calibResult = -9999; + int16_t adcCounts = -9999; + float adcVoltage = -9999; + float calibResult = -9999; // Check a measurement was *successfully* started (status bit 6 set) // Only go on to get a result if it was diff --git a/src/sensors/CampbellOBS3.cpp b/src/sensors/CampbellOBS3.cpp index edcc2cbda..bed6e1124 100644 --- a/src/sensors/CampbellOBS3.cpp +++ b/src/sensors/CampbellOBS3.cpp @@ -44,9 +44,9 @@ String CampbellOBS3::getSensorLocation(void) { bool CampbellOBS3::addSingleMeasurementResult(void) { // Variables to store the results in - int16_t adcCounts = -9999; - float adcVoltage = -9999; - float calibResult = -9999; + int16_t adcCounts = -9999; + float adcVoltage = -9999; + float calibResult = -9999; // Check a measurement was *successfully* started (status bit 6 set) // Only go on to get a result if it was diff --git a/src/sensors/TIADS1x15.cpp b/src/sensors/TIADS1x15.cpp index 0dedb185c..a731811a7 100644 --- a/src/sensors/TIADS1x15.cpp +++ b/src/sensors/TIADS1x15.cpp @@ -44,9 +44,9 @@ String TIADS1x15::getSensorLocation(void) { bool TIADS1x15::addSingleMeasurementResult(void) { // Variables to store the results in - int16_t adcCounts = -9999; - float adcVoltage = -9999; - float calibResult = -9999; + int16_t adcCounts = -9999; + float adcVoltage = -9999; + float calibResult = -9999; // Check a measurement was *successfully* started (status bit 6 set) // Only go on to get a result if it was diff --git a/src/sensors/TurnerCyclops.cpp b/src/sensors/TurnerCyclops.cpp index 4c2f13757..e7d86e6f8 100644 --- a/src/sensors/TurnerCyclops.cpp +++ b/src/sensors/TurnerCyclops.cpp @@ -44,9 +44,9 @@ String TurnerCyclops::getSensorLocation(void) { bool TurnerCyclops::addSingleMeasurementResult(void) { // Variables to store the results in - int16_t adcCounts = -9999; - float adcVoltage = -9999; - float calibResult = -9999; + int16_t adcCounts = -9999; + float adcVoltage = -9999; + float calibResult = -9999; // Check a measurement was *successfully* started (status bit 6 set) // Only go on to get a result if it was