Files
ESP8266lib/ext/sens/ENS160.h

147 lines
3.1 KiB
C++

#pragma once
/**
* a digital multi-gas sensor for indoor air quality monitoring
* https://www.sciosense.com/wp-content/uploads/documents/SC-001224-DS-7-ENS160-Datasheet.pdf
*/
template <typename I2C> class ENS160 {
private:
I2C& i2c;
static constexpr const uint8_t ADDR1 = 0x52;
static constexpr const uint8_t ADDR2 = 0x53;
uint8_t ADDR;
static constexpr const char* NAME = "ENS160";
static constexpr const uint8_t REG_PART_ID = 0x00;
static constexpr const uint8_t REG_OPMODE = 0x10;
static constexpr const uint8_t REG_TEMP_IN = 0x13;
static constexpr const uint8_t REG_RH_IN = 0x15;
static constexpr const uint8_t REG_DEVICE_STATUS = 0x20;
static constexpr const uint8_t REG_DATA_AQI = 0x21;
static constexpr const uint8_t REG_DATA_TVOC = 0x22;
static constexpr const uint8_t REG_DATA_ECO2 = 0x24;
public:
enum class Mode : uint8_t {
DEEP_SLEEP = 0x00,
IDLE = 0x01,
STANDARD = 0x02,
RESET = 0xF0,
};
union Status {
uint8_t raw;
struct {
uint8_t newgpr : 1;
uint8_t newdat : 1;
uint8_t valid : 2;
uint8_t dummy : 2;
uint8_t stater : 1;
uint8_t statas : 1;
} __attribute__((__packed__));
bool isNormal() const {return valid == 0;}
bool isWarmUp() const {return valid == 1;}
bool isStartUp() const {return valid == 2;}
bool isInvalid() const {return valid == 3;}
} __attribute__((__packed__));
union Result {
uint8_t raw[6];
struct {
Status status;
uint8_t aqi;
uint16_t tvoc;
uint16_t eco2;
} __attribute__((__packed__));
} __attribute__((__packed__));
public:
ENS160(I2C& i2c, uint8_t addr = ADDR1) : i2c(i2c), ADDR(addr) {
}
/** always 0x01 0x60 */
uint16_t getID() {
uint16_t res = 0;
i2c.readReg(ADDR, 0x00, 2, (uint8_t*)&res);
return res;
}
/** switch the mode of operation */
void setMode(Mode m) {
i2c.writeReg8(ADDR, REG_OPMODE, (uint8_t)m);
DELAY_MS(250); // not mentioned in the data-sheet but important?
}
/** set the current ambient temperature - for compensation */
void setTemp(float celsius) {
float kelvin = celsius + 273.15;
uint16_t tmp = (uint16_t) (kelvin * 64);
i2c.writeReg(ADDR, REG_TEMP_IN, 2, (uint8_t*)&tmp);
}
/** set the current ambient humidity (in %) - for compensation */
void setHumi(uint8_t humi) {
uint16_t tmp = humi * 512;
i2c.writeReg(ADDR, REG_RH_IN, 2, (uint8_t*)&tmp);
}
/** status + aqi + tvoc + eco2 */
Result getAll() {
Result res;
memset(res.raw, 0, 6);
i2c.readReg(ADDR, REG_DEVICE_STATUS, 6, res.raw);
res.status = getStatus();
//res.aqi = getAQI();
//res.tvoc = getTVOC();
//res.eco2 = getECO2();
return res;
}
Status getStatus() {
Status res;
res.raw = i2c.readReg8(ADDR, REG_DEVICE_STATUS);
return res;
}
uint8_t getAQI() {
uint8_t tmp = 0;
i2c.readReg(ADDR, REG_DATA_AQI, 1, &tmp);
return tmp & 0b111;
}
uint16_t getTVOC() {
uint16_t tmp = 0;
i2c.readReg(ADDR, REG_DATA_TVOC, 2, (uint8_t*)&tmp);
return tmp;
}
uint16_t getECO2() {
uint16_t tmp = 0;
i2c.readReg(ADDR, REG_DATA_ECO2, 2, (uint8_t*)&tmp);
return tmp;
}
/** is the device present on the bus? */
bool isPresent() {
return i2c.query(ADDR);
}
};