khenderick / esphome-opentherm

OpenTherm support for ESPHome
MIT License
14 stars 4 forks source link

Bit errors? #10

Closed ShurikenGitHub closed 11 months ago

ShurikenGitHub commented 11 months ago

Hi,

Awesome work, best esphome opentherm implementation i have seen yet!

The only issue i have is that a couple times per hour bit errors occur, i tried to make a really solid connection between the boiler and my diyless opentherm shield but the bit errors still occur. Anyone else with the same issue? image

Is it maybe possible to implement some sort of error checking?

Thx

khenderick commented 11 months ago

Thanks, glad you can use it 😊.

The errors are strange, I can't find such issues on my setup. Would you be able to collect the logs around the time such error occurs? This might give a clue on what's going on.

ShurikenGitHub commented 11 months ago

Hi khenderick, Thanks for the lightning fast response! I tried to capture a bit error in the logs: at 19:31:54 the modulation goes from 0 to 0.24609 % but the flame isn't on so i guess this is a little bit error, see logs:

[19:31:48][D][sensor:093]: 'DHW temperature': Sending state 29.00000 °C with 1 decimals of accuracy [19:31:48][D][opentherm:279]: Sending request: READ_DATA(27, 0x0000) [19:31:48][W][opentherm:283]: Received invalid response: DATA_INVALID(27, 0x0000) [19:31:48][D][opentherm:279]: Enqueued request: WRITE_DATA(1, 0x1400) [19:31:48][D][opentherm:279]: Sending request: READ_DATA(48, 0x0000) [19:31:49][W][opentherm:518]: Request timeout [19:31:49][D][opentherm:279]: Sending request: READ_DATA(49, 0x0000) [19:31:49][D][opentherm:279]: Received response: READ_ACK(49, 0x551E) [19:31:49][D][sensor:093]: 'CH maximum temperature': Sending state 85.00000 °C with 1 decimals of accuracy [19:31:49][D][sensor:093]: 'CH minimum temperature': Sending state 30.00000 °C with 1 decimals of accuracy [19:31:50][D][opentherm:279]: Sending request: READ_DATA(115, 0x0000) [19:31:50][W][opentherm:283]: Received invalid response: DATA_INVALID(115, 0x0000) [19:31:50][D][opentherm:279]: Sending request: READ_DATA(5, 0x0000) [19:31:50][W][opentherm:283]: Received invalid response: DATA_INVALID(5, 0x0000) [19:31:50][D][opentherm:279]: Sending request: READ_DATA(6, 0x0000) [19:31:50][D][opentherm:279]: Received response: READ_ACK(6, 0x0303) [19:31:50][D][opentherm:279]: Enqueued request: WRITE_DATA(1, 0x1400) [19:31:50][D][opentherm:279]: Sending request: READ_DATA(0, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(28, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(25, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(31, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(19, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(18, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(17, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(26, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(27, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(48, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(49, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(115, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(5, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(6, 0x0000) [19:31:51][D][opentherm:279]: Enqueued request: READ_DATA(0, 0x0000) [19:31:51][W][opentherm:518]: Request timeout [19:31:51][D][opentherm:279]: Sending request: WRITE_DATA(1, 0x1400) [19:31:51][D][opentherm:279]: Received response: WRITE_ACK(1, 0x1400) [19:31:52][D][opentherm:279]: Sending request: WRITE_DATA(1, 0x1400) [19:31:52][D][opentherm:279]: Received response: WRITE_ACK(1, 0x1400) [19:31:52][D][opentherm:279]: Sending request: WRITE_DATA(1, 0x1400) [19:31:52][D][opentherm:279]: Received response: WRITE_ACK(1, 0x1400) [19:31:52][D][opentherm:279]: Sending request: READ_DATA(28, 0x0000) [19:31:52][D][opentherm:279]: Received response: READ_ACK(28, 0x2580) [19:31:52][D][sensor:093]: 'return temperature': Sending state 37.50000 °C with 1 decimals of accuracy [19:31:52][D][opentherm:279]: Enqueued request: WRITE_DATA(1, 0x1400) [19:31:52][D][opentherm:279]: Sending request: READ_DATA(25, 0x0000) [19:31:52][D][opentherm:279]: Received response: READ_ACK(25, 0x2600) [19:31:52][D][sensor:093]: 'boiler temperature': Sending state 38.00000 °C with 1 decimals of accuracy [19:31:53][D][opentherm:279]: Sending request: READ_DATA(31, 0x0000) [19:31:53][W][opentherm:283]: Received invalid response: UNKNOWN_DATA_ID(31, 0x0000) [19:31:53][D][opentherm:279]: Sending request: READ_DATA(19, 0x0000) [19:31:53][D][opentherm:279]: Received response: READ_ACK(19, 0x0000) [19:31:53][D][sensor:093]: 'DHW flow rate': Sending state 0.00000 L/min with 1 decimals of accuracy [19:31:53][D][opentherm:279]: Sending request: READ_DATA(18, 0x0000) [19:31:53][D][opentherm:279]: Received response: READ_ACK(18, 0x01B3) [19:31:53][D][sensor:093]: 'pressure': Sending state 1.69922 bar with 1 decimals of accuracy [19:31:53][D][opentherm:279]: Sending request: READ_DATA(17, 0x0000) [19:31:54][D][opentherm:279]: Received response: READ_ACK(17, 0x003F) [19:31:54][D][sensor:093]: 'modulation': Sending state 0.24609 % with 1 decimals of accuracy [19:31:54][D][opentherm:279]: Sending request: READ_DATA(26, 0x0000) [19:31:54][D][opentherm:279]: Enqueued request: WRITE_DATA(1, 0x1400) [19:31:54][D][opentherm:279]: Received response: READ_ACK(26, 0x1D19) [19:31:54][D][sensor:093]: 'DHW temperature': Sending state 29.09766 °C with 1 decimals of accuracy [19:31:54][D][opentherm:279]: Sending request: READ_DATA(27, 0x0000) [19:31:54][W][opentherm:283]: Received invalid response: DATA_INVALID(27, 0x0000) [19:31:55][D][opentherm:279]: Sending request: READ_DATA(48, 0x0000) [19:31:55][D][opentherm:279]: Received response: READ_ACK(48, 0x4128) [19:31:55][D][sensor:093]: 'DHW maximum temperature': Sending state 65.00000 °C with 1 decimals of accuracy [19:31:55][D][sensor:093]: 'DHW minimum temperature': Sending state 40.00000 °C with 1 decimals of accuracy [19:31:55][D][opentherm:279]: Sending request: READ_DATA(49, 0x0000) [19:31:55][D][opentherm:279]: Received response: READ_ACK(49, 0x551E) [19:31:55][D][sensor:093]: 'CH maximum temperature': Sending state 85.00000 °C with 1 decimals of accuracy [19:31:55][D][sensor:093]: 'CH minimum temperature': Sending state 30.00000 °C with 1 decimals of accuracy [19:31:55][D][opentherm:279]: Sending request: READ_DATA(115, 0x0000) [19:31:55][W][opentherm:283]: Received invalid response: DATA_INVALID(115, 0x0000)

Let me know if you need any more examples/different logs

khenderick commented 11 months ago

Thanks for the logs. I'll take a look as soon as possible, hopefully somewhere next week 🙂. I'll keep you posted.

khenderick commented 11 months ago

A few questions:

There is a parity bit validation in the code (both for sending and receiving), so I would not expect single bit errors, but something else might be going on :thinking:

ShurikenGitHub commented 11 months ago

Hi,

Setup: Atag i-serie boiler, diyless shield with an esp8266 wemos d1 mini (aliexpress varient), a cable of approx 50cm between the boiler and the esp. No other sensors/integrations on the esphome instance.

I also tried esphome opentherm from https://github.com/rsciriano/ESPHome-OpenTherm but it doesn't give any similar issues

[17:18:44][D][sensor:093]: 'return temperature': Sending state 33.39844 °C with 1 decimals of accuracy [17:18:44][D][opentherm:289]: Enqueued request: READ_DATA(0, 0x0000) [17:18:44][D][opentherm:289]: Sending request: READ_DATA(0, 0x0000) [17:18:44][D][opentherm:289]: Enqueued request: READ_DATA(25, 0x0000) [17:18:44][D][opentherm:289]: Enqueued request: READ_DATA(31, 0x0000) [17:18:44][D][opentherm:289]: Received response: READ_ACK(0, 0x0000) [17:18:44][D][opentherm:289]: Sending request: READ_DATA(25, 0x0000) [17:18:45][D][opentherm:289]: Received response: READ_ACK(25, 0x2199) [17:18:45][D][sensor:093]: 'boiler temperature': Sending state 33.59766 °C with 1 decimals of accuracy [17:18:45][D][opentherm:289]: Sending request: READ_DATA(31, 0x0000) [17:18:45][D][opentherm:289]: Enqueued request: READ_DATA(19, 0x0000) [17:18:45][D][opentherm:289]: Enqueued request: WRITE_DATA(1, 0x1400) [17:18:45][W][opentherm:293]: Received invalid response: UNKNOWN_DATA_ID(31, 0x0000) [17:18:45][D][opentherm:289]: Sending request: READ_DATA(19, 0x0000) [17:18:45][D][opentherm:289]: Received response: READ_ACK(19, 0x0000) [17:18:45][D][sensor:093]: 'DHW flow rate': Sending state 0.00000 L/min with 1 decimals of accuracy [17:18:45][D][opentherm:289]: Sending request: WRITE_DATA(1, 0x1400) [17:18:45][D][opentherm:289]: Received response: WRITE_ACK(1, 0x1400) [17:18:45][D][opentherm:289]: Enqueued request: READ_DATA(18, 0x0000) [17:18:45][D][opentherm:289]: Sending request: READ_DATA(18, 0x0000) [17:18:46][D][opentherm:289]: Enqueued request: READ_DATA(17, 0x0000) [17:18:46][D][opentherm:289]: Received response: READ_ACK(18, 0x01B3) [17:18:46][D][sensor:093]: 'pressure': Sending state 1.69922 bar with 1 decimals of accuracy [17:18:46][D][opentherm:289]: Enqueued request: READ_DATA(26, 0x0000) [17:18:46][D][opentherm:289]: Sending request: READ_DATA(17, 0x0000) [17:18:46][D][opentherm:289]: Received response: READ_ACK(17, 0x0000) [17:18:46][D][sensor:093]: 'modulation': Sending state 0.00000 % with 1 decimals of accuracy [17:18:46][D][opentherm:289]: Sending request: READ_DATA(26, 0x0000) [17:18:46][D][opentherm:289]: Received response: READ_ACK(26, 0x1D66) [17:18:46][D][sensor:093]: 'DHW temperature': Sending state 29.39844 °C with 1 decimals of accuracy [17:18:46][D][opentherm:289]: Enqueued request: READ_DATA(27, 0x0000) [17:18:46][D][opentherm:289]: Sending request: READ_DATA(27, 0x0000) [17:18:47][D][opentherm:289]: Enqueued request: READ_DATA(48, 0x0000) [17:18:47][W][opentherm:293]: Received invalid response: DATA_INVALID(27, 0x0000) [17:18:47][D][opentherm:289]: Sending request: READ_DATA(48, 0x0000) [17:18:47][D][opentherm:289]: Enqueued request: WRITE_DATA(1, 0x1400) [17:18:47][D][opentherm:289]: Received response: READ_ACK(48, 0x4128) [17:18:47][D][sensor:093]: 'DHW maximum temperature': Sending state 65.00000 °C with 1 decimals of accuracy [17:18:47][D][sensor:093]: 'DHW minimum temperature': Sending state 40.00000 °C with 1 decimals of accuracy [17:18:47][D][opentherm:289]: Sending request: WRITE_DATA(1, 0x1400) [17:18:47][D][opentherm:289]: Enqueued request: READ_DATA(49, 0x0000) [17:18:47][D][opentherm:289]: Received response: WRITE_ACK(1, 0x1400) [17:18:47][D][opentherm:289]: Sending request: READ_DATA(49, 0x0000) [17:18:47][D][sensor:093]: 'Opentherm Wi-Fi Signal': Sending state -56.00000 dBm with 0 decimals of accuracy [17:18:47][D][sensor:093]: 'Opentherm Wi-Fi Signal Percentage': Sending state 88.00000 % with 1 decimals of accuracy [17:18:47][D][opentherm:289]: Received response: READ_ACK(49, 0x551E) [17:18:47][D][sensor:093]: 'CH maximum temperature': Sending state 85.00000 °C with 1 decimals of accuracy [17:18:47][D][sensor:093]: 'CH minimum temperature': Sending state 30.00000 °C with 1 decimals of accuracy [17:18:48][D][opentherm:289]: Enqueued request: READ_DATA(115, 0x0000) [17:18:48][D][opentherm:289]: Sending request: READ_DATA(115, 0x0000) [17:18:48][W][opentherm:293]: Received invalid response: DATA_INVALID(115, 0x0000) [17:18:48][D][opentherm:289]: Enqueued request: READ_DATA(5, 0x0000) [17:18:48][D][opentherm:289]: Sending request: READ_DATA(5, 0x0000) [17:18:48][D][opentherm:289]: Enqueued request: READ_DATA(6, 0x0000) [17:18:48][W][opentherm:293]: Received invalid response: DATA_INVALID(5, 0x0000) [17:18:49][D][opentherm:289]: Sending request: READ_DATA(6, 0x0000) [17:18:49][D][opentherm:289]: Received response: READ_ACK(6, 0x0303) [17:18:49][D][opentherm:289]: Enqueued request: WRITE_DATA(1, 0x1400) [17:18:49][D][opentherm:289]: Sending request: WRITE_DATA(1, 0x1400) [17:18:49][D][opentherm:289]: Enqueued request: READ_DATA(28, 0x0000) [17:18:49][D][opentherm:289]: Received response: WRITE_ACK(1, 0x1400) [17:18:49][D][opentherm:289]: Sending request: READ_DATA(28, 0x0000) [17:18:49][D][opentherm:289]: Enqueued request: READ_DATA(0, 0x0000) [17:18:49][D][opentherm:289]: Enqueued request: READ_DATA(25, 0x0000) [17:18:49][D][opentherm:289]: Enqueued request: READ_DATA(31, 0x0000) [17:18:50][D][opentherm:289]: Enqueued request: READ_DATA(19, 0x0000) [17:18:50][D][opentherm:289]: Received response: READ_ACK(28, 0x274C) [17:18:50][D][sensor:093]: 'return temperature': Sending state 39.29688 °C with 1 decimals of accuracy [17:18:50][D][opentherm:289]: Sending request: READ_DATA(0, 0x0000) [17:18:50][D][opentherm:289]: Received response: READ_ACK(0, 0x0000) [17:18:50][D][opentherm:289]: Sending request: READ_DATA(25, 0x0000) [17:18:50][D][opentherm:289]: Received response: READ_ACK(25, 0x2199) [17:18:50][D][sensor:093]: 'boiler temperature': Sending state 33.59766 °C with 1 decimals of accuracy [17:18:50][D][opentherm:289]: Sending request: READ_DATA(31, 0x0000) [17:18:50][D][opentherm:289]: Enqueued request: READ_DATA(18, 0x0000) [17:18:51][D][opentherm:289]: Enqueued request: READ_DATA(17, 0x0000) [17:18:51][W][opentherm:293]: Received invalid response: UNKNOWN_DATA_ID(31, 0x0000) [17:18:51][D][opentherm:289]: Enqueued request: READ_DATA(26, 0x0000) [17:18:51][D][opentherm:289]: Sending request: READ_DATA(19, 0x0000) [17:18:51][D][opentherm:289]: Enqueued request: WRITE_DATA(1, 0x1400) [17:18:51][D][opentherm:289]: Received response: READ_ACK(19, 0x0000) [17:18:51][D][sensor:093]: 'DHW flow rate': Sending state 0.00000 L/min with 1 decimals of accuracy [17:18:51][D][opentherm:289]: Sending request: READ_DATA(18, 0x0000) [17:18:51][D][opentherm:289]: Received response: READ_ACK(18, 0x01B3) [17:18:51][D][sensor:093]: 'pressure': Sending state 1.69922 bar with 1 decimals of accuracy [17:18:51][D][opentherm:289]: Sending request: READ_DATA(17, 0x0000) [17:18:51][D][opentherm:289]: Received response: READ_ACK(17, 0x0000) [17:18:51][D][sensor:093]: 'modulation': Sending state 0.00000 % with 1 decimals of accuracy [17:18:51][D][opentherm:289]: Sending request: READ_DATA(26, 0x0000) [17:18:51][D][opentherm:289]: Enqueued request: READ_DATA(27, 0x0000) [17:18:52][D][opentherm:289]: Received response: READ_ACK(26, 0x1D66) [17:18:52][D][sensor:093]: 'DHW temperature': Sending state 29.39844 °C with 1 decimals of accuracy [17:18:52][D][opentherm:289]: Enqueued request: READ_DATA(48, 0x0000) [17:18:52][D][opentherm:289]: Sending request: WRITE_DATA(1, 0x1400) [17:18:52][D][opentherm:289]: Received response: WRITE_ACK(1, 0x1400) [17:18:52][D][opentherm:289]: Sending request: READ_DATA(27, 0x0000) [17:18:52][W][opentherm:293]: Received invalid response: DATA_INVALID(27, 0x0000) [17:18:52][D][opentherm:289]: Enqueued request: READ_DATA(49, 0x0000) [17:18:52][D][opentherm:289]: Sending request: READ_DATA(48, 0x0000) [17:18:52][D][opentherm:289]: Received response: READ_ACK(48, 0x4128) [17:18:52][D][sensor:093]: 'DHW maximum temperature': Sending state 65.00000 °C with 1 decimals of accuracy [17:18:52][D][sensor:093]: 'DHW minimum temperature': Sending state 40.00000 °C with 1 decimals of accuracy [17:18:52][D][opentherm:289]: Sending request: READ_DATA(49, 0x0000) [17:18:52][D][opentherm:289]: Received response: READ_ACK(49, 0x551E) [17:18:52][D][sensor:093]: 'CH maximum temperature': Sending state 85.00000 °C with 1 decimals of accuracy [17:18:52][D][sensor:093]: 'CH minimum temperature': Sending state 30.00000 °C with 1 decimals of accuracy [17:18:53][D][opentherm:289]: Enqueued request: READ_DATA(115, 0x0000) [17:18:53][D][opentherm:289]: Enqueued request: WRITE_DATA(1, 0x1400) [17:18:53][D][opentherm:289]: Sending request: READ_DATA(115, 0x0000) [17:18:53][W][opentherm:293]: Received invalid response: DATA_INVALID(115, 0x0000) [17:18:53][D][opentherm:289]: Sending request: WRITE_DATA(1, 0x1400) [17:18:53][D][opentherm:289]: Received response: WRITE_ACK(1, 0x1400) [17:18:53][D][opentherm:289]: Enqueued request: READ_DATA(5, 0x0000) [17:18:53][D][opentherm:289]: Sending request: READ_DATA(5, 0x0000) [17:18:53][D][opentherm:289]: Enqueued request: READ_DATA(6, 0x0000) [17:18:53][W][opentherm:293]: Received invalid response: DATA_INVALID(5, 0x0000) [17:18:54][D][opentherm:289]: Sending request: READ_DATA(6, 0x0000) [17:18:54][D][opentherm:289]: Received response: READ_ACK(6, 0x0303) [17:18:54][D][opentherm:289]: Enqueued request: READ_DATA(28, 0x0000) [17:18:54][D][opentherm:289]: Sending request: READ_DATA(28, 0x0000) [17:18:54][D][opentherm:289]: Received response: READ_ACK(28, 0x214C) [17:18:54][D][sensor:093]: 'return temperature': Sending state 33.29688 °C with 1 decimals of accuracy

At 17:18:50 the return temperature goes from 33.39844 to 39.29688

khenderick commented 11 months ago

Interesting. That component seems to use sync calls, so that's an interesting path.

The cable in my base is a few meters, so that should be fine.

Do you have an ESP32 that you could temporarily hook up? I'm not sure my code is 100% ESP8266 compatible, so that's another thing that's worth investigating.

My code is bitbanging everything and is also using interrupts for receiving. The lack of power of the ESP8266 compared to the ESP32 might result in messed up data. I'm working on a bunch of changes that spread the calls more, and should thus be less intensive. Let's see if I can quickly wrap a few thing up so you can give that a try.

khenderick commented 11 months ago

Can you give following a try:

...

external_components:
  source: github://khenderick/esphome-opentherm@communication
  components: [opentherm]
  refresh: 0s

...
ShurikenGitHub commented 11 months ago

I tried the new code but it doesn't work on the esp8266, i will try it with an esp32. I also uploaded a log here above ^

khenderick commented 11 months ago

Hmmm, didn't expect compile errors. Can you share the compile output?

ShurikenGitHub commented 11 months ago

Sorry it compiled fine, but it still has biterrors that's what i meant with doesn't work

khenderick commented 11 months ago

The graph shows a dip from ~43 to ~-21 degrees, and this only needs 2 bits flipped, which won't be detected by the protocol's parity bit. The modulation level of 0.24609 is 0b111111 while we would suspect 0b0, again not detectable by the parity check. Since there are quite a bunch of invalid data messages in the logs, it seems like the parity checks are working, but it's just too much.

The other component you mentioned is based on the same library as this component, but seems (as far as I understand) to use only a fraction of the possibilities and runs synchronously, which is less intensive (as it sends data, and then just blocks waiting for the answer). I think that might be the reason why that component runs fine on the ESP8266 and this component struggles.

One of the reasons it's unlikely these components will be accepted in ESPHome in their current state is because the raw bit-banging in software instead of offloading it to hardware. The ESP should be able to do other things and a component should not interfere with other components. I hope to eventually implement this (and get it included in ESPHome), but it seems this offloading will only be possible for the ESP32 because the ESP8266 seems to lack the needed hardware support.

I think this component works good for everyday use as long as it gets sufficient power and runs on a dedicated device so it won't interfere with other components. I have it running fine on an ESP32 version of the WEMOS D1 mini with no significant other components.

However, back to your case, I'm not sure how to solve these. I don't think it would be a good idea to start adding filters etc in the component trying to figure out whether a certain value (that passes the parity check) makes sense or not as the build-in ESPHome filters already provide such functionality. I would suggest to play with those to filter out invalid values, or make them at least less intrusive. Another option is trying with an ESP32. If you would still see issues with an ESP32, please do let me know. In any case, just let me know if I can help.

ShurikenGitHub commented 11 months ago

I tested it with the ESP32 but there are still bit errors unfortunately. I will check if there is any loose connections to see if that solves the problem. Thank you for all the efforts made!

khenderick commented 11 months ago

You're welcome. Keep me posted!

ShurikenGitHub commented 11 months ago

Rewired everything and there is still biterrors, even worse now, it now has the same problem with the opentherm implementation of rsciriano. Very weird that it has such a bad connection for such a small distance since the cable is directly connected to the main pcb of the boiler.... Can't get my head around it why it would be so bad. I'm using quite a thick/low gauge cable but this shouldn't matter too much I guess? Anyways, it has nothing to do with your awesome code so I guess we can close this one?

khenderick commented 11 months ago

I'm using low-end speaker cable (about 18 gauge / 0.75 mm2) over about 3 to 4 meters. And typically these wires can run a lot further when wired to a classic thermostat a few rooms away. So I'm not suspecting the cable itself.

From previous experiences regarding crappy wires that need to carry signals, I'd suggest to check following things (you might already checked them, but they might be interesting if others find this thread in the future);

I'm sorry I couldn't help more. It seems like adding some extra filters will be the only feasible option in filtering those error readings out. If you need more/other help with this library, feel free to create a new ticket :+1: .