Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add sen6x, derived from sen5x driver #675

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper
category=Communication
url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino
architectures=*
depends=Adafruit NeoPixel, Adafruit SPIFlash, 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, 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 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
depends=Adafruit NeoPixel, Adafruit SPIFlash, 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 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
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ lib_deps =
https://github.com/Sensirion/arduino-sht.git
https://github.com/Sensirion/arduino-i2c-scd4x.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/Adafruit_TinyUSB_Arduino.git
Expand Down
16 changes: 16 additions & 0 deletions src/components/i2c/WipperSnapper_I2C.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,22 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
_sen5x->configureDriver(msgDeviceInitReq);
drivers.push_back(_sen5x);
WS_DEBUG_PRINTLN("SEN5X Initialized Successfully!");
} else if ((strcmp("sen6x", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sen60", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sen63C", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sen65", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sen66", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sen68", msgDeviceInitReq->i2c_device_name) == 0)) {
_sen6x = new WipperSnapper_I2C_Driver_SEN6X(this->_i2c, i2cAddress);
if (!_sen6x->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize SEN6X!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_sen6x->configureDriver(msgDeviceInitReq);
drivers.push_back(_sen6x);
WS_DEBUG_PRINTLN("SEN6X Initialized Successfully!");
} else if ((strcmp("sht40", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sht41", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sht45", msgDeviceInitReq->i2c_device_name) == 0)) {
Expand Down
2 changes: 2 additions & 0 deletions src/components/i2c/WipperSnapper_I2C.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "drivers/WipperSnapper_I2C_Driver_SCD30.h"
#include "drivers/WipperSnapper_I2C_Driver_SCD4X.h"
#include "drivers/WipperSnapper_I2C_Driver_SEN5X.h"
#include "drivers/WipperSnapper_I2C_Driver_SEN6X.h"
#include "drivers/WipperSnapper_I2C_Driver_SGP30.h"
#include "drivers/WipperSnapper_I2C_Driver_SGP40.h"
#include "drivers/WipperSnapper_I2C_Driver_SHT3X.h"
Expand Down Expand Up @@ -164,6 +165,7 @@ class WipperSnapper_Component_I2C {
WipperSnapper_I2C_Driver_VEML7700 *_veml7700 = nullptr;
WipperSnapper_I2C_Driver_SCD4X *_scd40 = nullptr;
WipperSnapper_I2C_Driver_SEN5X *_sen5x = nullptr;
WipperSnapper_I2C_Driver_SEN6X *_sen6x = nullptr;
WipperSnapper_I2C_Driver_SGP30 *_sgp30 = nullptr;
WipperSnapper_I2C_Driver_SGP40 *_sgp40 = nullptr;
WipperSnapper_I2C_Driver_PCT2075 *_pct2075 = nullptr;
Expand Down
340 changes: 340 additions & 0 deletions src/components/i2c/drivers/WipperSnapper_I2C_Driver_SEN6X.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,340 @@
/*!
* @file WipperSnapper_I2C_Driver_SEN6X.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) Marni Brewster 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 WipperSnapper_I2C_Driver_SEN6X_H
#define WipperSnapper_I2C_Driver_SEN6X_H

#include "WipperSnapper_I2C_Driver.h"
#include <SensirionI2cSen66.h>
#include <Wire.h>

/**************************************************************************/
/*!
@brief Class that provides a driver interface for the SEN6X sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_SEN6X : public WipperSnapper_I2C_Driver {

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.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_SEN6X(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}

/*******************************************************************************/
/*!
@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)_sensorAddress);
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 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) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t co2;
uint16_t error;

error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex, co2);
if ((_tempSensorPeriod != 0 && error != 0) || 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) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t co2;
uint16_t error;

error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex, co2);
if ((_humidSensorPeriod != 0 && error != 0) || 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) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t co2;
uint16_t error;

error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex, co2);
if ((_NOxIndexPeriod != 0 && error != 0) || 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) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t co2;
uint16_t error;

error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex, co2);
if ((_VOCIndexPeriod != 0 && error != 0) || 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) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t co2;
uint16_t error;

error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex, co2);
if ((_PM10SensorPeriod != 0 && error != 0) ||
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) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t co2;
uint16_t error;

error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex, co2);
if ((_PM25SensorPeriod != 0 && error != 0) ||
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) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t co2;
uint16_t error;

error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex, co2);
if ((_PM25SensorPeriod != 0 && error != 0) ||
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) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t co2;
uint16_t error;

error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex, co2);
if ((_PM100SensorPeriod != 0 && error != 0) ||
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) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t co2;
uint16_t error;

error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex, co2);

if ((_CO2SensorPeriod != 0 && error != 0) || co2 == NAN) {
return false;
}

co2Event->CO2 = co2;
return true;
}

protected:
SensirionI2cSen66 *_sen; ///< SEN6X driver object
};

#endif // WipperSnapper_I2C_Driver_SEN6X
Loading