8static const char *
const TAG =
"bme680.sensor";
10static const uint8_t BME680_REGISTER_COEFF1 = 0x89;
11static const uint8_t BME680_REGISTER_COEFF2 = 0xE1;
13static const uint8_t BME680_REGISTER_CONFIG = 0x75;
14static const uint8_t BME680_REGISTER_CONTROL_MEAS = 0x74;
15static const uint8_t BME680_REGISTER_CONTROL_HUMIDITY = 0x72;
16static const uint8_t BME680_REGISTER_CONTROL_GAS1 = 0x71;
17static const uint8_t BME680_REGISTER_CONTROL_GAS0 = 0x70;
18static const uint8_t BME680_REGISTER_HEATER_HEAT0 = 0x5A;
19static const uint8_t BME680_REGISTER_HEATER_WAIT0 = 0x64;
21static const uint8_t BME680_REGISTER_CHIPID = 0xD0;
23static const uint8_t BME680_REGISTER_FIELD0 = 0x1D;
25const float BME680_GAS_LOOKUP_TABLE_1[16]
PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8,
26 0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0};
28const float BME680_GAS_LOOKUP_TABLE_2[16]
PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8,
29 -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
32 switch (oversampling) {
74 ESP_LOGCONFIG(TAG,
"Setting up BME680...");
76 if (!this->
read_byte(BME680_REGISTER_CHIPID, &chip_id) || chip_id != 0x61) {
83 if (!this->
read_bytes(BME680_REGISTER_COEFF1, cal1, 25)) {
88 if (!this->
read_bytes(BME680_REGISTER_COEFF2, cal2, 16)) {
120 uint8_t temp_var = 0;
142 uint8_t config_register;
143 if (!this->
read_byte(BME680_REGISTER_CONFIG, &config_register)) {
147 config_register &= ~0b00011100;
148 config_register |= (this->
iir_filter_ & 0b111) << 2;
149 if (!this->
write_byte(BME680_REGISTER_CONFIG, config_register)) {
156 if (!this->
read_byte(BME680_REGISTER_CONTROL_HUMIDITY, &hum_control)) {
160 hum_control &= ~0b00000111;
162 if (!this->
write_byte(BME680_REGISTER_CONTROL_HUMIDITY, hum_control)) {
168 uint8_t gas1_control;
169 if (!this->
read_byte(BME680_REGISTER_CONTROL_GAS1, &gas1_control)) {
173 gas1_control &= ~0b00011111;
174 gas1_control |= 1 << 4;
176 if (!this->
write_byte(BME680_REGISTER_CONTROL_GAS1, gas1_control)) {
184 uint8_t gas0_control;
185 if (!this->
read_byte(BME680_REGISTER_CONTROL_GAS0, &gas0_control)) {
189 gas0_control &= ~0b00001000;
190 gas0_control |= heat_off << 3;
191 if (!this->
write_byte(BME680_REGISTER_CONTROL_GAS0, gas0_control)) {
215 ESP_LOGCONFIG(TAG,
"BME680:");
216 LOG_I2C_DEVICE(
this);
218 ESP_LOGE(TAG,
"Communication with BME680 failed!");
220 ESP_LOGCONFIG(TAG,
" IIR Filter: %s", iir_filter_to_str(this->
iir_filter_));
221 LOG_UPDATE_INTERVAL(
this);
231 ESP_LOGCONFIG(TAG,
" Heater OFF");
240 uint8_t meas_control = 0;
243 meas_control |= 0b01;
244 if (!this->
write_byte(BME680_REGISTER_CONTROL_MEAS, meas_control)) {
271 int32_t heatr_res_x100;
273 var1 = (((int32_t) ambient_temperature * gh3) / 1000) * 256;
274 var2 = (gh1 + 784) * (((((gh2 + 154009) *
temperature * 5) / 100) + 3276800) / 10);
275 var3 = var1 + (var2 / 2);
276 var4 = (var3 / (res_heat_range + 4));
277 var5 = (131 * res_heat_val) + 65536;
278 heatr_res_x100 = (int32_t) (((var4 / var5) - 250) * 34);
279 heatr_res = (uint8_t) ((heatr_res_x100 + 50) / 100);
285 uint8_t duration_value;
288 duration_value = 0xff;
294 duration_value =
duration + (factor * 64);
297 return duration_value;
301 if (!this->
read_bytes(BME680_REGISTER_FIELD0, data, 15)) {
310 ESP_LOGW(TAG,
"Communication with BME680 failed!");
316 uint32_t raw_temperature = (uint32_t(data[5]) << 12) | (uint32_t(data[6]) << 4) | (uint32_t(data[7]) >> 4);
317 uint32_t raw_pressure = (uint32_t(data[2]) << 12) | (uint32_t(data[3]) << 4) | (uint32_t(data[4]) >> 4);
318 uint32_t raw_humidity = (uint32_t(data[8]) << 8) | uint32_t(data[9]);
319 uint16_t raw_gas = (uint16_t) ((uint32_t) data[13] * 4 | (((uint32_t) data[14]) / 64));
320 uint8_t gas_range = data[14] & 0x0F;
327 bool gas_valid = (data[14] >> 5) & 1;
328 bool heat_stable = (data[14] >> 4) & 1;
332 ESP_LOGD(TAG,
"Got temperature=%.1f°C pressure=%.1fhPa humidity=%.1f%% gas_resistance=%.1fΩ",
temperature,
pressure,
333 humidity, gas_resistance);
335 ESP_LOGW(TAG,
"Gas measurement unsuccessful, reading invalid!");
337 ESP_LOGW(TAG,
"Heater unstable, reading invalid! (Normal for a few readings after a power cycle)");
346 if (gas_valid && heat_stable) {
360 float temp_adc = raw_temperature;
367 var1 = ((temp_adc / 16384.0f) - (t1 / 1024.0f)) * t2;
370 var3 = (temp_adc / 131072.0f) - (t1 / 8192.0f);
371 var2 = var3 * var3 * t3 * 16.0f;
400 var1 = (tfine / 2.0f) - 64000.0f;
401 var2 = var1 * var1 * (p6 / 131072.0f);
402 var2 = var2 + var1 * p5 * 2.0f;
403 var2 = (var2 / 4.0f) + (p4 * 65536.0f);
404 var1 = (((p3 * var1 * var1) / 16384.0f) + (p2 * var1)) / 524288.0f;
405 var1 = (1.0f + (var1 / 32768.0f)) * p1;
406 calc_pres = 1048576.0f - float(raw_pressure);
409 if (
int(var1) != 0) {
410 calc_pres = ((calc_pres - (var2 / 4096.0f)) * 6250.0f) / var1;
411 var1 = (p9 * calc_pres * calc_pres) / 2147483648.0f;
412 var2 = calc_pres * (p8 / 32768.0f);
413 var4 = calc_pres / 256.0f;
414 var3 = var4 * var4 * var4 * (p10 / 131072.0f);
415 calc_pres = calc_pres + (var1 + var2 + var3 + (p7 * 128.0f)) / 16.0f;
420 return calc_pres / 100.0f;
441 temp_comp = tfine / 5120.0f;
443 var1 = float(raw_humidity) - (h1 * 16.0f + ((h3 / 2.0f) * temp_comp));
445 (((h2 / 262144.0f) * (1.0f + ((h4 / 16384.0f) * temp_comp) + ((h5 / 1048576.0f) * temp_comp * temp_comp))));
446 var3 = h6 / 16384.0f;
447 var4 = h7 / 2097152.0f;
449 calc_hum = var2 + (var3 + var4 * temp_comp) * var2 * var2;
451 if (calc_hum > 100.0f) {
453 }
else if (calc_hum < 0.0f) {
464 float raw_gas_f = raw_gas;
465 float range_f = 1U <<
range;
468 var1 = 1340.0f + (5.0f * range_sw_err);
469 var2 = var1 * (1.0f + BME680_GAS_LOOKUP_TABLE_1[
range] / 100.0f);
470 var3 = 1.0f + (BME680_GAS_LOOKUP_TABLE_2[
range] / 100.0f);
472 calc_gas_res = 1.0f / (var3 * 0.000000125f * range_f * (((raw_gas_f - 512.0f) / var2) + 1.0f));
478 uint32_t meas_cycles;
479 const uint8_t os_to_meas_cycles[6] = {0, 1, 2, 4, 8, 16};
486 tph_dur = meas_cycles * 1963u;
virtual void mark_failed()
Mark this component as failed.
void status_set_warning(const char *message="unspecified")
void status_clear_warning()
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
uint8_t calc_heater_duration_(uint16_t duration)
Calculate the heater duration value to send to the BME680 register.
void read_data_()
Read data from the BME680 and publish results.
sensor::Sensor * humidity_sensor_
uint8_t calc_heater_resistance_(uint16_t temperature)
Calculate the heater resistance value to send to the BME680 register.
float calc_humidity_(uint16_t raw_humidity)
Calculate the relative humidity in % using the provided raw ADC value.
BME680Oversampling pressure_oversampling_
BME680CalibrationData calibration_
void set_pressure_oversampling(BME680Oversampling pressure_oversampling)
Set the pressure oversampling value. Defaults to 16X.
BME680Oversampling temperature_oversampling_
float get_setup_priority() const override
uint16_t heater_temperature_
BME680Oversampling humidity_oversampling_
void set_temperature_oversampling(BME680Oversampling temperature_oversampling)
Set the temperature oversampling value. Defaults to 16X.
void dump_config() override
sensor::Sensor * temperature_sensor_
float calc_gas_resistance_(uint16_t raw_gas, uint8_t range)
Calculate the gas resistance in Ω using the provided raw ADC value.
void set_heater(uint16_t heater_temperature, uint16_t heater_duration)
Set how the internal heater should operate.
uint16_t heater_duration_
sensor::Sensor * pressure_sensor_
void set_iir_filter(BME680IIRFilter iir_filter)
Set the IIR Filter value. Defaults to no IIR Filter.
uint32_t calc_meas_duration_()
Calculate how long the sensor will take until we can retrieve data.
float calc_temperature_(uint32_t raw_temperature)
Calculate the temperature in °C using the provided raw ADC value.
void set_humidity_oversampling(BME680Oversampling humidity_oversampling)
Set the humidity oversampling value. Defaults to 16X.
float calc_pressure_(uint32_t raw_pressure)
Calculate the pressure in hPa using the provided raw ADC value.
sensor::Sensor * gas_resistance_sensor_
BME680IIRFilter iir_filter_
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
void publish_state(float state)
Publish a new state to the front-end.
const char * iir_filter_to_str(BME280IIRFilter filter)
BME680IIRFilter
Enum listing all IIR Filter options for the BME680.
BME680Oversampling
Enum listing all oversampling options for the BME680.
@ BME680_OVERSAMPLING_16X
@ BME680_OVERSAMPLING_NONE
const float BME680_GAS_LOOKUP_TABLE_1[16] PROGMEM
const float DATA
For components that import data from directly connected sensors like DHT.
Providing packet encoding functions for exchanging data with a remote host.
int8_t ambient_temperature