Open mjdyson opened 2 years ago
I am interested in BME688 support also. I found this Arduino library that does not include BSEC, but might at least allow readings from the BME688 VOC sensor.
I just updated the existing component to the BSEC2 library: https://github.com/neffs/esphome/tree/bsec2
Before creating a PR we should figure out if it should be an additional component (e.g. bme68x_bsec) or replace the old version. In theory this should also work with BME680, but I don't have one to check. Help would be appreciated.
Adding the additional GAS_ESTIMATE values will be easy, but we also need to provide a way to configure the model.
Please submit a PR with your work.
Before creating a PR we should figure out if it should be an additional component (e.g. bme68x_bsec) or replace the old version. In theory this should also work with BME680, but I don't have one to check. Help would be appreciated.
Thank you @neffs <3 !
I would love to see your work inside the current bme680_bsec
component.
Moreover I can approve that it does work totally fine on an ESP32-C3 with an BME680 (#2072).
It also works on a Pico W with the following build flags modified from #3917
esphome:
name: <device-name>
platformio_options:
build_flags:
- -I /data/<device-name>/.piolibdeps/<device-name>/BSEC2\ Software\ Library/src/inc
- -L /data/<device-name>/.piolibdeps/<device-name>/BSEC2\ Software\ Library/src/cortex-m0plus
- -lalgobsec
Thanks @neffs.
Before creating a PR we should figure out if it should be an additional component (e.g. bme68x_bsec) or replace the old version. In theory this should also work with BME680, but I don't have one to check. Help would be appreciated.
Could the bme680_bsec component be depreciated and replaced with a bme68x_bsec2 component? This would cover the newer bme688 sensor.
Hello,
First, thank you @neffs for your contributions, it's really cool to have the support for bme688 :)
I'm trying to test the code from you pull request and I can't compile it. I'm getting the error "Platform not found: 'sensor.bme68x_bsec'." Any idea what I'm doing wrong ? I see that your PR passed firsts compile tests so I suppose the problem is between the chair and the keyboard ^^
This is my configuration:
external_components:
- source: github://neffs/esphome@bsec2_bme68x
components:
- bme68x_bsec
substitutions:
devicename: esp32-5
packages:
device_base: !include common/boards/arduino/d1-mini32.yaml
i2c:
sda: 21
scl: 22
scan: true
id: bus_i2c
bme68x_bsec:
address: 0x77
state_save_interval: 30min
bsec_configuration: 0,0,4,2,189,... (it is complete in my yaml, but let's not polluate the topic) # bme688_sel_33v_300s_4d
sensor:
- platform: bme68x_bsec
temperature:
name: "BME688 Temperature"
filters:
- median
pressure:
name: "BME688 Pressure"
filters:
- median
humidity:
name: "BME688 Humidity"
filters:
- median
iaq:
name: "BME688 IAQ"
filters:
- median
iaq_static:
name: "BME688 Static IAQ"
filters:
- median
co2_equivalent:
name: "BME688 CO2 Equivalent"
filters:
- median
breath_voc_equivalent:
name: "BME688 Breath VOC Equivalent"
filters:
- median
gas_resistance:
# Gas resistance in Ω
name: "BME688 Gas Resistance"
filters:
- median
Here's my config for an ESP32-S2 Mini board (lolin_s2_mini) + ### BME680:
esphome:
name: esp-device-name
external_components:
- source: github://neffs/esphome@bsec2_bme68x
components:
- bme68x_bsec
esp32:
board: lolin_s2_mini
variant: ESP32S2
framework:
type: arduino
# Enable logging
logger:
api:
encryption:
key: "xxxxxxxxxxxxx"
ota:
wifi:
ssid: "xxxxxxxxx"
password: "xxxxxxxxxx"
captive_portal:
i2c:
sda: 11
scl: 12
bme68x_bsec:
# Default: 0x76 or 0x77
address: 0x77
temperature_offset: 0
# Default: static or mobile
# iaq_mode: static # currently not working
# Default: lp or ulp
sample_rate: lp
# Default: 6h
state_save_interval: 6h
# Download from Bosch website: https://www.bosch-sensortec.com/software-tools/software/bme688-software/
# File: BSEC 2.x
# bsec2-4-0-0_generic_release_23012023.zip\BSEC2.4.0.0_Generic_Release_23012023\config\bme680\bme680_iaq_33v_3s_28d
bsec_configuration: 0,0,4,2,189,1,0,0,(...copy from the file above...)
sensor:
- platform: bme68x_bsec
temperature:
name: "Temperature"
id: "temperature"
humidity:
name: "Humidity"
id: "humidity"
pressure:
name: "Pressure"
id: "pressure"
icon: "mdi:gauge"
co2_equivalent:
name: "CO2 Equivalent"
icon: "mdi:molecule-co2"
breath_voc_equivalent:
name: "VOC Equivalent"
icon: "mdi:molecule"
iaq:
name: "IAQ"
id: iaq
icon: "mdi:approximately-equal"
gas_resistance:
name: "Gas Resistance"
icon: "mdi:omega"
- platform: absolute_humidity
name: Absolute Humidity
icon: "mdi:water"
temperature: temperature
humidity: humidity
text_sensor:
- platform: bme68x_bsec
iaq_accuracy:
name: "IAQ Accuracy"
- platform: template
name: "IAQ Classification"
icon: "mdi:checkbox-marked-circle-outline"
lambda: |-
if ( int(id(iaq).state) <= 50) {
return {"Excellent"};
}
else if (int(id(iaq).state) >= 51 && int(id(iaq).state) <= 100) {
return {"Good"};
}
else if (int(id(iaq).state) >= 101 && int(id(iaq).state) <= 150) {
return {"Lightly polluted"};
}
else if (int(id(iaq).state) >= 151 && int(id(iaq).state) <= 200) {
return {"Moderately polluted"};
}
else if (int(id(iaq).state) >= 201 && int(id(iaq).state) <= 250) {
return {"Heavily polluted"};
}
else if (int(id(iaq).state) >= 251 && int(id(iaq).state) <= 350) {
return {"Severely polluted"};
}
else if (int(id(iaq).state) >= 351) {
return {"Extremely polluted"};
}
else {
return {"error"};
}
This config should work for both the BME680 and BME688.
Thank you @neffs for your efforts.
Update: this seems to be fixed by updating ESPHome to 2024.6.4.
@neffs github://neffs/esphome@bsec2_bme68x
seems to be broken with Esphome 2024.6.1 if the safe_mode
is set...
esphome:
name: "esp-xxxxxx"
friendly_name: esp-xxxxx
external_components:
- source: github://neffs/esphome@bsec2_bme68x
components:
- bme68x_bsec
esp32:
board: lolin_s2_mini
variant: ESP32S2
framework:
type: arduino
# Enable logging
logger:
level: ERROR
api:
encryption:
key: "x"xxxxxxxxxxx
safe_mode: <--- this was introduced, before those options lived under OTA
disabled: true
ota:
- platform: esphome
password: "`xxxxxxxxxx"
wifi:
The rest of my config is what I posted above.
The safe_mode
was previously at ota
but now lives on a component.
While trying to compile the code I get this:
INFO ESPHome 2024.6.1
INFO Reading configuration /config/esphome/esp-xxxxx.yaml...
INFO Generating C++ source...
ERROR Circular dependency detected! Please run with -v option to see what functions failed to complete.
This breaks for me on a C3, the sensor reads nothing and:
[14:16:15][E][component:164]: Component bme68x_bsec set Error flag: unspecified
This is my yaml:
#
# BME680 Sensors
#
i2c:
id: i2c_bus
sda: GPIO05 # Orange
scl: GPIO04 # Yellow
scan: True
external_components:
- source: github://neffs/esphome@bsec2_bme68x
components:
- bme68x_bsec
bme68x_bsec:
id: bme680
address: 0x77
temperature_offset: 0
sample_rate: lp
i2c_id: i2c_bus
bsec_configuration: 0,0,4,2,189,1,0,0,0, _(copied from bme680_iaq_33v_3s_4d)_
sensor:
- platform: bme68x_bsec
bme68x_bsec_id: bme680
temperature:
name: "Temperature"
accuracy_decimals: 1
id: temperature
pressure:
name: "Pressure"
accuracy_decimals: 5
id: pressure
humidity:
name: "Humidity"
id: humidity
accuracy_decimals: 1
iaq:
name: "IAQ"
id: iaq
co2_equivalent:
name: "CO2 Equivalent"
gas_resistance:
name: "Gas Resistance"
id: gas
accuracy_decimals: 5
breath_voc_equivalent:
name: "Intake Breath VOC Equivalent"
text_sensor:
- platform: bme68x_bsec
bme68x_bsec_id: bme680
iaq_accuracy:
name: "IAQ Accuracy"
- platform: template
name: "Air Quality"
icon: "mdi:checkbox-marked-circle-outline"
lambda: |-
if (int(id(iaq).state) <= 50) {
return {"Excellent"};
}
else if (int(id(iaq).state) <= 100) {
return {"Good"};
}
else if (int(id(iaq).state) <= 150) {
return {"Lightly polluted"};
}
else if (int(id(iaq).state) <= 200) {
return {"Moderately polluted"};
}
else if (int(id(iaq).state) <= 250) {
return {"Heavily polluted"};
}
else if (int(id(iaq).state) <= 350) {
return {"Severely polluted"};
}
else if (int(id(iaq).state) <= 500) {
return {"Extremely polluted"};
}
else {
return {"unknown"};
}
This breaks for me on a C3, the sensor reads nothing and:
[14:16:15][E][component:164]: Component bme68x_bsec set Error flag: unspecified
Can you try the following config?
There seems to be some awkward things in yours like that bme68x_bsec_id
and your i2c setup. To be fair I would use GPIO 8 and 9 as they seem to be the preferred / native i2c ones:
I've it working on 2024.6.4 (update if you are in an earlier 2024.6 version) with this C3 board.
esphome:
name: esp-storage
friendly_name: esp-storage
external_components:
- source: github://neffs/esphome@bsec2_bme68x
components:
- bme68x_bsec
refresh: 0s
esp32:
board: esp32-c3-devkitm-1
framework:
type: arduino
# Enable logging
logger:
level: ERROR
# Enable Home Assistant API
api:
encryption:
key: "xxxxxxxxxxxxxxxxxxxx"
ota:
- platform: esphome
password: "xxxxxxxxxxxxxxxxxxxxx"
safe_mode:
disabled: true
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
i2c:
sda: 8
scl: 9
bme68x_bsec:
# Default: 0x76 or 0x77
address: 0x77
temperature_offset: 4.9 # 4.9
# Default: static or mobile
#iaq_mode: static
# Default: lp or ulp
sample_rate: lp
# Default: 6h
state_save_interval: 6h
# bsec2-4-0-0_generic_release_23012023.zip\BSEC2.4.0.0_Generic_Release_23012023\config\bme680\bme680_iaq_33v_3s_28d\
bsec_configuration: 0,0,4,2,189,1,0,0,0,0,0,0,158,7,0,0,(.........)
sensor:
- platform: bme68x_bsec
temperature:
name: "Temperature"
id: "temperature"
humidity:
name: "Humidity"
id: "humidity"
pressure:
name: "Pressure"
id: "pressure"
icon: "mdi:gauge"
co2_equivalent:
name: "CO2 Equivalent"
id: "co2_equivalent"
icon: "mdi:molecule-co2"
breath_voc_equivalent:
name: "VOC Equivalent"
icon: "mdi:molecule"
iaq:
name: "IAQ"
id: iaq
icon: "mdi:approximately-equal"
gas_resistance:
name: "Gas Resistance"
icon: "mdi:omega"
- platform: absolute_humidity
name: Absolute Humidity
icon: "mdi:water"
temperature: temperature
humidity: humidity
text_sensor:
- platform: bme68x_bsec
iaq_accuracy:
name: "IAQ Accuracy"
- platform: template
name: "IAQ Classification"
icon: "mdi:checkbox-marked-circle-outline"
lambda: |-
if ( int(id(iaq).state) <= 50) {
return {"Excellent"};
}
else if (int(id(iaq).state) >= 51 && int(id(iaq).state) <= 100) {
return {"Good"};
}
else if (int(id(iaq).state) >= 101 && int(id(iaq).state) <= 150) {
return {"Lightly polluted"};
}
else if (int(id(iaq).state) >= 151 && int(id(iaq).state) <= 200) {
return {"Moderately polluted"};
}
else if (int(id(iaq).state) >= 201 && int(id(iaq).state) <= 250) {
return {"Heavily polluted"};
}
else if (int(id(iaq).state) >= 251 && int(id(iaq).state) <= 350) {
return {"Severely polluted"};
}
else if (int(id(iaq).state) >= 351) {
return {"Extremely polluted"};
}
else {
return {"error"};
}
- platform: template
name: "CO2 Classification"
icon: "mdi:checkbox-marked-circle-outline"
lambda: |-
if ( int(id(co2_equivalent).state) <= 400) {
return {"Excellent"};
}
else if (int(id(co2_equivalent).state) >= 401 && int(id(co2_equivalent).state) <= 1000) {
return {"Normal"};
}
else if (int(id(co2_equivalent).state) >= 1001 && int(id(co2_equivalent).state) <= 2000) {
return {"Unhealty"};
}
else if (int(id(co2_equivalent).state) >= 2001 && int(id(co2_equivalent).state) <= 5000) {
return {"Health Risk"};
}
else if (int(id(co2_equivalent).state) >= 5001) {
return {"DANGER!"};
}
else {
return {"error"};
}
switch:
- platform: restart
name: "Restart"
I've updated https://github.com/esphome/esphome/pull/4585 so it can now be used as an external component: see https://github.com/esphome/esphome/pull/4585#issuecomment-2199450256
You'll need to be using ESPHome dev
as https://github.com/esphome/esphome/pull/7023 was just merged and it contains some necessary changes. Some feedback on the PR would be great. 🙂
I've updated esphome/esphome#4585 so it can now be used as an external component: see esphome/esphome#4585 (comment) You'll need to be using ESPHome
dev
as esphome/esphome#7023 was just merged and it contains some necessary changes. Some feedback on the PR would be great. 🙂
I don't get it... the code from @neffs was already working as an external component. It just broke for a specific version of ESPHome (2024.6.x) but the fix was to update ESPHome to 2024.6.4..
You can of course still use it as an external component directly from @neffs's repo. The PR is using that branch, so I believe it should give you the same thing either way.
Describe the problem you have/What new integration you would like
Support for the customised BME688 algorithm that is learned from the dev-board and then put through the Bosch ML software tool. For Arduino sketches, I believe additional config files need to be included in the main program, which allow a customised data model to be referenced. BSEC 2.0.6 is the latest version, which is only available from the BoschSensorTec website after signing a form. The BoschSensorTec github is not currently at this version.
Please describe your use case for this integration and alternatives you've tried:
By using the ML output from a sensor board, the BME688 claims to be able to distinguish between different types of gases. A trained model should be able to tell the difference between coffee and tea for example. The use case I am looking to achieve is to be able to detect 3d printer fumes from various filament types, including ABS and PLA.
Additional context
I dont believe the latest API is in the ESPHome code base. Specifically there are outputs returned from the sensor called "BSEC_OUTPUT_GAS_ESTIMATE_1" (and 2/3/4), which show "Gas_Estimate [probability 0.00-1]. Outputs corresponding to different target groups(Classes) with the probability of occurrence". These target groups (classes) are specified during the ML training and are for the different types of gas that you want to test for.
There is a lot of information in the zip file that is available from the Bosch website, after signing up for the download file, including test data.