Browse Source

sns: bme680 updates for the i2c change

pull/2516/head
Maxim Prokhorov 2 years ago
parent
commit
d800445442
1 changed files with 112 additions and 76 deletions
  1. +112
    -76
      code/espurna/sensors/BME680Sensor.h

+ 112
- 76
code/espurna/sensors/BME680Sensor.h View File

@ -89,30 +89,42 @@ class BME680Sensor : public I2CSensor<> {
public:
// ---------------------------------------------------------------------
// Public
// Sensor API
// ---------------------------------------------------------------------
BME680Sensor() {
_error = SENSOR_ERROR_OK;
_sensor_id = SENSOR_BME680_ID;
_count = 9;
static constexpr Magnitude Magnitudes[] {
MAGNITUDE_TEMPERATURE,
MAGNITUDE_HUMIDITY,
MAGNITUDE_PRESSURE,
MAGNITUDE_RESISTANCE,
MAGNITUDE_IAQ_ACCURACY,
MAGNITUDE_IAQ,
MAGNITUDE_IAQ_STATIC,
MAGNITUDE_CO2,
MAGNITUDE_VOC,
};
unsigned char id() const override {
return SENSOR_BME680_ID;
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
unsigned char count() const override {
return std::size(Magnitudes);
}
void begin() {
void begin() override {
if (!_dirty) {
return;
}
// I2C auto-discover
unsigned char addresses[] = {BME680_I2C_ADDR_PRIMARY, BME680_I2C_ADDR_SECONDARY};
_address = _begin_i2c(_address, sizeof(addresses), addresses);
if (_address == 0) return;
static constexpr uint8_t addresses[] {BME680_I2C_ADDR_PRIMARY, BME680_I2C_ADDR_SECONDARY};
auto address = findAndLock(addresses);
if (address == 0) {
return;
}
iaqSensor.begin(_address, Wire);
iaqSensor.begin(address, Wire);
DEBUG_MSG_P(PSTR("[BME680] BSEC library version v%u.%u.%u.%u\n"),
iaqSensor.version.major,
@ -130,20 +142,19 @@ class BME680Sensor : public I2CSensor<> {
iaqSensor.setConfig(bsec_config_iaq);
_loadState();
float sampleRate;
_last_state = TimeSource::now();
// BSEC configuration with 300s allows for the sensor to sleep for 300s
// on the ULP mode in order to minimize power consumption.
if (BME680_BSEC_CONFIG == BME680_BSEC_CONFIG_GENERIC_18V_300S_4D ||
BME680_BSEC_CONFIG == BME680_BSEC_CONFIG_GENERIC_18V_300S_4D ||
BME680_BSEC_CONFIG == BME680_BSEC_CONFIG_GENERIC_18V_300S_4D) {
sampleRate = BSEC_SAMPLE_RATE_ULP;
} else {
sampleRate = BSEC_SAMPLE_RATE_LP;
}
const float sampleRate =
((BME680_BSEC_CONFIG == BME680_BSEC_CONFIG_GENERIC_18V_300S_4D)
|| (BME680_BSEC_CONFIG == BME680_BSEC_CONFIG_GENERIC_18V_300S_4D)
|| (BME680_BSEC_CONFIG == BME680_BSEC_CONFIG_GENERIC_18V_300S_4D))
? BSEC_SAMPLE_RATE_ULP
: BSEC_SAMPLE_RATE_LP;
iaqSensor.updateSubscription(sensorList, 12, sampleRate);
iaqSensor.updateSubscription(
SensorList, std::size(SensorList), sampleRate);
if (!_isOk()) {
_showSensorErrors();
@ -157,30 +168,25 @@ class BME680Sensor : public I2CSensor<> {
}
// Descriptive name of the sensor
String description() {
String description() const override {
char buffer[21];
snprintf(buffer, sizeof(buffer), "BME680 @ I2C (0x%02X)", _address);
snprintf_P(buffer, sizeof(buffer),
PSTR("BME680 @ I2C (0x%02X)"), getAddress());
return String(buffer);
}
// Type for slot # index
unsigned char type(unsigned char index) {
if (index == 0) return MAGNITUDE_TEMPERATURE;
if (index == 1) return MAGNITUDE_HUMIDITY;
if (index == 2) return MAGNITUDE_PRESSURE;
if (index == 3) return MAGNITUDE_RESISTANCE;
if (index == 4) return MAGNITUDE_IAQ_ACCURACY;
if (index == 5) return MAGNITUDE_IAQ;
if (index == 6) return MAGNITUDE_IAQ_STATIC;
if (index == 7) return MAGNITUDE_CO2;
if (index == 8) return MAGNITUDE_VOC;
unsigned char type(unsigned char index) const override {
if (index < std::size(Magnitudes)) {
return Magnitudes[index].type;
}
return MAGNITUDE_NONE;
}
// The maximum allowed time between two `bsec_sensor_control` calls depends on
// configuration profile `bsec_config_iaq` below.
void tick() {
void tick() override {
if (iaqSensor.run()) {
_rawTemperature = iaqSensor.rawTemperature;
_rawHumidity = iaqSensor.rawHumidity;
@ -202,20 +208,33 @@ class BME680Sensor : public I2CSensor<> {
// Ensure we show any possible issues with the sensor, post() is called regardless of sensor status() / error() codes
void post() override {
_showSensorErrors();
_showSensorErrors();
}
// Current value for slot # index
double value(unsigned char index) {
if (index == 0) return _temperature;
if (index == 1) return _humidity;
if (index == 2) return _pressure;
if (index == 3) return _gasResistance;
if (index == 4) return _iaqAccuracy;
if (index == 5) return _iaq;
if (index == 6) return _iaqStatic;
if (index == 7) return _co2Equivalent;
if (index == 8) return _breathVocEquivalent;
double value(unsigned char index) override {
if (index < std::size(Magnitudes)) {
switch (Magnitudes[index].type) {
case MAGNITUDE_TEMPERATURE:
return _temperature;
case MAGNITUDE_HUMIDITY:
return _humidity;
case MAGNITUDE_PRESSURE:
return _pressure;
case MAGNITUDE_RESISTANCE:
return _gasResistance;
case MAGNITUDE_IAQ_ACCURACY:
return _iaqAccuracy;
case MAGNITUDE_IAQ:
return _iaq;
case MAGNITUDE_IAQ_STATIC:
return _iaqStatic;
case MAGNITUDE_CO2:
return _co2Equivalent;
case MAGNITUDE_VOC:
return _breathVocEquivalent;
}
}
return 0;
}
@ -223,46 +242,50 @@ class BME680Sensor : public I2CSensor<> {
protected:
void _loadState() {
String storedState = getSetting("bsecState");
auto storedState = getSetting("bsecState");
if (!storedState.length()) {
return;
}
DEBUG_MSG_P(PSTR("[BME680] Restoring previous state\n"));
hexDecode(storedState.c_str(), storedState.length(), _bsecState, sizeof(_bsecState));
if (hexDecode(storedState.c_str(), storedState.length(), _state, sizeof(_state))) {
DEBUG_MSG_P(PSTR("[BME680] Restoring saved state...\n"));
iaqSensor.setState(_bsecState);
_showSensorErrors();
iaqSensor.setState(_state);
_showSensorErrors();
}
}
void _saveState() {
if (!BME680_STATE_SAVE_INTERVAL) return;
static unsigned long last_millis = 0;
if (_iaqAccuracy < 3 || (millis() - last_millis < BME680_STATE_SAVE_INTERVAL)) {
if (!SaveInterval.count()) {
return;
}
iaqSensor.getState(_bsecState);
if (_iaqAccuracy < 3) {
return;
}
char storedState[BSEC_MAX_STATE_BLOB_SIZE * 2 + 1] = {0};
hexEncode(_bsecState, BSEC_MAX_STATE_BLOB_SIZE, storedState, sizeof(storedState));
const auto now = TimeSource::now();
if (now - _last_state < SaveInterval) {
return;
}
setSetting("bsecState", storedState);
iaqSensor.getState(_state);
setSetting("bsecState", hexEncode(_state));
last_millis = millis();
_last_state = now;
}
bool _isError() {
return (iaqSensor.status < BSEC_OK) || (iaqSensor.bme680Status < BME680_OK);
bool _isError() const {
return (iaqSensor.status < BSEC_OK)
|| (iaqSensor.bme680Status < BME680_OK);
}
bool _isOk() {
return (iaqSensor.status == BSEC_OK) && (iaqSensor.bme680Status == BME680_OK);
bool _isOk() const {
return (iaqSensor.status == BSEC_OK)
&& (iaqSensor.bme680Status == BME680_OK);
}
void _showSensorErrors() {
void _showSensorErrors() const {
// see `enum { ... } bsec_library_return_t` values & description at:
// BSEC Software Library/src/inc/bsec_datatypes.h
if (iaqSensor.status != BSEC_OK) {
@ -297,7 +320,7 @@ class BME680Sensor : public I2CSensor<> {
}
}
bsec_virtual_sensor_t sensorList[12] = {
bsec_virtual_sensor_t SensorList[12] = {
BSEC_OUTPUT_RAW_TEMPERATURE, // Unscaled (raw) temperature (ºC).
BSEC_OUTPUT_RAW_PRESSURE, // Unscaled (raw) pressure (Pa).
@ -331,21 +354,34 @@ class BME680Sensor : public I2CSensor<> {
// ongoing (0) or finished (1).
};
float _breathVocEquivalent = 0.0f;
float _co2Equivalent = 0.0f;
float _gasResistance = 0.0f;
float _temperature = 0.0f;
float _rawTemperature = 0.0f;
float _rawHumidity = 0.0f;
float _humidity = 0.0f;
float _iaq = 0.0f;
float _pressure = 0.0f;
float _rawHumidity = 0.0f;
float _rawTemperature = 0.0f;
float _temperature = 0.0f;
uint8_t _bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0};
float _gasResistance = 0.0f;
uint8_t _iaqAccuracy = 0;
float _iaq = 0.0f;
float _iaqStatic = 0;
float _breathVocEquivalent = 0.0f;
float _co2Equivalent = 0.0f;
using TimeSource = espurna::time::CoreClock;
static constexpr auto SaveInterval = TimeSource::duration { BME680_STATE_SAVE_INTERVAL };
TimeSource::time_point _last_state;
uint8_t _state[BSEC_MAX_STATE_BLOB_SIZE] = {0};
Bsec iaqSensor;
};
#if __cplusplus < 201703L
constexpr BaseSensor::Magnitude BME680Sensor::Magnitudes[];
#endif
#endif // SENSOR_SUPPORT && BME680_SUPPORT

Loading…
Cancel
Save