ESP Home manually trigger sensor updates

Hello,

i am using a ESP8266 with BME680 and the code from the second (advanced) example here:

I noticed there is an time offset of 15 seconds between the reporting of the BME680 Raw values (temperature, humidity, pressure, gas_resistance), the values from the sensor template (Indoor Air Quality) and the values from the text sensor template (IAQ Classification).
I assume it does not take 15s to calculate the template values.

So I have two questions:

  1. Can somebody explain where this offset comes from?
  2. Is there a way to trigger the sensor data aquisition manually?

Background for my question is that I want to use deep sleep in the future but noticed that not all values are reported at the same time, which results in unnecessary time where the uC is consuming power but has not reported all the sensor values.

I already tried to use
component.update: temperature

but this results in an error:
ID 'temperature' of type sensor::Sensor doesn't inherit from PollingComponent. Please double check your ID is pointing to the correct value.

I also tried
id(temperature).publish_state(id(temperature).state);

but this does only publish a exisiting value (e.g. when setting update interval to “never” the reported values always default to 0)

Thanks in advance for your help!

We would be unsure what the cause of tour template sensor delay is without looking at the yaml, so post it and someone may be able to assist.

1 Like

Thanks for your reply!
Sure, here is my yaml:

esphome:
  name: wd1m-6-test
  friendly_name: WD1M-6-TEST

esp8266:
  board: d1_mini

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: <redacted>

ota:
  password: <redacted>

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  power_save_mode: light #none, light, high    

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Wd1M-6-Test Fallback Hotspot"
    password: <redacted>

captive_portal:

i2c:
  sda: 4
  scl: 5
  scan: False

sensor:
  - platform: bme680
    temperature:
      id: temperature
      name: "BME680 Temperature"
      oversampling: 16x
    pressure:
      id: pressure
      name: "BME680 Pressure"
    humidity:
      id: "humidity"
      name: "BME680 Humidity"
    gas_resistance:
      id: "gas_resistance"
      name: "BME680 Gas Resistance"
    address: 0x77
    update_interval: 60s
  - platform: template
    name: "BME680 Indoor Air Quality"
    id: iaq
    icon: "mdi:gauge"
    # caulculation: comp_gas = log(R_gas[ohm]) + 0.04 log(Ohm)/%rh * hum[%rh]
    lambda: |-
      return float(log(id(gas_resistance).state) + 0.04 *  id(humidity).state);
    unit_of_measurement: 'IAQ'

text_sensor:
  - platform: template
    update_interval: 60s
    id: iaq_class
    name: "BME680 IAQ Classification"
    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"};
      }

And here is the (wifi) log that shows the offset:

[11:30:57][D][bme680.sensor:332]: Got temperature=23.6°C pressure=974.7hPa humidity=44.2% gas_resistance=8551.5Ω
[11:30:57][D][sensor:093]: 'BME680 Temperature': Sending state 23.64315 °C with 1 decimals of accuracy
[11:30:57][D][sensor:093]: 'BME680 Pressure': Sending state 974.72717 hPa with 1 decimals of accuracy
[11:30:57][D][sensor:093]: 'BME680 Humidity': Sending state 44.19717 % with 1 decimals of accuracy
[11:30:57][D][sensor:093]: 'BME680 Gas Resistance': Sending state 8551.50586 Ω with 1 decimals of accuracy
[11:31:20][D][text_sensor:064]: 'BME680 IAQ Classification': Sending state 'Excellent'
[11:31:21][D][sensor:093]: 'BME680 Indoor Air Quality': Sending state 10.82175 IAQ with 1 decimals of accuracy

BME680 sensor is read and values published at 11:30:57.
Text sensor and teamplate sensor are published at 11:31:20.
Offset of 23s. The actual offset seems to be random with each reset/reboot but stays the same within each reset/reboot.

Might come from the “oversampling” parameter?

Oversampling Options

By default, some temp sensor measures each value 16 times when requesting a new value. You can, however, configure this amount. Possible oversampling values:

  • NONE (value is skipped)
  • 1x
  • 2x
  • 4x
  • 8x
  • 16x (default)

Just tried to disable oversampling, but this did not change the outcome.

I noticed when setting to VERY_VERBOSE I get the following logs:

13:48:08:396 -> [VV][scheduler:063]: set_interval(name='', interval=60000, offset=13901)
13:48:08:407 -> [VV][scheduler:063]: set_interval(name='update', interval=60000, offset=18134)
13:48:08:412 -> [VV][scheduler:063]: set_interval(name='update', interval=60000, offset=23334)

The offset value seems to be random with each reboot and it does not really correlate with the delay/offset I actually see when the sensor data is published.

The scheduler intervals belong to:

  1. actual hardware BME680 sensor
  2. sensor template
  3. text sensor.

The two components both have a update_interval of 60s. These doesn’t always sync up.

Try setting the update_interval to never in the text_sensor and then just call component.update of the text_sensor in the on_value action in the temperature section of the bme680 sensor.

sensor:
  - platform: bme680
    temperature:
      id: temperature
      name: "BME680 Temperature"
      oversampling: 16x
      on_value:
        - component.update: iaq_class
      ...
text_sensor:
  - platform: template
    update_interval: never
    id: iaq_class
    ...

I’m actually trying to accomplish almost the same on an AHT20. Here, I want the frontend to be able to set an calibration offset (don’t want to compile this to the firmware obviously) and figured I could do it this way:


number:
  - platform: template
    name: "Temperature offset"
    id: temperature_offset
    optimistic: true
    min_value: -10
    max_value: 10
    step: 0.1
    restore_value: true
    initial_value: 0

  - platform: template
    name: "Humidity offset"
    id: humidity_offset
    optimistic: true
    min_value: -25
    max_value: 25
    step: 0.1
    restore_value: true
    initial_value: 0
    on_value: 
      then:
        - component.update: sensor_humidity

sensor:
  - platform: uptime
    name: "Uptime"

  - platform: aht10
    variant: AHT20
    temperature:
      name: "Temperature"
      id: sensor_temperature
      accuracy_decimals: 1
      filters:
        - lambda: return x + id(temperature_offset).state;
    humidity:
      name: "Humidity"
      id: sensor_humidity
      accuracy_decimals: 1
      filters:
        - lambda: return x + id(humidity_offset).state;

  - platform: ens160_i2c
    address: 0x53
    aqi:
      name: "AQI"
      id: aqi
      accuracy_decimals: 2
    eco2:
      name: "eCO2"
    tvoc:
      name: "Tvoc"
    compensation:
      temperature: sensor_temperature
      humidity: sensor_humidity

But also getting the same yaml linting error. It’s just an asthetic thing of course, re-sending the value after changing the value so I don’t have to wait 60s after a value change. I’m sure this must be possible?