Esphome round with extra digits in HA

Regarding this config where I want to avoid updating HA too often, but want to capture changes in pressure:

sensor:
  - platform: adc
    pin: A0
    name: "Pressure"
    accuracy_decimals: 1
    device_class: pressure
    state_class: measurement
    unit_of_measurement: "psi"
    icon: "mdi:gauge"
    update_interval: 5s
    filters:
      - lambda: |-
          ESP_LOGD("pressure_tag", "Raw value before filter: %f (%.1f)", x, x * 130);
          return x;
      - delta: 2%
      - lambda: return x * 130;
      - round: 1

Just so I’m sure: update_interval above is telling ESPHome to read the ADC every 5 seconds, and then the delta says if the ADC’s raw value changes by 2% then send the adjusted value to HA. Correct?

I assume it would be better to use the delta after the conversion and use a fixed value (like 5 psi).

One thing I’ve noticed with using round is I see the ESPHome logs show the rounded value:

[09:12:13.767][D][pressure_tag:036]: Raw value before filter: 0.524414 (68.2)
[09:12:18.767][D][pressure_tag:036]: Raw value before filter: 0.525391 (68.3)
[09:12:23.774][D][pressure_tag:036]: Raw value before filter: 0.528320 (68.7)
[09:12:23.781][D][sensor:135]: 'Pressure': Sending state 68.70000 psi with 1 decimals of accuracy
[09:12:28.775][D][pressure_tag:036]: Raw value before filter: 0.527344 (68.6)
[09:12:33.776][D][pressure_tag:036]: Raw value before filter: 0.525391 (68.3)

But the state is showing a large number of digits.

I assume that is some round-trip precision error happening on the HA side where API receives the text 68.70000, converts to float and back to a string again.

$ python3 -c 'print("Round-trip:{:.20f}".format(float("68.70000")))'
Round-trip:68.70000000000000284217

Before the delta above I was saving a lot of state data, so that update frequency is better now. I was using round to make HA see fewer state change. But if the conversion error is the same every time maybe it makes no difference.

Not sure exactly what you are asking.

This issue probably won’t clear it up for you either:

It is not clear why you have two lambdas in your example.

Nor is your intention for round clear.

If you want better advice it is better to state what it is you are trying to achieve not ask how to do the thing you think will do what you want.

Assuming this is what you want:

That is clearer, but what does “too often” mean in this context? Similarly, what does “changes in pressure” mean?

I have been capturing sensor data for almost 2 decades and haven’t come close to running out of room yet. I typically use 30s for an update interval since I have determined that to generally be adequate. You need to figure out what you like. I use InfluxDB and Grafana and a sensor that doesn’t update frequently can be annoying (is the sensor dead or did it not send since it was the same, how do you know).

esphome makes it possible to sample frequently and update infrequently if that is what you want.

The sensor filters are a way to do that. round is not a way to do that.

This section is good.

I would do your calculations first (you can combine your lambdas and/or just use the multiply filter. The use an or with both a throttle and a delta

It all depends on what you are trying to achieve.

How to have a high sample rate on the ADC to catch quick changes, but only send to HA when there’s a significant change. That’s update_interval with a delta.

The 12-bit ADC on the ESP32 has more precision than I care about. But, I want to see short duration significant changes.

Using a short update_interval will sample the ADC frequently, but no point in sending those to HA if no significant change.

Right. It must be a round-trip “error” and it’s pretty harmless since the conversion of the rounded number results in the same value every time (so no state change). I assume HA has no knowledge of round used in ESPHome config, so it can’t really know to round the value before saving as text.

One can see how it’s a little confusing when round is used in ESPHome but it doesn’t look as expected in the resulting state.

Using delta and round together is probably not necessary.

I’m not clear how throttle would apply here when using update_interval.

Using them like @neel-m suggested with OR gives you output if delta threshold is reached OR throttle time is reached. Commonly used when one wants to have rapid response for notable changes but also regular updates.

By the way, I think it’s kind of interesting how the conversion is working:

sqlite> select state, anything_updated from states_by_name where entity_name = 'sensor.house_water_pressure_pressure' order by state_id desc limit 15;
state             anything_updated
----------------  -----------------------
64.1999969482422  2025-12-28 07:33:29.182
59.2000007629395  2025-12-28 07:32:49.178
54.0              2025-12-28 07:31:58.155
59.0              2025-12-28 07:29:37.115
64.5              2025-12-28 07:28:52.211
unavailable       2025-12-28 07:28:37.740
64.0999984741211  2025-12-28 07:28:01.627
62.7999992370605  2025-12-28 07:27:51.625
61.5999984741211  2025-12-28 07:27:46.622
59.7000007629395  2025-12-28 07:27:41.621
61.7999992370605  2025-12-28 07:27:36.620
63.0999984741211  2025-12-28 07:27:26.619
61.5999984741211  2025-12-28 07:27:16.608
58.4000015258789  2025-12-28 07:27:11.603
52.2999992370605  2025-12-28 07:26:56.602

It kind of looks like HA is just trimming trailing zeros, which is the interesting part.

(This doesn’t look exactly like how the conversion is happening, but shows the round-trip results.)

homeassistant:/config# python3 -c 'print("Round-trip:{:.30f}".format(float("64.5")))'
Round-trip:64.500000000000000000000000000000

homeassistant:/config# python3 -c 'print("Round-trip:{:.30f}".format(float("59.2")))'
Round-trip:59.200000000000002842170943040401

Again, not a problem, just interesting. No point in saving those insignificant digits.

Perfect. Essentially giving a heartbeat so you know the device is still sending updates. I think I read the throttle docs wrong:

Throttle the incoming values. When this filter gets an incoming value, it checks if the last incoming value is at least specified time period old. If it is not older than the configured value, the value is not passed forward.

Ignoring the delta for now, it says it’s comparing the time of the current incoming value with last incoming value. Am I reading that wrong?

That reads like using an update_interval: 5s the and throttle: 10s the throttle filter is seeing an incoming value every 5 seconds. It will never see an incoming value older than 10 seconds, so won’t ever pass.

To get that heartbeat ever 10s you would want to compare with the last value passed on, it would seem.

Update: throttle must look at the time since the last value that was passed on as it works as suggested.

Thanks.

Exactly.
And the documentation is not clearest possible.