8 static const char *
const TAG =
"bme680.sensor";
10 static const uint8_t BME680_REGISTER_COEFF1 = 0x89;
11 static const uint8_t BME680_REGISTER_COEFF2 = 0xE1;
13 static const uint8_t BME680_REGISTER_CONFIG = 0x75;
14 static const uint8_t BME680_REGISTER_CONTROL_MEAS = 0x74;
15 static const uint8_t BME680_REGISTER_CONTROL_HUMIDITY = 0x72;
16 static const uint8_t BME680_REGISTER_CONTROL_GAS1 = 0x71;
17 static const uint8_t BME680_REGISTER_CONTROL_GAS0 = 0x70;
18 static const uint8_t BME680_REGISTER_HEATER_HEAT0 = 0x5A;
19 static const uint8_t BME680_REGISTER_HEATER_WAIT0 = 0x64;
21 static const uint8_t BME680_REGISTER_CHIPID = 0xD0;
23 static const uint8_t BME680_REGISTER_FIELD0 = 0x1D;
25 const 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};
28 const 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)) {
199 if (!this->
write_byte(BME680_REGISTER_HEATER_HEAT0, temperature)) {
207 if (!this->
write_byte(BME680_REGISTER_HEATER_WAIT0, duration)) {
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)) {
253 if (temperature < 200)
255 if (temperature > 400)
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;
287 if (duration >= 0xfc0) {
288 duration_value = 0xff;
290 while (duration > 0x3F) {
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;
BME680Oversampling temperature_oversampling_
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
const float DATA
For components that import data from directly connected sensors like DHT.
float calc_gas_resistance_(uint16_t raw_gas, uint8_t range)
Calculate the gas resistance in Ω using the provided raw ADC value.
BME680CalibrationData calibration_
float get_setup_priority() const override
void status_set_warning(const char *message="unspecified")
BME680IIRFilter
Enum listing all IIR Filter options for the BME680.
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.
void set_pressure_oversampling(BME680Oversampling pressure_oversampling)
Set the pressure oversampling value. Defaults to 16X.
float calc_humidity_(uint16_t raw_humidity)
Calculate the relative humidity in % using the provided raw ADC value.
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
BME680IIRFilter iir_filter_
void set_humidity_oversampling(BME680Oversampling humidity_oversampling)
Set the humidity oversampling value. Defaults to 16X.
void set_heater(uint16_t heater_temperature, uint16_t heater_duration)
Set how the internal heater should operate.
sensor::Sensor * gas_resistance_sensor_
int8_t ambient_temperature
BME680Oversampling humidity_oversampling_
uint16_t heater_temperature_
sensor::Sensor * pressure_sensor_
const float BME680_GAS_LOOKUP_TABLE_1 [16] PROGMEM
void status_clear_warning()
uint16_t heater_duration_
void publish_state(float state)
Publish a new state to the front-end.
uint32_t calc_meas_duration_()
Calculate how long the sensor will take until we can retrieve data.
float calc_pressure_(uint32_t raw_pressure)
Calculate the pressure in hPa using the provided raw ADC value.
void dump_config() override
sensor::Sensor * temperature_sensor_
BME680Oversampling
Enum listing all oversampling options for the BME680.
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
virtual void mark_failed()
Mark this component as failed.
void set_iir_filter(BME680IIRFilter iir_filter)
Set the IIR Filter value. Defaults to no IIR Filter.
Implementation of SPI Controller mode.
uint8_t calc_heater_resistance_(uint16_t temperature)
Calculate the heater resistance value to send to the BME680 register.
sensor::Sensor * humidity_sensor_
BME680Oversampling pressure_oversampling_
void set_temperature_oversampling(BME680Oversampling temperature_oversampling)
Set the temperature oversampling value. Defaults to 16X.
float calc_temperature_(uint32_t raw_temperature)
Calculate the temperature in °C using the provided raw ADC value.