mirror of
https://github.com/esphome/esphome.git
synced 2024-11-27 09:18:00 +01:00
bme680_bsec: use BOSCH BSEC Library 1.8.1492
This commit is contained in:
parent
4c6a17e304
commit
366061b0f2
3 changed files with 118 additions and 83 deletions
|
@ -1,7 +1,7 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.components import i2c, esp32
|
from esphome.components import i2c, esp32
|
||||||
from esphome.const import CONF_ID, CONF_SAMPLE_RATE, CONF_TEMPERATURE_OFFSET
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
CODEOWNERS = ["@trvrnrth"]
|
CODEOWNERS = ["@trvrnrth"]
|
||||||
DEPENDENCIES = ["i2c"]
|
DEPENDENCIES = ["i2c"]
|
||||||
|
@ -9,8 +9,10 @@ AUTO_LOAD = ["sensor", "text_sensor"]
|
||||||
MULTI_CONF = True
|
MULTI_CONF = True
|
||||||
|
|
||||||
CONF_BME680_BSEC_ID = "bme680_bsec_id"
|
CONF_BME680_BSEC_ID = "bme680_bsec_id"
|
||||||
|
CONF_TEMPERATURE_OFFSET = "temperature_offset"
|
||||||
CONF_IAQ_MODE = "iaq_mode"
|
CONF_IAQ_MODE = "iaq_mode"
|
||||||
CONF_SUPPLY_VOLTAGE = "supply_voltage"
|
CONF_SUPPLY_VOLTAGE = "supply_voltage"
|
||||||
|
CONF_SAMPLE_RATE = "sample_rate"
|
||||||
CONF_STATE_SAVE_INTERVAL = "state_save_interval"
|
CONF_STATE_SAVE_INTERVAL = "state_save_interval"
|
||||||
|
|
||||||
bme680_bsec_ns = cg.esphome_ns.namespace("bme680_bsec")
|
bme680_bsec_ns = cg.esphome_ns.namespace("bme680_bsec")
|
||||||
|
@ -85,4 +87,4 @@ async def to_code(config):
|
||||||
cg.add_library("SPI", None)
|
cg.add_library("SPI", None)
|
||||||
|
|
||||||
cg.add_define("USE_BSEC")
|
cg.add_define("USE_BSEC")
|
||||||
cg.add_library("boschsensortec/BSEC Software Library", "1.6.1480")
|
cg.add_library("boschsensortec/BSEC Software Library", "1.8.1492")
|
||||||
|
|
|
@ -15,27 +15,24 @@ std::vector<BME680BSECComponent *>
|
||||||
uint8_t BME680BSECComponent::work_buffer_[BSEC_MAX_WORKBUFFER_SIZE] = {0};
|
uint8_t BME680BSECComponent::work_buffer_[BSEC_MAX_WORKBUFFER_SIZE] = {0};
|
||||||
|
|
||||||
void BME680BSECComponent::setup() {
|
void BME680BSECComponent::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Setting up BME680(%s) via BSEC...", this->device_id_.c_str());
|
ESP_LOGCONFIG(TAG, "Setting up BME68x(%s) via BSEC...", this->device_id_.c_str());
|
||||||
|
|
||||||
uint8_t new_idx = BME680BSECComponent::instances.size();
|
uint8_t new_idx = BME680BSECComponent::instances.size();
|
||||||
BME680BSECComponent::instances.push_back(this);
|
BME680BSECComponent::instances.push_back(this);
|
||||||
|
|
||||||
this->bsec_state_data_valid_ = false;
|
this->bsec_state_data_valid_ = false;
|
||||||
|
|
||||||
// Initialize the bme680_ structure (passed-in to the bme680_* functions) and the BME680 device
|
// Initialize the bme68x_ structure (passed-in to the bme68x_* functions) and the BME68x device
|
||||||
this->bme680_.dev_id =
|
this->bme68x_.intf_ptr =
|
||||||
new_idx; // This is a "Place holder to store the id of the device structure" (see bme680_defs.h).
|
this; // This will be passed-in as last parameter to the next "read" and "write" function pointers.
|
||||||
// This will be passed-in as first parameter to the next "read" and "write" function pointers.
|
this->bme68x_.intf = BME68X_I2C_INTF; // We currently only support I2C interface
|
||||||
// We currently use the index of the object in the BME680BSECComponent::instances vector to identify
|
this->bme68x_.read = BME680BSECComponent::read_bytes_wrapper;
|
||||||
// the different devices in the system.
|
this->bme68x_.write = BME680BSECComponent::write_bytes_wrapper;
|
||||||
this->bme680_.intf = BME680_I2C_INTF;
|
this->bme68x_.delay_us = BME680BSECComponent::delay_us;
|
||||||
this->bme680_.read = BME680BSECComponent::read_bytes_wrapper;
|
this->bme68x_.amb_temp = 25;
|
||||||
this->bme680_.write = BME680BSECComponent::write_bytes_wrapper;
|
|
||||||
this->bme680_.delay_ms = BME680BSECComponent::delay_ms;
|
|
||||||
this->bme680_.amb_temp = 25;
|
|
||||||
|
|
||||||
this->bme680_status_ = bme680_init(&this->bme680_);
|
this->bme68x_status_ = bme68x_init(&this->bme68x_);
|
||||||
if (this->bme680_status_ != BME680_OK) {
|
if (this->bme68x_status_ != BME68X_OK) {
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -155,8 +152,8 @@ void BME680BSECComponent::dump_config() {
|
||||||
LOG_I2C_DEVICE(this);
|
LOG_I2C_DEVICE(this);
|
||||||
|
|
||||||
if (this->is_failed()) {
|
if (this->is_failed()) {
|
||||||
ESP_LOGE(TAG, "Communication failed (BSEC Status: %d, BME680 Status: %d)", this->bsec_status_,
|
ESP_LOGE(TAG, "Communication failed (BSEC Status: %d, BME68x Status: %d)", this->bsec_status_,
|
||||||
this->bme680_status_);
|
this->bme68x_status_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGCONFIG(TAG, " Temperature Offset: %.2f", this->temperature_offset_);
|
ESP_LOGCONFIG(TAG, " Temperature Offset: %.2f", this->temperature_offset_);
|
||||||
|
@ -184,12 +181,12 @@ float BME680BSECComponent::get_setup_priority() const { return setup_priority::D
|
||||||
void BME680BSECComponent::loop() {
|
void BME680BSECComponent::loop() {
|
||||||
this->run_();
|
this->run_();
|
||||||
|
|
||||||
if (this->bsec_status_ < BSEC_OK || this->bme680_status_ < BME680_OK) {
|
if (this->bsec_status_ < BSEC_OK || this->bme68x_status_ < BME68X_OK) {
|
||||||
this->status_set_error();
|
this->status_set_error();
|
||||||
} else {
|
} else {
|
||||||
this->status_clear_error();
|
this->status_clear_error();
|
||||||
}
|
}
|
||||||
if (this->bsec_status_ > BSEC_OK || this->bme680_status_ > BME680_OK) {
|
if (this->bsec_status_ > BSEC_OK || this->bme68x_status_ > BME68X_OK) {
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
} else {
|
} else {
|
||||||
this->status_clear_warning();
|
this->status_clear_warning();
|
||||||
|
@ -221,36 +218,50 @@ void BME680BSECComponent::run_() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->bsec_status_ = bsec_sensor_control(curr_time_ns, &this->bme680_settings_);
|
this->bsec_status_ = bsec_sensor_control(curr_time_ns, &this->bseclib_settings_);
|
||||||
if (this->bsec_status_ < BSEC_OK) {
|
if (this->bsec_status_ < BSEC_OK) {
|
||||||
ESP_LOGW(TAG, "Failed to fetch sensor control settings (BSEC Error Code %d)", this->bsec_status_);
|
ESP_LOGW(TAG, "Failed to fetch sensor control settings (BSEC Error Code %d)", this->bsec_status_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->next_call_ns_ = this->bme680_settings_.next_call;
|
this->next_call_ns_ = this->bseclib_settings_.next_call;
|
||||||
|
|
||||||
if (this->bme680_settings_.trigger_measurement) {
|
if (this->bseclib_settings_.trigger_measurement) {
|
||||||
this->bme680_.tph_sett.os_temp = this->bme680_settings_.temperature_oversampling;
|
// Time to perform a new measurement
|
||||||
this->bme680_.tph_sett.os_pres = this->bme680_settings_.pressure_oversampling;
|
|
||||||
this->bme680_.tph_sett.os_hum = this->bme680_settings_.humidity_oversampling;
|
// Set general sensor configuration
|
||||||
this->bme680_.gas_sett.run_gas = this->bme680_settings_.run_gas;
|
struct bme68x_conf bme68x_general_conf;
|
||||||
this->bme680_.gas_sett.heatr_temp = this->bme680_settings_.heater_temperature;
|
bme68x_general_conf.os_temp = this->bseclib_settings_.temperature_oversampling;
|
||||||
this->bme680_.gas_sett.heatr_dur = this->bme680_settings_.heating_duration;
|
bme68x_general_conf.os_pres = this->bseclib_settings_.pressure_oversampling;
|
||||||
this->bme680_.power_mode = BME680_FORCED_MODE;
|
bme68x_general_conf.os_hum = this->bseclib_settings_.humidity_oversampling;
|
||||||
uint16_t desired_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_GAS_SENSOR_SEL;
|
bme68x_general_conf.filter = BME68X_FILTER_OFF;
|
||||||
this->bme680_status_ = bme680_set_sensor_settings(desired_settings, &this->bme680_);
|
bme68x_general_conf.odr = BME68X_ODR_NONE;
|
||||||
if (this->bme680_status_ != BME680_OK) {
|
this->bme68x_status_ = bme68x_set_conf(&bme68x_general_conf, &this->bme68x_);
|
||||||
ESP_LOGW(TAG, "Failed to set sensor settings (BME680 Error Code %d)", this->bme680_status_);
|
if (this->bme68x_status_ != BME68X_OK) {
|
||||||
|
ESP_LOGW(TAG, "Failed to set general sensor config (BME68x Error Code %d)", this->bme68x_status_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->bme680_status_ = bme680_set_sensor_mode(&this->bme680_);
|
// Set heater configuration
|
||||||
if (this->bme680_status_ != BME680_OK) {
|
struct bme68x_heatr_conf bme68x_heater_conf;
|
||||||
ESP_LOGW(TAG, "Failed to set sensor mode (BME680 Error Code %d)", this->bme680_status_);
|
bme68x_heater_conf.enable = this->bseclib_settings_.run_gas;
|
||||||
|
bme68x_heater_conf.heatr_temp = this->bseclib_settings_.heater_temperature;
|
||||||
|
bme68x_heater_conf.heatr_dur = this->bseclib_settings_.heating_duration;
|
||||||
|
this->bme68x_status_ = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &bme68x_heater_conf, &this->bme68x_);
|
||||||
|
if (this->bme68x_status_ != BME68X_OK) {
|
||||||
|
ESP_LOGW(TAG, "Failed to set gas sensor config (BME68x Error Code %d)", this->bme68x_status_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t meas_dur = 0;
|
// Set sensor operation mode
|
||||||
bme680_get_profile_dur(&meas_dur, &this->bme680_);
|
this->bme68x_status_ = bme68x_set_op_mode(BME68X_FORCED_MODE, &this->bme68x_);
|
||||||
|
if (this->bme68x_status_ != BME68X_OK) {
|
||||||
|
ESP_LOGW(TAG, "Failed to set sensor mode (BME68x Error Code %d)", this->bme68x_status_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate time for the measurement to be ready
|
||||||
|
uint32_t meas_dur_us = bme68x_get_meas_dur(BME68X_FORCED_MODE, &bme68x_general_conf, &this->bme68x_) +
|
||||||
|
bme68x_heater_conf.heatr_dur * 1000;
|
||||||
|
|
||||||
// Since we are about to go "out of scope" in the loop, take a snapshot of the state now so we can restore it later
|
// Since we are about to go "out of scope" in the loop, take a snapshot of the state now so we can restore it later
|
||||||
// TODO: it would be interesting to see if this is really needed here, or if it's needed only after each
|
// TODO: it would be interesting to see if this is really needed here, or if it's needed only after each
|
||||||
|
@ -258,6 +269,8 @@ void BME680BSECComponent::run_() {
|
||||||
if (BME680BSECComponent::instances.size() > 1)
|
if (BME680BSECComponent::instances.size() > 1)
|
||||||
this->snapshot_state_();
|
this->snapshot_state_();
|
||||||
|
|
||||||
|
// Queuing read for later, so ESPHome can do something more productive in the meantime
|
||||||
|
uint32_t meas_dur = meas_dur_us / 1000;
|
||||||
ESP_LOGV(TAG, "Queueing read in %ums", meas_dur);
|
ESP_LOGV(TAG, "Queueing read in %ums", meas_dur);
|
||||||
this->set_timeout("read", meas_dur, [this]() { this->read_(); });
|
this->set_timeout("read", meas_dur, [this]() { this->read_(); });
|
||||||
} else {
|
} else {
|
||||||
|
@ -270,67 +283,85 @@ void BME680BSECComponent::read_() {
|
||||||
ESP_LOGV(TAG, "%s: Reading data", this->device_id_.c_str());
|
ESP_LOGV(TAG, "%s: Reading data", this->device_id_.c_str());
|
||||||
int64_t curr_time_ns = this->get_time_ns_();
|
int64_t curr_time_ns = this->get_time_ns_();
|
||||||
|
|
||||||
if (this->bme680_settings_.trigger_measurement) {
|
if (this->bseclib_settings_.trigger_measurement) {
|
||||||
while (this->bme680_.power_mode != BME680_SLEEP_MODE) {
|
uint8_t op_mode = BME68X_FORCED_MODE;
|
||||||
this->bme680_status_ = bme680_get_sensor_mode(&this->bme680_);
|
while (op_mode != BME68X_SLEEP_MODE) {
|
||||||
if (this->bme680_status_ != BME680_OK) {
|
this->bme68x_status_ = bme68x_get_op_mode(&op_mode, &this->bme68x_);
|
||||||
ESP_LOGW(TAG, "Failed to get sensor mode (BME680 Error Code %d)", this->bme680_status_);
|
if (this->bme68x_status_ != BME68X_OK) {
|
||||||
|
ESP_LOGW(TAG, "Failed to get sensor mode (BME68x Error Code %d)", this->bme68x_status_);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->bme680_settings_.process_data) {
|
if (!this->bseclib_settings_.process_data) {
|
||||||
ESP_LOGV(TAG, "Data processing not required");
|
ESP_LOGV(TAG, "Data processing not required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bme680_field_data data;
|
struct bme68x_data data;
|
||||||
this->bme680_status_ = bme680_get_sensor_data(&data, &this->bme680_);
|
uint8_t data_count = 0;
|
||||||
|
this->bme68x_status_ = bme68x_get_data(BME68X_FORCED_MODE, &data, &data_count, &this->bme68x_);
|
||||||
if (this->bme680_status_ != BME680_OK) {
|
if (this->bme68x_status_ != BME68X_OK) {
|
||||||
ESP_LOGW(TAG, "Failed to get sensor data (BME680 Error Code %d)", this->bme680_status_);
|
ESP_LOGW(TAG, "Failed to get sensor data (BME68x Error Code %d)", this->bme68x_status_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(data.status & BME680_NEW_DATA_MSK)) {
|
if (!(data.status & BME68X_NEW_DATA_MSK)) {
|
||||||
ESP_LOGD(TAG, "BME680 did not report new data");
|
ESP_LOGD(TAG, "BME68x did not report new data");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temperature, Pressure, Humidity & Gas Resistance
|
bsec_input_t
|
||||||
|
inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temperature, Temperature offset, Pressure, Humidity & Gas Resistance
|
||||||
uint8_t num_inputs = 0;
|
uint8_t num_inputs = 0;
|
||||||
|
|
||||||
if (this->bme680_settings_.process_data & BSEC_PROCESS_TEMPERATURE) {
|
if (this->bseclib_settings_.process_data & BSEC_PROCESS_TEMPERATURE) {
|
||||||
inputs[num_inputs].sensor_id = BSEC_INPUT_TEMPERATURE;
|
inputs[num_inputs].sensor_id = BSEC_INPUT_TEMPERATURE;
|
||||||
inputs[num_inputs].signal = data.temperature / 100.0f;
|
inputs[num_inputs].signal = data.temperature;
|
||||||
inputs[num_inputs].time_stamp = curr_time_ns;
|
inputs[num_inputs].time_stamp = curr_time_ns;
|
||||||
|
ESP_LOGV(TAG, "%s: BSEC In[%d](Temperature)=%f", this->device_id_.c_str(), num_inputs, inputs[num_inputs].signal);
|
||||||
num_inputs++;
|
num_inputs++;
|
||||||
|
|
||||||
// Temperature offset from the real temperature due to external heat sources
|
// Temperature offset from the real temperature due to external heat sources
|
||||||
inputs[num_inputs].sensor_id = BSEC_INPUT_HEATSOURCE;
|
inputs[num_inputs].sensor_id = BSEC_INPUT_HEATSOURCE;
|
||||||
inputs[num_inputs].signal = this->temperature_offset_;
|
inputs[num_inputs].signal = this->temperature_offset_;
|
||||||
inputs[num_inputs].time_stamp = curr_time_ns;
|
inputs[num_inputs].time_stamp = curr_time_ns;
|
||||||
|
ESP_LOGV(TAG, "%s: BSEC In[%d](TemperatureOffset)=%f", this->device_id_.c_str(), num_inputs,
|
||||||
|
inputs[num_inputs].signal);
|
||||||
num_inputs++;
|
num_inputs++;
|
||||||
}
|
}
|
||||||
if (this->bme680_settings_.process_data & BSEC_PROCESS_HUMIDITY) {
|
if (this->bseclib_settings_.process_data & BSEC_PROCESS_HUMIDITY) {
|
||||||
inputs[num_inputs].sensor_id = BSEC_INPUT_HUMIDITY;
|
inputs[num_inputs].sensor_id = BSEC_INPUT_HUMIDITY;
|
||||||
inputs[num_inputs].signal = data.humidity / 1000.0f;
|
inputs[num_inputs].signal =
|
||||||
|
data.humidity; // Comment in struct bme68x_data wrongly states that humidity unit is %RH x1000, but inspecting
|
||||||
|
// the data when using float type the unit is plain %RH
|
||||||
inputs[num_inputs].time_stamp = curr_time_ns;
|
inputs[num_inputs].time_stamp = curr_time_ns;
|
||||||
|
ESP_LOGV(TAG, "%s: BSEC In[%d](Humidity)=%f", this->device_id_.c_str(), num_inputs, inputs[num_inputs].signal);
|
||||||
num_inputs++;
|
num_inputs++;
|
||||||
}
|
}
|
||||||
if (this->bme680_settings_.process_data & BSEC_PROCESS_PRESSURE) {
|
if (this->bseclib_settings_.process_data & BSEC_PROCESS_PRESSURE) {
|
||||||
inputs[num_inputs].sensor_id = BSEC_INPUT_PRESSURE;
|
inputs[num_inputs].sensor_id = BSEC_INPUT_PRESSURE;
|
||||||
inputs[num_inputs].signal = data.pressure;
|
inputs[num_inputs].signal = data.pressure;
|
||||||
inputs[num_inputs].time_stamp = curr_time_ns;
|
inputs[num_inputs].time_stamp = curr_time_ns;
|
||||||
|
ESP_LOGV(TAG, "%s: BSEC In[%d](Pressure)=%f", this->device_id_.c_str(), num_inputs, inputs[num_inputs].signal);
|
||||||
num_inputs++;
|
num_inputs++;
|
||||||
}
|
}
|
||||||
if (this->bme680_settings_.process_data & BSEC_PROCESS_GAS) {
|
if (this->bseclib_settings_.process_data & BSEC_PROCESS_GAS) {
|
||||||
if (data.status & BME680_GASM_VALID_MSK) {
|
if (data.status & BME68X_GASM_VALID_MSK) {
|
||||||
inputs[num_inputs].sensor_id = BSEC_INPUT_GASRESISTOR;
|
inputs[num_inputs].sensor_id = BSEC_INPUT_GASRESISTOR;
|
||||||
inputs[num_inputs].signal = data.gas_resistance;
|
inputs[num_inputs].signal = min(
|
||||||
|
data.gas_resistance,
|
||||||
|
12800000.0f); // Limit the maximum value to avoid BSEC error -2 (BSEC_E_DOSTEPS_VALUELIMITS)
|
||||||
|
// Starting with clean calibration data, a sensor has been observed generating constant gas
|
||||||
|
// resistance values at 12917167, which then decreased over time. A signal value at 12800001.0f
|
||||||
|
// results in the BSEC library v1.8.1492 returning error -2 (BSEC_E_DOSTEPS_VALUELIMITS).
|
||||||
|
// 12800000 and below are OK; no problem at all in BSEC v1.6.1480
|
||||||
inputs[num_inputs].time_stamp = curr_time_ns;
|
inputs[num_inputs].time_stamp = curr_time_ns;
|
||||||
|
ESP_LOGV(TAG, "%s: BSEC In[%d](GasResistance)=%f (original=%f)", this->device_id_.c_str(), num_inputs,
|
||||||
|
inputs[num_inputs].signal, data.gas_resistance);
|
||||||
num_inputs++;
|
num_inputs++;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGD(TAG, "BME680 did not report gas data");
|
ESP_LOGD(TAG, "BME68x did not report gas data");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (num_inputs < 1) {
|
if (num_inputs < 1) {
|
||||||
|
@ -346,8 +377,8 @@ void BME680BSECComponent::read_() {
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
return;
|
return;
|
||||||
// Now that the BSEC library has been re-initialized, bsec_sensor_control *NEEDS* to be called in order to support
|
// Now that the BSEC library has been re-initialized, bsec_sensor_control *NEEDS* to be called in order to support
|
||||||
// multiple devices with a different set of enabled sensors (even if the bme680_settings_ data is not used)
|
// multiple devices with a different set of enabled sensors (even if the bseclib_settings_ data is not used)
|
||||||
this->bsec_status_ = bsec_sensor_control(curr_time_ns, &this->bme680_settings_);
|
this->bsec_status_ = bsec_sensor_control(curr_time_ns, &this->bseclib_settings_);
|
||||||
if (this->bsec_status_ < BSEC_OK) {
|
if (this->bsec_status_ < BSEC_OK) {
|
||||||
ESP_LOGW(TAG, "Failed to fetch sensor control settings (BSEC Error Code %d)", this->bsec_status_);
|
ESP_LOGW(TAG, "Failed to fetch sensor control settings (BSEC Error Code %d)", this->bsec_status_);
|
||||||
return;
|
return;
|
||||||
|
@ -440,24 +471,26 @@ void BME680BSECComponent::publish_sensor_(text_sensor::TextSensor *sensor, const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Communication function - read
|
// Communication function - read
|
||||||
// First parameter is the "dev_id" member of our "bme680_" object, which is passed-back here as-is
|
// Last parameter is a pointer to our BME680BSECComponent object, which is passed-back here as-is
|
||||||
int8_t BME680BSECComponent::read_bytes_wrapper(uint8_t devid, uint8_t a_register, uint8_t *data, uint16_t len) {
|
BME68X_INTF_RET_TYPE BME680BSECComponent::read_bytes_wrapper(uint8_t reg_addr, uint8_t *reg_data, uint32_t len,
|
||||||
BME680BSECComponent *inst = instances[devid];
|
void *ptr) {
|
||||||
|
BME680BSECComponent *inst = (BME680BSECComponent *) ptr;
|
||||||
// Use the I2CDevice::read_bytes method to perform the actual I2C register read
|
// Use the I2CDevice::read_bytes method to perform the actual I2C register read
|
||||||
return inst->read_bytes(a_register, data, len) ? 0 : -1;
|
return inst->read_bytes(reg_addr, reg_data, len) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Communication function - write
|
// Communication function - write
|
||||||
// First parameter is the "dev_id" member of our "bme680_" object, which is passed-back here as-is
|
// Last parameter is a pointer to our BME680BSECComponent object, which is passed-back here as-is
|
||||||
int8_t BME680BSECComponent::write_bytes_wrapper(uint8_t devid, uint8_t a_register, uint8_t *data, uint16_t len) {
|
BME68X_INTF_RET_TYPE BME680BSECComponent::write_bytes_wrapper(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len,
|
||||||
BME680BSECComponent *inst = instances[devid];
|
void *ptr) {
|
||||||
|
BME680BSECComponent *inst = (BME680BSECComponent *) ptr;
|
||||||
// Use the I2CDevice::write_bytes method to perform the actual I2C register write
|
// Use the I2CDevice::write_bytes method to perform the actual I2C register write
|
||||||
return inst->write_bytes(a_register, data, len) ? 0 : -1;
|
return inst->write_bytes(reg_addr, reg_data, len) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BME680BSECComponent::delay_ms(uint32_t period) {
|
void BME680BSECComponent::delay_us(uint32_t period, void *ptr) {
|
||||||
ESP_LOGV(TAG, "Delaying for %ums", period);
|
ESP_LOGV(TAG, "Delaying for %uus", period);
|
||||||
delay(period);
|
delay_microseconds_safe(period);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the BSEC library state and save it in the bsec_state_data_ member (volatile memory)
|
// Fetch the BSEC library state and save it in the bsec_state_data_ member (volatile memory)
|
||||||
|
@ -515,7 +548,7 @@ int BME680BSECComponent::reinit_bsec_lib_() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BME680BSECComponent::load_state_() {
|
void BME680BSECComponent::load_state_() {
|
||||||
uint32_t hash = fnv1_hash("bme680_bsec_state_" + this->device_id_);
|
uint32_t hash = fnv1_hash("bme68x_bsec_state_" + this->device_id_);
|
||||||
this->bsec_state_ = global_preferences->make_preference<uint8_t[BSEC_MAX_STATE_BLOB_SIZE]>(hash, true);
|
this->bsec_state_ = global_preferences->make_preference<uint8_t[BSEC_MAX_STATE_BLOB_SIZE]>(hash, true);
|
||||||
|
|
||||||
if (!this->bsec_state_.load(&this->bsec_state_data_)) {
|
if (!this->bsec_state_.load(&this->bsec_state_data_)) {
|
||||||
|
|
|
@ -58,9 +58,9 @@ class BME680BSECComponent : public Component, public i2c::I2CDevice {
|
||||||
void set_breath_voc_equivalent_sensor(sensor::Sensor *sensor) { this->breath_voc_equivalent_sensor_ = sensor; }
|
void set_breath_voc_equivalent_sensor(sensor::Sensor *sensor) { this->breath_voc_equivalent_sensor_ = sensor; }
|
||||||
|
|
||||||
static std::vector<BME680BSECComponent *> instances;
|
static std::vector<BME680BSECComponent *> instances;
|
||||||
static int8_t read_bytes_wrapper(uint8_t devid, uint8_t a_register, uint8_t *data, uint16_t len);
|
static BME68X_INTF_RET_TYPE read_bytes_wrapper(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *ptr);
|
||||||
static int8_t write_bytes_wrapper(uint8_t devid, uint8_t a_register, uint8_t *data, uint16_t len);
|
static BME68X_INTF_RET_TYPE write_bytes_wrapper(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *ptr);
|
||||||
static void delay_ms(uint32_t period);
|
static void delay_us(uint32_t period, void *ptr);
|
||||||
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
@ -95,9 +95,9 @@ class BME680BSECComponent : public Component, public i2c::I2CDevice {
|
||||||
void queue_push_(std::function<void()> &&f) { this->queue_.push(std::move(f)); }
|
void queue_push_(std::function<void()> &&f) { this->queue_.push(std::move(f)); }
|
||||||
|
|
||||||
static uint8_t work_buffer_[BSEC_MAX_WORKBUFFER_SIZE];
|
static uint8_t work_buffer_[BSEC_MAX_WORKBUFFER_SIZE];
|
||||||
struct bme680_dev bme680_;
|
struct bme68x_dev bme68x_;
|
||||||
bsec_library_return_t bsec_status_{BSEC_OK};
|
bsec_library_return_t bsec_status_{BSEC_OK};
|
||||||
int8_t bme680_status_{BME680_OK};
|
int8_t bme68x_status_{BME68X_OK};
|
||||||
|
|
||||||
int64_t last_time_ms_{0};
|
int64_t last_time_ms_{0};
|
||||||
uint32_t millis_overflow_counter_{0};
|
uint32_t millis_overflow_counter_{0};
|
||||||
|
@ -109,8 +109,8 @@ class BME680BSECComponent : public Component, public i2c::I2CDevice {
|
||||||
uint8_t bsec_state_data_[BSEC_MAX_STATE_BLOB_SIZE]; // This is the current snapshot of the BSEC library state
|
uint8_t bsec_state_data_[BSEC_MAX_STATE_BLOB_SIZE]; // This is the current snapshot of the BSEC library state
|
||||||
ESPPreferenceObject bsec_state_;
|
ESPPreferenceObject bsec_state_;
|
||||||
uint32_t state_save_interval_ms_{21600000}; // 6 hours - 4 times a day
|
uint32_t state_save_interval_ms_{21600000}; // 6 hours - 4 times a day
|
||||||
uint32_t last_state_save_ms_ = 0;
|
uint32_t last_state_save_ms_{0};
|
||||||
bsec_bme_settings_t bme680_settings_;
|
bsec_bme_settings_t bseclib_settings_;
|
||||||
|
|
||||||
std::string device_id_;
|
std::string device_id_;
|
||||||
float temperature_offset_{0};
|
float temperature_offset_{0};
|
||||||
|
|
Loading…
Reference in a new issue