diff --git a/README.md b/README.md index bf156d9..96e1ede 100644 --- a/README.md +++ b/README.md @@ -59,14 +59,6 @@ The SuperSensor's voice functionality can be completely disabled if voice support is not desired. This defeats most of the point of the SuperSensor, but can be done if desired. -### Gas Ceiling - -The AQ (air quality) calculation from the BME680 requires a "maximum"/ceiling -threshold for the gas resistance value in clean air after some operation -time. The value defaults to 200 kΩ to provide an initial baseline, but -should be calibrated manually after setup as each sensor is different. See -the section "Calibrating AQ" below for more details. - ### Light Threshold Control The SuperSensor features a "light presence" binary sensor based on the light @@ -178,139 +170,3 @@ For detect, no occupancy will ever fire. For clear, no states will clear occupancy; with any detect option, this means that occupancy will be detected only once and never clear, which is likely not useful. - -## Calibrating AQ - -The Supersensor uses the Bosch BME680 combination temperature, humidity, -pressure, and gas sensor to provide a wide range of useful information about -the environmental conditions the sensor is placed in. However, this sensor -can be tricky to work with. - -While it's normally recommended to use the Bosch BSEC library with this -sensor, in my ~6 month experience I found this library to be far more trouble -than it was worth. Specifically, it's IAQ measurement is nearly useless, with -a strong tendency to get stuck in an upward trend constantly "calibrating" -itself to higher and higher baselines, to the point where nonsensical values -were being read. After much research into this, I decided to abandon the -library in version 1.1 and went with a more custom solution. - -Instead of the BSEC, we use the stock BME680 ESPHome library, along with -some calculations by thstielow on GitHub in their [IAQ project](https://github.com/thstielow/raspi-bme680-iaq). -This provided some useful example code and formulae to calculate a useful -Air Quality (AQ) value instead of the useless Bosch value. - -However using this method requires some manual calibration of the sensor -after putting it together but before final use, in order to get a somewhat -accurate value out of the AQ component. If you don't care about the AQ value, -you can skip this, but it is recommended to take full advantage of the sensor. - -As a quick explainer, the code leverages a combination of the "Gas Resistance" -value provided by the sensor, along with an absolute humidity calculated from -the temperature and relative humidity of the sensor (included ESPHome sensor), -along with two values (one configurable, one hard-coded) and several formulae -to arrive at the resulting AQ value. For full details of the calculation, -see the repository linked above, which was re-implemented faithfully here. - -The first thing to note is that each BME680 sensor is wildly different in -terms of gas resistance values. In the same air, I had sensors reading values -that differed by nearly 200,000Ω, which necessitates a human-configurable -baseline value. Further, the IAQ project recommends determining a linear -slope value for this, but instead of trying to explain how to calculate this, -I just went with the default slope value of 0.03 for this first iteration. - -Thus, the main difficulty in getting a useful AQ score is finding the -"Gas Resistance Ceiling" value. This value is configurable in the -SuperSensor interface (Web or HomeAssistant), and should be calibrated as -follows during the initial setup of the supersensor. - -1. Find a known-clean room, for instance a well-ventilated, well-cleaned -room in your house or similar. It should have fresh air (no stray VOCs) but -also minimal drafts or outside exposure especially if there is a poor external -AQ level. This will be your calibration reference room. Ideally, this room -should be somewhere between 16C and 26C for optimal performance, so air -conditioning (or a nice spring/fall day) is best. - -2. Turn on the SuperSensor in this environment, and connect it to your -HomeAssistant instance; this will be critical for viewing historical graphs -during the following steps. - -3. Let the SuperSensor run to "burn in" the gas sensor for at least 3-6 hours, -or until the value for the Gas Resistance stabilizes. It is best to avoid much -movement or activity in the selected calibration room to avoid disrupting -the sensor during this time. It is also best to ensure that the ambient -temperature changes as little as possible during this time. - -4. Review the resulting graph of Gas Resistance over the burn-in period. You -can usually ignore the first hour or two as the sensor was burning in, and -focus instead on the last hour or so. - -5. Make note of the highest mean value reached by the sensor during this time. -This will be your baseline value for calibrating the Gas Resistance Ceiling. - -6. Round the value up to the nearest 1000. For example, if the maximum value -was 195732.1, round this to 196000.0. - -7. Find the difference in the temperature of the BME680 temperature sensor -from 20C, called ΔT below. I found this part by trial-and-error, so this is -not precise, but as an example if the calibration room is reporting 26C, your -ΔT value in the next step is 6. If your temperature was below 20C, use 0. - -8. Use one of the following formulae to come up with your offset value, which -depends on the maximum value range found in step 6. - - * `<100,000`: 200 * ΔT = 0-1200 - * `100,000-200,000`: 500 * ΔT = 0-3000 - * `>200,000`: 1000 * ΔT = 0-6000 - -Again this value is rough, and might not even really be needed, but helps -avoid weird issues with AQ values dropping suddenly later as temperature -and humidity changes. - -9. Add your offset value from step 8 to the rounded maximum from step 6. -For example, 196000.0 with a ΔT of 5C (25C ambient) yields 201000.0 - -10. Divide the result from 9 by 1000 to give a number from 1-500. This -is the value to enter as the "Gas Resistance Ceiling (kΩ)" for this -sensor. This value will be saved in the NV-RAM of the ESP32 and preserved -on reboots. - -At this point, you should have a value that results in the "BME680 AQ" -sensor reporting 100% AQ, i.e. clean air. You can now test to ensure -that the value will correctly drop as VOCs are added. - -1. Take a Sharpie permanent marker, Acetone nail polish remover, or some -other VOC that the BME680 gas sensor can detect, and place it near the -sensor. For example with a sharpie, remove the cap and place the tip -about 1-2cm from the sensor, or place a small capful of nail polish -remover about 3-5cm from the sensor. - -2. Wait about 30 seconds. - -3. You should see the AQ value drop precipitously, into the order of 50% -or lower, and ideally closer to 0-20%. If the value remains higher than -50% with this test, your calculated Gas Resistance Ceiling might be -too low, and should be increased in increments of 1000. - -4. Remove the VOC source (replace the cap, remove the capful of remover, -etc.) and wait about 30-60 minutes. - -5. You should see the AQ value and gas resistance return to their original -values. If it is significantly lower than before, even after waiting 60+ -minutes, restart the calculation from step 5 in the previous section -using this new value as the baseline. - -At this point, the sensor should be calibrated enough for day-to-day -casual home use, and will tell you if there is any significant -VOC contamination in the air by dropping the AQ value from 100% to some -lower value representing the approximate decrease in air quality. Since -the sensor also factors in the absolute humidity (and via that, the -ambient temperature) into the AQ calculation, high humidity will also -drop the value, as this too impacts the air quality. Hopefully this -is useful for your purposes. - -If you find that the AQ value still doesn't represent known reality, -you can also tweak the in-code value for `ph_slope` on line 522, as -it's possible your sensor differs significantly here. As mentioned -above this is still a work in progress to determine for myself, so -future versions may alter this or include calibration of this value -automatically, depending on how things go in my testing. diff --git a/supersensor.yaml b/supersensor.yaml index c42d15b..7fd01cf 100644 --- a/supersensor.yaml +++ b/supersensor.yaml @@ -1,10 +1,10 @@ --- ############################################################################### -# SuperSensor v1.0 ESPHome configuration +# SuperSensor v1.x ESPHome configuration ############################################################################### # -# Copyright (C) 2023 Joshua M. Boniface +# Copyright (C) 2023-2025 Joshua M. Boniface # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -26,7 +26,7 @@ esphome: friendly_name: "Supersensor" project: name: joshuaboniface.supersensor - version: "1.2" + version: "1.3" on_boot: - priority: 600 then: @@ -70,11 +70,6 @@ esp32: # CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y" globals: - - id: gas_resistance_ceiling - type: int - restore_value: yes - initial_value: "200" - - id: pir_hold_time type: int restore_value: yes @@ -728,21 +723,6 @@ switch: entity_category: diagnostic number: - - platform: template - name: "Gas Resistance Ceiling (kΩ)" - id: gas_resistance_ceiling_setter - min_value: 10 - max_value: 500 - step: 1 - entity_category: config - lambda: |- - return id(gas_resistance_ceiling); - set_action: - then: - - globals.set: - id: gas_resistance_ceiling - value: !lambda 'return int(x);' - # PIR Hold Time: # The number of seconds after motion detection for the PIR sensor to remain held on - platform: template