trvrnrth / esphome-bsec-bme680

ESPHome component for the Bosch BME680 sensor via BSEC providing temperature, humidity, pressure and indoor air quality measurements.
85 stars 17 forks source link

How to setup the update interval #7

Closed florafrisia closed 3 years ago

florafrisia commented 3 years ago

Hello,

I like to thank you the work you did on the bme680. Still I have a small question I like to setup the update_interval. Most sensors in ESPHome have this option.

With kind regards,

Peter Noé

trvrnrth commented 3 years ago

Whilst it would technically be possible to allow a custom update interval it is recommended to run BSEC with one of the standard sampling rates of either every 3 or 300 seconds). See the explanation from Bosch. At present the component does not allow selection of sampling rate and operates in the Low Power 3s mode.

As noted in the readme you may of course apply any further filtering you wish to the sensors and effectively control the update rate in that manner. For example, I apply a median filter in my setup to guard against outliers, limit the number of updates sent to home assistant and reduce storage requirements in influxdb which I use to store historical data.

ignisf commented 3 years ago

Hi @trvrnrth, I'd like to test how the ULP mode behaves, what should I alter in your component's source? I've identified these two lines that need changing for now: https://github.com/trvrnrth/esphome-bsec-bme680/blob/93e42f1ca1f2176ce5c7edf5c4184d4ce51087c5/bme680_bsec/bme680_bsec.cpp#L16 https://github.com/trvrnrth/esphome-bsec-bme680/blob/93e42f1ca1f2176ce5c7edf5c4184d4ce51087c5/bme680_bsec/bme680_bsec.cpp#L45

trvrnrth commented 3 years ago

@ignisf I think that should be it :)

ignisf commented 3 years ago

@trvrnrth it seems to be working as expected. I also removed the staggering of the sensor state updates. And by 'as expected' I mean that it lowered the load on my esp32cam to a manageable level. I'm still monitoring the measurements.

Attaching diff:

diff --git a/bme680_bsec/bme680_bsec.cpp b/bme680_bsec/bme680_bsec.cpp
index 68a1c0c..64059b5 100644
--- a/bme680_bsec/bme680_bsec.cpp
+++ b/bme680_bsec/bme680_bsec.cpp
@@ -13,7 +13,7 @@ static const char *TAG = "bme680_bsec.sensor";
 static const std::string IAQ_ACCURACY_STATES[4] = {"Stabilizing", "Uncertain", "Calibrating", "Calibrated"};

 static const uint8_t BSEC_CONFIG_IAQ[] = {
-#include "config/generic_33v_3s_28d/bsec_iaq.txt"
+#include "config/generic_33v_300s_28d/bsec_iaq.txt"
 };

 std::map<uint8_t, BME680BSECComponent *> BME680BSECComponent::instances;
@@ -42,7 +42,7 @@ void BME680BSECComponent::setup() {
       BSEC_OUTPUT_CO2_EQUIVALENT,
       BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
   };
-  this->bsec_.updateSubscription(sensor_list, 7, BSEC_SAMPLE_RATE_LP);
+  this->bsec_.updateSubscription(sensor_list, 7, BSEC_SAMPLE_RATE_ULP);
 }

 void BME680BSECComponent::dump_config() {
@@ -74,39 +74,16 @@ float BME680BSECComponent::get_setup_priority() const { return setup_priority::D

 void BME680BSECComponent::loop() {
   if (this->check_bsec_status_() && this->bsec_.run()) {
-    this->sensor_push_num_ = 1;
     this->save_state_();
-  }

-  // In order not to block here, spread the sensor state pushes
-  // across subsequent calls otherwise we end up with API disconnects
-  if (this->sensor_push_num_ > 0 && this->sensor_push_num_ <= 8) {
-    switch (this->sensor_push_num_++) {
-      case 1:
-        this->publish_state_(this->temperature_sensor_, this->bsec_.temperature);
-        break;
-      case 2:
-        this->publish_state_(this->humidity_sensor_, this->bsec_.humidity);
-        break;
-      case 3:
-        this->publish_state_(this->pressure_sensor_, this->bsec_.pressure / 100.0);
-        break;
-      case 4:
-        this->publish_state_(this->gas_resistance_sensor_, this->bsec_.gasResistance);
-        break;
-      case 5:
-        this->publish_state_(this->iaq_sensor_, this->get_iaq_());
-        break;
-      case 6:
-        this->publish_state_(this->iaq_accuracy_sensor_, IAQ_ACCURACY_STATES[this->get_iaq_accuracy_()]);
-        break;
-      case 7:
-        this->publish_state_(this->co2_equivalent_sensor_, this->bsec_.co2Equivalent);
-        break;
-      case 8:
-        this->publish_state_(this->breath_voc_equivalent_sensor_, this->bsec_.breathVocEquivalent);
-        break;
-    }
+    this->publish_state_(this->temperature_sensor_, this->bsec_.temperature);
+    this->publish_state_(this->humidity_sensor_, this->bsec_.humidity);
+    this->publish_state_(this->pressure_sensor_, this->bsec_.pressure / 100.0);
+    this->publish_state_(this->gas_resistance_sensor_, this->bsec_.gasResistance);
+    this->publish_state_(this->iaq_sensor_, this->get_iaq_());
+    this->publish_state_(this->iaq_accuracy_sensor_, IAQ_ACCURACY_STATES[this->get_iaq_accuracy_()]);
+    this->publish_state_(this->co2_equivalent_sensor_, this->bsec_.co2Equivalent);
+    this->publish_state_(this->breath_voc_equivalent_sensor_, this->bsec_.breathVocEquivalent);
   }
 }
trvrnrth commented 3 years ago

@ignisf Good to hear. I may build it in as an option in the future if time allows.

The staggering of the updates was for esp8266 boards really as they couldn't cope with doing all the pushes in one loop call but it shouldn't have any negative impact for other boards with more processing power either. I'm curious why you needed to remove it?

ignisf commented 3 years ago

I wasn't sure when would the this->check_bsec_status_() && this->bsec_.run() condition be true so I wanted to simplify the function as much as possible. Now that I've observed the code work as expected, I may as well add it back.

trvrnrth commented 3 years ago

@ignisf I'd recommend it. I observed that the pushes blocked which was causing me API disconnects when running on an ESP8266. There's a fair chance you'd not notice on an ESP32 but as it sounds like you've got it doing camera duty as well it'd probably be worth keeping them split just in case!

ariedeleen commented 3 years ago

As a 'workaound' I have as mentioned earlier set a filter throttle to delay or limit the status updates. So, now it updates, for example, every five minutes. Have not figured it out for the text_sensor: That is still updating every ~3 sec.

https://esphome.io/components/sensor/index.html?highlight=filters#sensor-filters

sensor:

@trvrnrth thanx for the effort ;-) to get this working with the BSEC shebang.

trvrnrth commented 3 years ago

@ariedeleen I hadn't really considered the text sensor but you're correct; filters won't work for it. I'll see about getting it to only publish a new state when the value changes.

For the numeric sensors it was a deliberate choice to not have a configurable interval. The underlying sensor run has to be completed regardless and the filters provide much more flexibility.