7static const char *
const TAG =
"bme680.sensor";
9static const uint8_t BME680_REGISTER_COEFF1 = 0x89;
10static const uint8_t BME680_REGISTER_COEFF2 = 0xE1;
12static const uint8_t BME680_REGISTER_CONFIG = 0x75;
13static const uint8_t BME680_REGISTER_CONTROL_MEAS = 0x74;
14static const uint8_t BME680_REGISTER_CONTROL_HUMIDITY = 0x72;
15static const uint8_t BME680_REGISTER_CONTROL_GAS1 = 0x71;
16static const uint8_t BME680_REGISTER_CONTROL_GAS0 = 0x70;
17static const uint8_t BME680_REGISTER_HEATER_HEAT0 = 0x5A;
18static const uint8_t BME680_REGISTER_HEATER_WAIT0 = 0x64;
20static const uint8_t BME680_REGISTER_CHIPID = 0xD0;
22static const uint8_t BME680_REGISTER_FIELD0 = 0x1D;
24constexpr float BME680_GAS_LOOKUP_TABLE_1[16]
PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8,
25 0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0};
27constexpr float BME680_GAS_LOOKUP_TABLE_2[16]
PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8,
28 -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
30[[maybe_unused]]
static const char *oversampling_to_str(
BME680Oversampling oversampling) {
31 switch (oversampling) {
74 if (!this->
read_byte(BME680_REGISTER_CHIPID, &chip_id) || chip_id != 0x61) {
81 if (!this->
read_bytes(BME680_REGISTER_COEFF1, coeff1, 25)) {
86 if (!this->
read_bytes(BME680_REGISTER_COEFF2, coeff2, 16)) {
118 uint8_t temp_var = 0;
140 uint8_t config_register;
141 if (!this->
read_byte(BME680_REGISTER_CONFIG, &config_register)) {
145 config_register &= ~0b00011100;
146 config_register |= (this->
iir_filter_ & 0b111) << 2;
147 if (!this->
write_byte(BME680_REGISTER_CONFIG, config_register)) {
154 if (!this->
read_byte(BME680_REGISTER_CONTROL_HUMIDITY, &hum_control)) {
158 hum_control &= ~0b00000111;
160 if (!this->
write_byte(BME680_REGISTER_CONTROL_HUMIDITY, hum_control)) {
166 uint8_t gas1_control;
167 if (!this->
read_byte(BME680_REGISTER_CONTROL_GAS1, &gas1_control)) {
171 gas1_control &= ~0b00011111;
172 gas1_control |= 1 << 4;
174 if (!this->
write_byte(BME680_REGISTER_CONTROL_GAS1, gas1_control)) {
182 uint8_t gas0_control;
183 if (!this->
read_byte(BME680_REGISTER_CONTROL_GAS0, &gas0_control)) {
187 gas0_control &= ~0b00001000;
188 gas0_control |= heat_off << 3;
189 if (!this->
write_byte(BME680_REGISTER_CONTROL_GAS0, gas0_control)) {
213 ESP_LOGCONFIG(TAG,
"BME680:");
214 LOG_I2C_DEVICE(
this);
216 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
218 ESP_LOGCONFIG(TAG,
" IIR Filter: %s", iir_filter_to_str(this->
iir_filter_));
219 LOG_UPDATE_INTERVAL(
this);
229 ESP_LOGCONFIG(TAG,
" Heater OFF");
236 uint8_t meas_control = 0;
239 meas_control |= 0b01;
240 if (!this->
write_byte(BME680_REGISTER_CONTROL_MEAS, meas_control)) {
267 int32_t heatr_res_x100;
269 var1 = (((int32_t) ambient_temperature * gh3) / 1000) * 256;
270 var2 = (gh1 + 784) * (((((gh2 + 154009) *
temperature * 5) / 100) + 3276800) / 10);
271 var3 = var1 + (var2 / 2);
272 var4 = (var3 / (res_heat_range + 4));
273 var5 = (131 * res_heat_val) + 65536;
274 heatr_res_x100 = (int32_t) (((var4 / var5) - 250) * 34);
275 heatr_res = (uint8_t) ((heatr_res_x100 + 50) / 100);
281 uint8_t duration_value;
284 duration_value = 0xff;
290 duration_value =
duration + (factor * 64);
293 return duration_value;
297 if (!this->
read_bytes(BME680_REGISTER_FIELD0, data, 15)) {
306 ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL);
315 uint16_t raw_gas = (uint16_t) ((
uint32_t) data[13] * 4 | (((
uint32_t) data[14]) / 64));
316 uint8_t gas_range = data[14] & 0x0F;
323 bool gas_valid = (data[14] >> 5) & 1;
324 bool heat_stable = (data[14] >> 4) & 1;
328 ESP_LOGD(TAG,
"Got temperature=%.1f°C pressure=%.1fhPa humidity=%.1f%% gas_resistance=%.1fΩ",
temperature,
pressure,
329 humidity, gas_resistance);
331 ESP_LOGW(TAG,
"Gas measurement unsuccessful, reading invalid!");
333 ESP_LOGW(TAG,
"Heater unstable, reading invalid! (Normal for a few readings after a power cycle)");
342 if (gas_valid && heat_stable) {
356 float temp_adc = raw_temperature;
363 var1 = ((temp_adc / 16384.0f) - (t1 / 1024.0f)) * t2;
366 var3 = (temp_adc / 131072.0f) - (t1 / 8192.0f);
367 var2 = var3 * var3 * t3 * 16.0f;
396 var1 = (tfine / 2.0f) - 64000.0f;
397 var2 = var1 * var1 * (p6 / 131072.0f);
398 var2 = var2 + var1 * p5 * 2.0f;
399 var2 = (var2 / 4.0f) + (p4 * 65536.0f);
400 var1 = (((p3 * var1 * var1) / 16384.0f) + (p2 * var1)) / 524288.0f;
401 var1 = (1.0f + (var1 / 32768.0f)) * p1;
402 calc_pres = 1048576.0f - float(raw_pressure);
405 if (
int(var1) != 0) {
406 calc_pres = ((calc_pres - (var2 / 4096.0f)) * 6250.0f) / var1;
407 var1 = (p9 * calc_pres * calc_pres) / 2147483648.0f;
408 var2 = calc_pres * (p8 / 32768.0f);
409 var4 = calc_pres / 256.0f;
410 var3 = var4 * var4 * var4 * (p10 / 131072.0f);
411 calc_pres = calc_pres + (var1 + var2 + var3 + (p7 * 128.0f)) / 16.0f;
416 return calc_pres / 100.0f;
437 temp_comp = tfine / 5120.0f;
439 var1 = float(raw_humidity) - (h1 * 16.0f + ((h3 / 2.0f) * temp_comp));
441 (((h2 / 262144.0f) * (1.0f + ((h4 / 16384.0f) * temp_comp) + ((h5 / 1048576.0f) * temp_comp * temp_comp))));
442 var3 = h6 / 16384.0f;
443 var4 = h7 / 2097152.0f;
445 calc_hum = var2 + (var3 + var4 * temp_comp) * var2 * var2;
447 if (calc_hum > 100.0f) {
449 }
else if (calc_hum < 0.0f) {
460 float raw_gas_f = raw_gas;
461 float range_f = 1U <<
range;
464 var1 = 1340.0f + (5.0f * range_sw_err);
465 var2 = var1 * (1.0f + BME680_GAS_LOOKUP_TABLE_1[
range] / 100.0f);
466 var3 = 1.0f + (BME680_GAS_LOOKUP_TABLE_2[
range] / 100.0f);
468 calc_gas_res = 1.0f / (var3 * 0.000000125f * range_f * (((raw_gas_f - 512.0f) / var2) + 1.0f));
475 const uint8_t os_to_meas_cycles[6] = {0, 1, 2, 4, 8, 16};
482 tph_dur = meas_cycles * 1963u;
void mark_failed()
Mark this component as failed.
void status_set_warning()
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(const std voi set_timeout)(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
void status_clear_warning()
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_
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) const
bool read_byte(uint8_t a_register, uint8_t *data)
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.
constexpr float BME680_GAS_LOOKUP_TABLE_1[16] PROGMEM
BME680Oversampling
Enum listing all oversampling options for the BME680.
@ BME680_OVERSAMPLING_16X
@ BME680_OVERSAMPLING_NONE
int8_t ambient_temperature