diff --git a/Payload-data-read.md b/Payload-data-read.md
index 0f9abcd..0c4bf9f 100644
--- a/Payload-data-read.md
+++ b/Payload-data-read.md
@@ -23,359 +23,473 @@ This document describes payload data of few **selected readable packet types** (
### Data types
-The following data types were observed in the payload. Bytes are ordered ordered in a "normal" way, i.e. big endian:
-
-| Data type | Definition |
-| --------- | ------------------------------------------------------------ |
-| flag8 | byte composed of 8 single-bit flags |
-| u8 | unsigned 8-bit integer 0 .. 255 |
-| u16 | unsigned 16-bit integer 0..65535 |
-| u24 | unsigned 24-bit integer 0..16777215 |
-| f8.8 | signed fixed point value : 1 sign bit, 7 integer bit, 8 fractional bits (two’s compliment, see explanation below) |
-| f8/8 | Daikin-style fixed point value: 1st byte is value before comma, and 2nd byte is first digit after comma (see explanation below) |
-| s-abs4 | Daikin-style temperature deviation: bit 4 is sign bit, bits 0-3 is absolute value of deviation |
-
-Explanation of **f8.8** format: a temperature of 21.5°C in f8.8 format is represented by the 2-byte value in 1/256th of a unit as 1580 hex (1580hex = 5504dec, dividing by 256 gives 21.5). A temperature of -5.25°C in f8.8 format is represented by the 2-byte value FAC0 hex (FAC0hex = - (10000hex-FAC0hex) = - 0540hex = - 1344dec, dividing by 256 gives -5.25).
-
-Explanation of **f8/8** format: a temperature of 21.5°C in f8/8 format is represented by the byte value of 21 (0x15) followed by the byte value of 5 (0x05). So far this format was only detected for the setpoint temperature, which is usually not negative, so we don't know how negative numbers are stored in this format.
-
-# Packet type 0x10
-
-### Packet type 0x10: request
-
-Header: 0x000010
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | -------------------------------- | --------- | ------------------------------------------------------------ |
-| 0 | Climate | flag8 | 0: power (off/on) |
-| 1 | Climate status | flag8 | 0: heating (off/on)
1: cooling (off/on)
7: status (standby / running) |
-| 2 | DHW tank | flag8 | 0: power (off/on) |
-| 3 | ? | | |
-| 4 | ? | | |
-| 5 | ? | | |
-| 6 | ? | | |
-| 7 | Target room temperature | u8 | |
-| 8 | ? | | |
-| 9 | Heating/cooling operation mode ? | flag8 | 5: ?
6: ? |
-| 10 | Quiet mode | flag8 | 2: quiet mode (off/on) |
-| 11 | ? | | |
-| 12 | ?? | flag8 | 3: ? |
-| 13 | ? | | |
-| 14 | ? | | |
-| 15 | ?? | flag8 | 0: ?
1: ?
2: ?
3: ? |
-| 16 | ? | | |
-| 17 | DHW tank mode | flag8 | 1: booster (off/on)
6: operation (off/on) |
-| 18-19 | DHW target temperature | f8/8 | |
-
-### Packet type 0x10: response
-
-Header: 0x400010
-
-| Data byte | Description | Data type | Bit: description |
-| ---------- | ----------------------- | ---------- | ------------------------------------------------------------ |
-| 0 | LWT control | flag8 | 0: LWT control (off/on) |
-| 1 | ?? | flag8 | 7: ? |
-| 2 | Valves | flag8 | 0: heating (off/on)
1: cooling (off/on)
4: ?
5: main zone (off/on)
6: additional zone (off/on)
7: DHW tank (off/on) |
-| 3 | DHW control | flag8 | 0: DHW control (off/on)
4: DHW boost (off/on) |
-| 4-5 | DHW target temperature | f8/8 | |
-| 6 | ?? | flag8 | 0: ?
1: ?
2: ?
3: ? |
-| 7 | ? | | |
-| 8 | Target room temperature | u8 | |
-| 9 | ? | | |
-| 10 | Space operation mode | flag8 | 1: ?
3: ?
4: ?
5: auto (off/on)
6: ? |
-| 11 | Quiet mode | flag8 | 2: quiet mode (off/on) |
-| 12-16 | ? | | |
-| 17 | Operation mode | flag8 | 0: DHW boost (off/on)
1: Defrost (off/on)
6: DHW (off/on) |
-| 18 | Pump and compressor | flag8 | 0: compressor (off/on)
3: pump (off/on) |
-| 19 | DHW ? | flag8 | 1: ?
0: mode?? |
-
-# Packet type 0x11
-
-### Packet type 0x11: request
-
-Header: 0x000011
-
-| Data byte | Description | Data type | Bit: description |
-| ---------- | ----------------------- | ---------- | ----------------- |
-| 0-1 | Actual room temperature | f8.8 | |
-| 2 | ? | | |
-| 3 | ? | | |
-| 4 | ? | | |
-| 5 | ? | | |
-| 6 | ? | | |
-| 7 | ? | | |
-
-### Packet type 0x11: response
-
-Header: 0x400011
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | ------------------------------------------------------------ | --------- | ---------------- |
-| 0-1 | Leaving water temperature | f8.8 | |
-| 2-3 | DHW temperature | f8.8 | |
-| 4-5 | Outside temperature 1 (raw; in 0.5 degree resolution) | f8.8 | |
-| 6-7 | Returning water temperature | f8.8 | |
-| 8-9 | Mid-way temperature (heat exchanger) | f8.8 | |
-| 10-11 | Refrigerant temperature | f8.8 | |
-| 12-13 | Actual room temperature | f8.8 | |
-| 14-15 | External temperature sensor (if connected);
otherwise Outside temperature 2 derived from external unit sensor, but stabilized; it does not change during defrosts; it also adds extra variations not in raw outside temperature, perhaps due to averaging over samples | f8.8 | |
-| 16-17 | ? | | |
-
-# Packet type 0x12
-
-### Packet type 0x12: request
-
-Header: 0x000012
-
-| Data byte | Description | Data type | Bit: description |
-| ---------- | ------------------------------------------------------------ | --------- | --------------------------------- |
-| 0 | new hour value | flag8 | 1: new-hour or restart indicator |
-| 1 | day of week (0=Monday, 6=Sunday) | u8 | |
-| 2 | time - hours | u8 | |
-| 3 | time - minutes | u8 | |
-| 4 | date - year (0x13 = 2019) | u8 | |
-| 5 | date - month | u8 | |
-| 6 | date - day of month | u8 | |
-| 7-11 | ? | u8 | |
-| 12 | upon restart: 1x 00; 1x 01; then 41; a single value of 61 triggers an immediate restart | flag8 | 1: ?
5: reboot
6: ? |
-| 13 | once 00, then 04 | flag 8 | 2: ? |
-| 14 | ? | | |
-
-### Packet type 0x12: response
-
-Header: 0x400012
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | --------------------------------------------------------- | --------- | ------------------------------------------------------------ |
-| 0 | ?? | | |
-| 1 | ?? | | |
-| 2-9 | ? | | |
-| 9 | External thermostat main | flag8 | 1: main B - cooling (off/on)
2: main A - heating (off/on) |
-| 10 | kWh preference input(s)
External thermostat additional | flag8 | 4: preference kWh input
7: additional B - cooling (off/on) |
-| 11 | Current limit in 0.1 A ?? | u8 | |
-| 12 | operating mode | flag8 | 0: heat pump? 6: gas? 7: DHW active2 ? |
-| 13 | ? | | |
-| 14-29 | ? | | |
-
-
-# Packet type 0x13
-
-### Packet type 0x13: request
-
-Header: 0x000013
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | ---------------------------------- | --------- | ---------------- |
-| 0-1 | ? | | |
-| 2 | first package 0x00 instead of 0xD0 | flag8 ? | |
-
-### Packet type 0x13: response
-
-Header: 0x400013
-
-| Data byte | Description | Data type | Bit: description |
-| --------------- | ------------------------------------------------------------ | ----------- | ---------------- |
-| 0 | DHW target temperature
(one packet delayed/from/via boiler?/ 0 in first packet after restart) | u8 / f8.8 ? | |
-| 1 | ? | | |
-| 2 | ?? | | |
-| 3 | ?? | | |
-| 4-6 | ? | | |
-| 7 | no flow | | FF = no flow |
-| 8-9 | flow (in 0.1 l/min) | u16 | |
-| 10-11 | software version inner unit | u16 | |
-| 12-13 | software version outer unit | u16 | |
-| EHV only: 14 | ?? | u8 | |
-| EHV only: 15 | ?? | u8 | |
-
-# Packet type 0x14
-
-### Packet type 0x14: request
-
-Header: 0x000014
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | --------------------------------------------------------- | ---------- | ----------------- |
-| 0-1 | Target LWT main zone | f8/8 | |
-| 2 | ?? | | |
-| 3 | ? | | |
-| 4 | ?? first package 0x37 instead of 0x2D (55 instead of 45) | u8 | |
-| 5 | ? | | |
-| 6 | ?? first package 0x37 instead of 0x07 | u8 | |
-| 7 | ? | | |
-| 8 | delta-T | s-abs4 | |
-| 9 | ?? night/eco related mode ? 7:00: 02 9:00: 05 | | |
-| 10-11 | ? | | |
-| 12 | first package 0x37 instead of 0x00 | | |
-| 13-14 | ? | | |
-
-### Packet type 0x14: response
-
-Header: 0x400014
-
-| Data byte | Description | Data type | Bit: description |
-| ---------- | ------------------------------------ | ---------- | ----------------- |
-| 0-1 | Target LWT main zone (desired) | f8/8 | |
-| 2-3 | ?? | f8/8 | |
-| 4-5 | Target LWT additional zone (desired) | f8/8 | |
-| 6 | ? | | |
-| 7 | ? | | |
-| 8 | ? LWT offset | | |
-| 9 | ? | | |
-| 10-14 | | | |
-| 15-16 | Target LWT main zone (actual) | f8/8 | |
-| 17-18 | Target LWT additional zone (actual) | f8/8 | |
-
-# Packet type 0x15
-
-### Packet type 0x15: request
-
-Header: 0x000015
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | -------------------------- | --------- | ---------------- |
-| 0 | ? | | |
-| 1-2 | operating mode? 7:30: 01D6 | | |
-| 3 | ? | | |
-| 4 | ?? | | |
-| 5 | ?? | | |
-
-### Packet type 0x15: response
-
-Header: 0x400015
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | ------------------------------------------------ | --------- | ---------------- |
-| 0-1 | ? | | |
-| 2-3 | Refrigerant temperature in 0.5 degree resolution | f8.8 | |
-| 4-5 | ? | | |
-| 6* | parameter number (see table bellow) | u8 | |
-| 7* | (part of parameter or parameter value?) | u8 | |
-| 8* | ?? | u8 | |
-
-*observed on Daikin Altherma LT (EHVH/EHVX) heat pumps, missing on Daikin Altherma Hybrid (EHYHBX)
-
-| Parameter number | Parameter Value | Description | Data type | Bit: description |
-| ---------------- | --------------- | ------------------ | --------- | ---------------- |
-| 05 | 96 | 15.0 degree ? | u8div10 | |
-| 08 | 73,78,7D | 11.5, 12.0, 12.5 ? | u8div10 | |
-| 0A | C3,C8 | 19.5, 20.0 | u8div10 | |
-| 0C | 6E,73,78 | 11.0, 11.5, 12.0 | u8div10 | |
-| 0E | B9,BE | 18.5, 19.0 | u8div10 | |
-| 0F | 68,6B | 10.4, 10.7 | u8div10 | |
-| 10 | 05 | 0.5 | u8div10 | |
-| 19 | 01 | 0.1 | u8div10 | |
-| others | 00 | ?? | u8 | |
-
-
-# Packet type 0x16
-
-observed on Daikin Altherma LT (EHVH/EHVX) heat pumps, missing on Daikin Altherma Hybrid (EHYHBX)
-
-### Packet type 0x16: request
-
-Header: 0x000016
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | ----------------- | --------- | ---------------- |
-| 0-1 | ? | | |
-| 2-3 | room temperature? | f8.8 | |
-| 4-15 | ? | | |
-
-### Packet type 0x16: response
-
-Header: 0x400016
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | -------------------------------- | --------- | ---------------- |
-| 0 | Current in 0.1 A | u8div10 | |
-| 1 | Power input in 0.1 kW | u8div10 | |
-| 2 | ? | | |
-| 3 | ? | | |
-| 4 | ? | | |
-| 5 | ? | | |
-| 6 | Heating/cooling output in 0.1 kW | u8div10 | |
-| 7 | DHW output in 0.1 kW | u8div10 | |
-| 8 | ?? | | |
-
-# Packet type 0xB8
-
-These packets contain counters for energy consumed and produced, operating hours and number of starts. Communication in packet type B8 is specific. In request, master specifies data type it would like to receive. Slave (heat pump) responds with the requested data type.
-
-### Packet type 0xB8: request
-
-Header: 0x0000B8
-
-| Data byte | Description | Data type | Byte: description |
-| --------- | ----------- | --------- | ------------------------------------------------------------ |
-| 0 | Data type | u8 | 0x00: energy consumed (kWh)
0x01: energy produced (kWh)
0x02: pump and compressor hours
0x03: backup heater hours
0x04: compressor starts
0x05: gas boiler hours |
-
-### Packet type 0xB8: response
-
-Header: 0x4000B8
-
-#### Data type 0x00
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | -------------------------------------------- | --------- | ---------------- |
-| 0 | Data type 0x00 | u8 | |
-| 1-3 | energy consumed for heating (backup heater?) | u24 | |
-| 4-6 | energy consumed for DHW (backup heater?) | u24 | |
-| 7-9 | energy consumed for heating (compressor?) | u24 | |
-| 10-12 | energy consumed for cooling | u24 | |
-| 13-15 | energy consumed for DHW (compressor?) | u24 | |
-| 16-18 | energy consumed total | u24 | |
+The following data-types were observed or suspected in the payload data:
+
+| Data type | Definition |
+|---------------|:-------------------------------------|
+| flag8 | byte composed of 8 single-bit flags |
+| c8 | ASCII character byte |
+| s8 | signed 8-bit integer -128 .. 127 |
+| u8 | unsigned 8-bit integer 0 .. 255 |
+| u6 | unsigned 6-bit integer 0 .. 63 |
+| u2 | unsigned 2-bit integer 0 .. 3 or 00 .. 11 |
+| s16 | signed 16-bit integer -32768..32767 |
+| u16 | unsigned 16-bit integer 0 .. 65535 |
+| u24 | unsigned 24-bit integer |
+| u32 | unsigned 32-bit integer |
+| u16hex | unsigned 16-bit integer output as hex 0x0000-0xFFFF |
+| u24hex | unsigned 24-bit integer |
+| u32hex | unsigned 32-bit integer |
+| f8.8 (code: f8_8) | signed fixed point value : 1 sign bit, 7 integer bit, 8 fractional bits (two’s compliment, see explanation below) |
+| f8/8 (code: f8s8) | Daikin-style fixed point value: 1st byte is value before comma, and 2nd byte is first digit after comma (see explanation below) |
+| s-abs4 | Daikin-style temperature deviation: bit 4 is sign bit, bits 0-3 is absolute value of deviation |
+| sfp7 | signed floating point value: 1 sign bit, 4 mantissa bits, 2 exponent bits (used for field settings) |
+| u8div10 | unsigned 8-bit integer 0 .. 255, to be divided by 10 |
+| u16div10 | unsigned 16-bit integer 0 .. 65535, to be divided by 10 |
+| t8 | schedule moment in 10 minute increments from midnight (0=0:00, 143=23:50) |
+| d24 | day in format YY MM DD |
+
+Explanation of f8.8 format: a temperature of 21.5°C in f8.8 format is represented by the 2-byte value in 1/256th of a unit as 1580 hex (1580hex = 5504dec, dividing by 256 gives 21.5). A temperature of -5.25°C in f8.8 format is represented by the 2-byte value FAC0 hex (FAC0hex = - (10000hex-FACOhex) = - 0540hex = - 1344dec, dividing by 256 gives -5.25).
+
+Explanation of f8/8 format: a temperature of 21.5°C in f8/8 format is represented by the byte value of 21 (0x15) followed by the byte value of 5 (0x05). So far this format was only detected for the setpoint temperature, which is usually not negative, so we don't know how negative numbers are stored in this format.
+
+# Packet types 10-1F form communication package between main controller and heat pump
+
+Packet types 10-16 are part of the regular communication pattern between main controller and heat pump.
+
+## Packet type 10 - operating status
+
+### Packet type 10: request
+
+Header: 000010
+
+|Byte(:bit)| Hex value observed | Description | Data type
+|:---------|:-------------------|:-------------------------|:-
+|0:0 | 0/1 | Heat pump (off/on) | bit
+|0:other | 0 | ? | bit
+|1:7 | 0/1 | Heat pump (off/on) | bit
+|1:0 | 0/1 | 1=Heating mode | bit
+|1:1 | 0/1 | 1=Cooling mode | bit
+|1:0 | 1 | Operating mode gas? | bit
+|1:other | 0 | Operating mode? | bit
+|2:1 | 0/1 | DHW tank power (off/on) | bit
+|2:0 | 0/1 | DHW (off/on) | bit
+|2:other | 0 | ? | bit
+| 3 | 00 | ? |
+| 4 | 00 | ? |
+| 5 | 00 | ? |
+| 6 | 00 | ? |
+| 7-8 | 13 05 | Target room temperature | f8.8
+| 9:6 | 0/1 | ? | bit
+| 9:5 | 0/1 | Heating/Cooling automatic mode | bit
+| 9:others | 0 | ? | bit
+|10:2 | 0/1 | Quiet mode (off/on) | bit
+|10:others | 0 | ? | bit
+| 11 | 00 | ? |
+|12:3 | 1 | ? | bit
+|12:others | 0 | ? | bit
+| 13 | 00 | ? |
+| 14 | 00 | ? |
+| 15 | 0F | ? | flag8/bits?
+| 16 | 00 | ? |
+|17:6 | 0/1 | operation (off/on) | bit
+|17:1 | 0/1 | booster (off/on) | bit
+|17:others | 0 | ? | bit
+| 18 | 3C | DHW target temperature | u8 / f8.8?
+| 19 | 00 | fractional part byte 18? |
+
+### Packet type 10: response
+
+Header: 400010
+
+|Byte(:bit)| Hex value observed | Description | Data type
+|:---------|:-------------------|:-------------------------|:-
+| 0:0 | 0/1 | Heating power (off/on) | bit
+| 0:other | 0 | ? | bit
+| 1:7 | 0/1 | Operating mode gas? | bit
+| 1:0 | 0 | Operating mode? | bit
+| 1:other | 0 | Operating mode? | bit
+| 2:7 | 0/1 | DHW tank power (off/on) | bit
+| 2:6 | 0/1 | Additional zone (off/on) | bit
+| 2:5 | 0/1 | Main zone (off/on) | bit
+| 2:4 | 0/1 | ? | bit
+| 2:3 | 0 | ? | bit
+| 2:2 | 0 | ? | bit
+| 2:1 | 0/1 | cooling (off/on) | bit
+| 2:0 | 0/1 | heating (off/on) | bit
+| 3:4 | 0/1 | **DHW boost (off/on)** | bit
+| 3:0 | 0/1 | **DHW (off/on)** | bit
+| 3:others | 0 | ? | bit
+| 4 | 3C | DHW target temperature| u8 / f8.8?
+| 5 | 00 | +fractional part? |
+| 6 | 0F | ? | u8 / flag8?
+| 7 | 00 | ?
+| 8 | 14 | Target room temperature | u8 / f8.8?
+| 9 | 00 | ?
+|10 | 1A | ?
+|11:2 | 0/1 | Quiet mode (off/on) | bit
+|11 | 0 | ? | bit
+|12 | 00 | Error code part 1 | u8
+|13 | 00 | Error code part 2 | u8
+|14 | 00 | Error subcode | u8
+|15-17 | 00 | ?
+|17:1 | 0/1 | Defrost operation | bit
+|18:3 | 0/1 | Circ.pump (off/on) | bit
+|18:1 | 0/1 | ? | bit
+|18:0 | 0/1 | Compressor (off/on) | bit
+|18:other | 0 | ? | bit
+|19:2 | 0/1 | DHW mode | bit
+|19:1 | 0/1 | gasboiler active1 (off/on) | bit
+|19:other | 0 | ? | bit
+
+Error codes: tbd, HJ-11 is coded as 024D2C, 89-2 is coded as 08B908, 89-3 is coded as 08B90C.
+
+## Packet type 11 - temperatures
+
+### Packet type 11: request
+
+Header: 000011
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------|:-------------------|:------------------------|:-
+| 0-1 | XX YY | Actual room temperature | f8.8
+| 2 | 00 | ?
+| 3 | 00 | ?
+| 4 | 00 | ?
+| 5 | 00 | ?
+| 6 | 00 | ?
+| 7 | 00 | ?
+
+### Packet type 11: response
+
+Header: 400011
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------|:-------------------|:------------------------------------------------------|:-
+| 0-1 | XX YY | LWT temperature | f8.8
+| 2-3 | XX YY | DHW temperature tank (if present) | f8.8
+| 4-5 | XX YY | Outside temperature (raw; in 0.5 degree resolution) | f8.8
+| 6-7 | XX YY | RWT | f8.8
+| 8-9 | XX YY | Mid-way temperature heat pump - gas boiler | f8.8
+| 10-11 | XX YY | Refrigerant temperature | f8.8
+| 12-13 | XX YY | Actual room temperature | f8.8
+| 14-15 | XX YY | External outside temperature sensor (if connected); otherwise Outside temperature 2 derived from external unit sensor, but stabilized; does not change during defrosts; perhaps averaged over time | f8.8
+| 16-19 | 00 | ?
+
+## Packet type 12 - Time, date and status flags
+
+### Packet type 12: request
+
+Header: 000012
+
+| Byte(:bit) | Hex value observed | Description | Data type
+|:-----------|:------------------------------|:---------------------------------|:-
+| 0:1 | 0/1 | pulse at start each new hour | bit
+| 0:other| 0 | ? | bit
+| 1 | 00-06 | day of week (0=Monday, 6=Sunday) | u8
+| 2 | 00-17 | time - hours | u8
+| 3 | 00-3B | time - minutes | u8
+| 4 | 13-16 | date - year (16 = 2022) | u8
+| 5 | 01-0C | date - month | u8
+| 6 | 01-1F | date - day of month | u8
+| 7-11 | 00 | ? |
+| 12:6 | 0/1 | restart process indicator ? | bit
+| 12:5 | 0/1 | restart process indicator ? | bit
+| 12:0 | 0/1 | restart process indicator ? | bit
+| 12:other| 0 | ? | bit
+| 13:2 | 0/1 | once 0, then 1 | bit
+| 13:other| 0 | ? | bit
+| 14 | 00 | ? |
+
+Byte 12 has following pattern upon restart: 1x 00; 1x 01; then 41. A single value of 61 triggers an immediate heat pump restart.
+
+### Packet type 12: response
+
+Header: 400012
+
+| Byte(:bit) | Hex value observed | Description | Data type
+|:-----------|:-------------------|:----------------------|:-
+| 0 | 40 | ?
+| 1 | 40 | ?
+| 2-9 | 00 | ?
+| 10:4 | 0/1 | kWh preference input | bit
+| 10:other| 0 | | bit
+| 11 | 00/7F | once 00, then 7F | u8
+| 12 | | operating mode | flag8
+| 12:7 | 0/1 | DHW active2 | bit
+| 12:6 | 0/1 | gas? (depends on DHW on/off and heating on/off) | bit
+| 12:0 | 0/1 | heat pump? | bit
+| 12:other| 0 | ? | bit
+| 13:2 | 1 | ? | bit
+| 13:other| 0 | ? | bit
+| 14-19 | 00 | ?
+
+## Packet type 13 - software version, DHW target temperature and flow
+
+### Packet type 13: request
+
+Header: 000013
+
+| Byte(:bit) | Hex value observed | Description | Data type
+|:-----------|:-------------------|:-----------------------------------|:-
+| 0-1 | 00 | ?
+| 2:4 | 0/1 | ? | bit
+| 2:5,3-0 | 0 | ? | bit
+| 2:7-6 | 00/01/10/11 | modus ABS / WD / ABS+prog / WD+dev | bit2
+
+### Packet type 13: response
+
+Header: 400013
+
+| Byte(:bit) | Hex value observed | Description | Data type
+|:-----------|:-------------------|:----------------------------|:-
+| 0 | 3C | DHW target temperature (one packet delayed/from/via boiler?/ 0 in first packet after restart) | u8 / f8.8 ?
+| 1 | 00 | +fractional part?
+| 2 | 01 | ?
+| 3 | 40/D0 | ?
+| 3:5-0 | 0 | ? | bit
+| 3:7-6 | 00/01/10/11 | modus ABS / WD / ABS+prog / WD+dev | bit2
+| 4-7 | 00 | ?
+| 8-9 | **FFFC/FFFD/**0000-010E | flow (in 0.1 l/min) (EHV/EHYHB only. Zero on EJHA) | **s16div10 (negative if pump stops, probably bad calibration)**
+| 10-11 | xxxx | software version inner unit | u16
+| 12-13 | xxxx | software version outer unit | u16
+|EHV only: 14| 00 | ? | u8
+|EHV only: 15| 00 | ? | u8
+
+The DHW target temperature is one packet delayed - perhaps this is due to communication with the Intergas gas boiler and confirms the actual gas boiler setting?
+
+## Packet type 14 - LWT target temperatures, temperature deviation, ..
+
+### Packet type 14: request
+
+Header: 000014
+
+| Byte(:bit) | Hex value observed | Description | Data type
+|:-----------|:-------------------|:---------------------------------|:-
+| 0-1 | 27 00 | LWT setpoint Heating Main zone | f8.8 or f8/8?
+| 2-3 | 12 00 | LWT setpoint Cooling Main zone | f8.8 or f8/8?
+| 4-5 | 27 00 | LWT setpoint Heating Add zone | f8.8 or f8/8?
+| 6-7 | 12 00 | LWT setpoint Cooling Add zone | f8.8 or f8/8?
+| 8 | 00-0A,10-1A | LWT deviation Heating Main zone | s-abs4
+| 9 | 00-0A,10-1A | LWT deviation Cooling Main zone | s-abs4
+| 10 | 00-0A,10-1A | LWT deviation Heating Add zone | s-abs4
+| 11 | 00-0A,10-1A | LWT deviation Cooling Add zone | s-abs4
+| 12 | 00/37 | first package 37 instead of 00 | u8
+| 13-14 | 00 | ?
+
+### Packet type 14: response
+
+Header: 400014
+
+| Byte(:bit) | Hex value observed | Description | Data type
+|:-----------|:-------------------|:--------------------------|:-
+| 0-14 | XX | echo of 000014-{00-14} |
+| 15-16 | 1C-24 00-09 | Target LWT Main zone in 0.1 degree (based on outside temperature in 0.5 degree resolution)| f8/8?
+| 17-18 | 1C-24 00-09 | Target LWT Add zone in 0.1 degree (based on outside temperature in 0.5 degree resolution)| f8/8?
+
+## Packet type 15 - temperatures, operating mode
+
+### Packet type 15: request
-#### Data type 0x01
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | --------------------------- | --------- | ---------------- |
-| 0 | Data type 0x01 | u8 | |
-| 1-3 | energy produced for heating | u24 | |
-| 4-6 | energy produced for cooling | u24 | |
-| 7-9 | energy produced for DHW | u24 | |
-| 10-12 | energy produced total | u24 | |
-
-#### Data type 0x02
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | ---------------------------------- | --------- | ---------------- |
-| 0 | Data type 0x02 | u8 | |
-| 1-3 | number of pump hours | u24 | |
-| 4-6 | number of compressor hours heating | u24 | |
-| 7-9 | number of compressor hours cooling | u24 | |
-| 10-12 | number of compressor hours DHW | u24 | |
-
-#### Data type 0x03
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | -------------------------------- | --------- | ---------------- |
-| 0 | Data type 0x03 | u8 | |
-| 1-3 | backup heater1 hours for heating | u24 | |
-| 4-6 | backup heater1 hours for DHW | u24 | |
-| 7-9 | backup heater2 hours for heating | u24 | |
-| 10-12 | backup heater2 hours for DHW | u24 | |
-| 13-15 | ? | u24 | |
-| 16-18 | ? | u24 | |
-
-#### Data type 0x04
-
-| Data byte | Description | Data type | Bit: description |
-| --------- | --------------------------- | --------- | ---------------- |
-| 0 | Data type 0x04 | u8 | |
-| 1-3 | ? | u24 | |
-| 4-6 | ? | u24 | |
-| 7-9 | ? | u24 | |
-| 10-12 | number of compressor starts | u24 | |
+Header: 000015
-#### Data type 0x05
+| Byte(:bit) | Hex value observed | Description | Data type
+|:-----------|:----------------------|:--------------------------------|:-
+| 0 | 00 | ?
+| 1-2 | 01/09/0A/0B 54/F4/C4/D6/F0 | schedule-induced operating mode? | flag8,flag8?
+| 3 | 00 | ?
+| 4 | 03 | ?
+| 5 | 20/52 | ?
-| Data byte | Description | Data type | Bit: description |
-| --------- | -------------------------------------- | --------- | ---------------- |
-| 0 | Data type 0x05 | u8 | |
-| 1-3 | number of gas boiler hours for heating | u24 | |
-| 4-6 | number of gas boiler hours for DHW | u24 | |
-| 7-9 | ? | u24 | |
-| 10-12 | ? | u24 | |
-| 13-15 | number of gas boiler hours total | u24 | |
-| 16-18 | ? | u24 | |
+### Packet type 15: response
+Header: 400015
+
+| Byte(:bit) | Hex value observed | Description | Data type
+|:-----------|:----------------------|:----------------------------------|:-
+| 0-1 | 00 | Refrigerant temperature? | f8.8?
+| 2-3 | FD-FF,00-08 00/80 | Refrigerant temperature (in 0.5C) | f8.8
+| 4-5 | 00 | Refrigerant temperature? | f8.8?
+|EHV only: 6 | 00-19 | parameter number | u8/u16
+|EHV only: 7 | 00 | (part of parameter or value?) |
+|EHV only: 8 | XX | ? | s16div10_LE?
+
+EHV is the only model for which we have seen use of the mechanism in the basic packet types.
+The following parameters have been observed in this packet type on EHV model only:
+
+| Parameter number | Parameter Value | Description
+|:-----------------|:------------------------------|:-
+|EHV: 05 | 96 | 15.0 degree?
+|EHV: 08 | 73,78,7D | 11.5, 12.0, 12.5 ?
+|EHV: 0A | C3,C8 | 19.5, 20.0
+|EHV: 0C | 6E,73,78 | 11.0, 11.5, 12.0
+|EHV: 0E | B9,BE | 18.5, 19.0
+|EHV: 0F | 68,6B | 10.4, 10.7
+|EHV: 10 | 05 | 0.5
+|EHV: 19 | 01 | 0.1
+|EHV: others | 00 | ?
+
+These parameters are likely s16div10.
+
+## Packet type 16 - temperatures
+
+Only observed on EHV\* and EJHA\* heat pumps.
+
+### Packet type 16: request
+
+Header: 000016
+
+| Byte(:bit) | Hex value observed | Description | Data type
+|:-----------|:-------------------|:------------------|:-
+| 0-1 | 00 | ?
+| 2-3 | 32 14 | room temperature? | f8.8?
+| 4-15 | 00 | ?
+
+### Packet type 16: response
+
+Header: 400016
+
+| Byte(:bit) | Hex value observed | Description | Data type
+|:-----------|:-------------------|:---------------------------------|:-
+| 0 | | **Current in 0.1 A** | u8div10
+| 1 | | **Power input in 0.1 kW** | u8div10
+| 0-7 | 00 | ? |
+| 6 | | **Heating/cooling output in 0.1 kW** | u8div10
+| 7 | | **DHW output in 0.1 kW** | u8div10
+| 8 | E6 | ? |
+
+# Packet types A1 and B1 communicate text data
+
+## Packet type A1
+
+Used for name of product?
+
+### Packet type A1: request
+
+Header: 0000A1
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:----------------------|:-
+| 0 | 00 | ?
+| 1-15 | 30 | ASCII '0' | c8
+| 16-17 | 00 | ASCII '\0' | c8
+
+### Packet type A1: response
+
+Header: 4000A1
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:----------------------|:-
+| 0 | 00 | ?
+| 1-15 | 00 | ASCII '\0' (missing) name outside unit | c8
+| 16-17 | 00 | ASCII '\0' | c8
+
+## Packet type B1 - heat pump name
+
+Product name.
+
+### Packet type B1: request
+
+Header: 0000B1
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:----------------------|:-
+| 0 | 00 | ?
+| 1-15 | 30 | ASCII '0' | c8
+| 16-17 | 00 | ASCII '\0' | c8
+
+### Packet type B1: response
+
+Header: 4000B1
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:----------------------|:-
+| 0 | 00 | ?
+| 1-12 | XX | ASCII "EHYHBH08AAV3" name inside unit | c8
+| 13-17 | 00 | ASCII '\0' | c8
+
+# Packet type B8 - counters, #hours, #starts, electricity used, energy produced
+
+Counters for energy consumed and operating hours. The main controller specifies which data type it would like to receive. The heat pump responds with the requested data type counters. A B8 package is only transmitted by the main controller after a manual menu request for these counters. P1P2Monitor can insert B8 requests to poll these counters, but this violates the rule that an auxiliary controller should not act as main controller. But if timed carefully, it works.
+
+### Packet type B8: request
+
+Header: 0000B8
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:----------------------|:-
+| 0 | XX | data type requested
00: energy consumed
01: energy produced
02: pump and compressor hours
03: backup heater hours
04: compressor starts
05: boiler hours and starts | u8
+
+### Packet type B8: response
+
+Header: 4000B8
+
+#### Data type 00
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:--------------------------------------|:-
+| 0 | 00 | data type 00 : energy consumed (kWh) | u8
+| 1-3 | XX XX XX | by backup heater for heating | u24
+| 4-6 | XX XX XX | by backup heater for DHW | u24
+| 7-9 | 00 XX XX | by compressor for heating | u24
+| 10-12 | XX XX XX | by compressor for cooling | u24
+| 13-15 | XX XX XX | by compressor for DHW | u24
+| 16-18 | XX XX XX | total | u24
+
+#### Data type 01
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:-------------------------------------|:-
+| 0 | 01 | data type 01 : energy produced (kWh) | u8
+| 1-3 | XX XX XX | for heating | u24
+| 4-6 | XX XX XX | for cooling | u24
+| 7-9 | XX XX XX | for DHW | u24
+| 10-12 | XX XX XX | total | u24
+
+On EJHA\* all counters for type 01 are always zero.
+
+#### Data type 02
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:-------------------------------|:-
+| 0 | 02 | data type 02 : operating hours | u8
+| 1-3 | XX XX XX | pump hours | u24
+| 4-6 | XX XX XX | compressor for heating | u24
+| 7-9 | XX XX XX | compressor for cooling | u24
+| 10-12 | XX XX XX | compressor for DHW | u24
+
+#### Data type 03
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:-------------------------------|:-
+| 0 | 03 | data type 03 : operating hours | u8
+| 1-3 | XX XX XX | backup heater1 for heating | u24
+| 4-6 | XX XX XX | backup heater1 for DHW | u24
+| 7-9 | XX XX XX | backup heater2 for heating | u24
+| 10-12 | XX XX XX | backup heater2 for DHW | u24
+| 13-15 | XX XX XX | ? | u24
+| 17-18 | XX XX XX | ? | u24
+
+#### Data type 04
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:----------------------------|:-
+| 0 | 04 | data type 04 | u8
+| 1-3 | XX XX XX | ? | u24
+| 4-6 | XX XX XX | ? | u24
+| 7-9 | XX XX XX | ? | u24
+| 10-12 | XX XX XX | number of compressor starts | u24
+
+#### Data type 05
+
+| Byte nr | Hex value observed | Description | Data type
+|:--------------|:------------------------------|:------------------------------------------|:-
+| 0 | 05 | data type 05 : gas boiler in hybrid model | u8
+| 1-3 | XX XX XX | boiler operating hours for heating | u24
+| 4-6 | XX XX XX | boiler operating hours for DHW | u24
+| 7-9 | XX XX XX | gas usage for heating (unit tbd) | u24
+| 10-12 | XX XX XX | gas usage for heating (unit tbd) | u24
+| 13-15 | XX XX XX | number of boiler starts | u24
+| 16-18 | XX XX XX | gas usage total (unit tbd) | u24
+
+Internal gas metering seems only supported on newer models, not on the AAV3.
diff --git a/README.md b/README.md
index 95e6c9b..02306a7 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,30 @@
# Arduino Altherma UDP Controller
-## What is it good for?
+* [What is it good for?](#what-is-it-good-for)
+* [Technical specifications](#technical-specifications)
+* [Hardware](#hardware)
+* [Firmware](#firmware)
+* [Settings](#settings)
+ - [System Info](#system-info)
+ - [P1P2 Status](#p1p2-status)
+ - [IP Settings](#ip-settings)
+ - [TCP/UDP Settings](#tcpudp-settings)
+ - [P1P2 Settings](#p1p2-settings)
+ - [Packet Filter](#packet-filter)
+* [Integration](#integration)
+ - [Loxone](#loxone)
+ - [Other systems](#other-systems)
+* [Limitations and known issues](#limitations-and-known-issues)
+* [Comparison with other solutions](#comparison-with-other-solutions)
+* [Version history](#version-history)
+
+# What is it good for?
Allows you to connect your Daikin Altherma heat pump (P1/P2 bus) to a home automation system (such as Loxone). This controller reads data from the P1/P2 bus on your Daikin Altherma and forwards them via ethernet UDP. You can also control your Daikin Altherma by sending commands via ethernet UDP.
-The controller itself can be configured through built-in web interface, which alsoallows you to monitor the P1/P2 connection and count errors. All settings and P1/P2 statistics are stored in EEPROM. This program implements P1P2Serial library (https://github.com/Arnold-n/P1P2Serial).
+The controller has a built-in web interface. You can use this web interface to configure the controller itself, monitor the status of the controller's connection to the P1/P2 bus and check error counters. All settings and P1/P2 statistics are stored in EEPROM. This program implements P1P2Serial library (https://github.com/Arnold-n/P1P2Serial).
-
-
-
-## What are the technical specifications?
+# Technical specifications
* this controller is compatible with Daikin Altherma heat pumps (E-series), including:
- Altherma Hybrid
@@ -39,9 +54,9 @@ The controller itself can be configured through built-in web interface, which al
# Hardware
Get the hardware and connect together:
-* **Arduino Uno or Mega**.
+* **Arduino Uno**.
-* **Ethernet shield (with W5100, W5200 or W5500 chip)**. The ubiquitous W5100 shield for Uno/Mega is sufficient. !!! ENC28J60 will not work !!!
+* **Ethernet shield (with W5100, W5200 or W5500 chip)**. The ubiquitous W5100 shield for Uno is sufficient. !!! ENC28J60 will not work !!!
* **Custom P1P2 Uno adapter**. You can [solder your own adapter](https://github.com/Arnold-n/P1P2Serial/tree/main/circuits#p1p2-adapter-as-arduino-uno-hat) or buy one from Arnold-n (his e-mail address can be found on line 3 of his library [P1P2Serial.cpp](https://github.com/Arnold-n/P1P2Serial/blob/main/P1P2Serial.cpp)).
Here is my HW setup (cheap Arduino Uno clone + W5500 Ethernet shield from Keyestudio + custom P1P2 Uno adapter):
@@ -85,13 +100,13 @@ This controller has a built-in webserver which allows you to configure the contr
* **Connecting...** The controller is in the process of connecting to the P1/P2 bus (to the main Daikin controller).
* **Connected**. The controller is connected to the P1/P2 bus (to the main Daikin controller). Once connected, the controller can also:
- show Altherma model in **Daikin Unit**
- - periodically request, read (and send via UDP) some additional data (counters)
+ - periodically request, read (and send via UDP) Altherma counters
- control Altherma by sending **Write Packet** through the web interface
- control Altherma by sending commands via UDP
* **Not Supported by the Pump**. The controller failed to connect to the P1/P2 bus (to the main Daikin controller) because it is not supported by the heat pump. The controller will not reconnect even if it is in the Auto Connect mode (see P1P2 Settings) but the user can still try to (re)connect manually. The **Not Supported by the Pump** status occurs when:
- - the heat pump (the main Daikin controller) does not support external controllers
- - one external controller (for example Daikin LAN controller) is already connected to the P1/P2 bus and the heat pump does not support second external controller
- - two external controllers are already connected
+ - The heat pump (the main Daikin controller) does not support external controllers.
+ - One external controller (for example Daikin LAN controller) is already connected to the P1/P2 bus and the heat pump does not support second external controller. The number of supported external controllers depends on the model of the Daikin unit.
+ - Two external controllers are already connected. This Arduino controller can not connect to the P1/P2 bus if there are already 2 or more external controllers (regardless of whether the Daikin unit supports more external controllers or not).
**Daikin Unit**. Shows the name of your Altherma indoor unit.
@@ -200,7 +215,7 @@ Optionally, set the **Remote IP** (= Loxone Miniserver IP) and enable **Only to/
### 3. Virtual UDP Input
-Download the Loxone template **[VIU_Daikin Altherma.xml](VIU_Daikin Altherma.xml)**. Open Loxone Config and in the periphery tree mark `Virtual Inputs`, then go to UDP Device Templates > Import Template ... in the menu bar:
+Download the Loxone template **[VIU_Daikin Altherma.xml](https://github.com/budulinek/arduino-altherma-controller/blob/main/VIU_Daikin%20Altherma.xml)**. Open Loxone Config and in the periphery tree mark `Virtual Inputs`, then go to UDP Device Templates > Import Template ... in the menu bar:
@@ -208,25 +223,28 @@ Find the template you have downloaded and import the template. You should see Da
-Just drag and drop individual inputs into your Loxone plan and you are ready to go. The only challenge are compound inputs containing multiple digital inputs in one byte. Names of these compound inputs end with `_B`. You need to connect these compound inputs to a `Binary Decoder` block and decode individual digital inputs according to the provided hint. Here is an example of `Valves_B` compound input:
+Just drag and drop individual inputs into your Loxone plan and you are ready to go. There are only two challenges:
+* LWT deviations `Deviation_LWT__` are split into two inputs carrying positive values `_Pos` and negative values `_Neg`.
+* There are compound inputs containing multiple digital inputs in one byte. Names of these compound inputs end with `_B`. You need to connect these compound inputs to a `Binary Decoder` block and decode individual digital inputs according to the provided hint. Here is an example of `Valves_B` compound input:
+
### 4. Virtual Output
Virtual Output will only work if the Arduino controller is connected to the P1/P2 bus (can write to the bus). Moreover, writeable command are device-specific. The Virtual Output Commands provided in the template may (with no guarantee) work only with **Daikin Altherma LT (EHVH(H/X/Z))** heat pumps. **Use at your own risk!!!**
-Download the Loxone template **[VO_Daikin Altherma LT.xml](VO_Daikin Altherma LT.xml)**. Open Loxone Config and in the periphery tree mark `Virtual Outputs`, then go to Device Templates > Import Template ... in the menu bar. Find the template you have downloaded and import the template. You should see Daikin Altherma LT with a number of `Virtual Output Commands`. Change the IP address or UDP port if needed:
+Download the Loxone template **[VO_Daikin Altherma LT.xml](https://github.com/budulinek/arduino-altherma-controller/blob/main/VO_Daikin%20Altherma%20LT.xml)**. Open Loxone Config and in the periphery tree mark `Virtual Outputs`, then go to Device Templates > Import Template ... in the menu bar. Find the template you have downloaded and import the template. You should see Daikin Altherma LT with a number of `Virtual Output Commands`. Change the IP address or UDP port if needed:
There are 3 types of outputs available:
-* Analog outputs for target temperatures, setpoints etc. As expected, these inputs accept temperature in °C (float).
+* Analog outputs for target temperatures, setpoints etc. As expected, these outputs accept temperature in °C (float).
* Digital outputs have `_OnOff` in their name. As expected: 0 = Off, 1 = On.
-* Discreet analog outputs for various operational modes. Always check the provided hints. Here is an example of Heating/Cooling operational mode:
+* Discreet analog outputs for various operational modes. These outputs accept discreet integer values - see the provided hints. Here is an example of Heating/Cooling operational mode:
-If you want to control your heat pump through Loxone App (just like I did in the short video above) or Loxone Web Interface, use the `EIB push-button` block. It has the same functionality as a normal push-button but in addition has the State (S) input which can forward the status of a heat pump actuator without triggering an action on the output. As a result, you can have a smooth two-directional communication between the main Daikin controller and the Loxone App. Here you have a solution for the DHW On/Off push-button and the DHW Boost push button. Please note that the DHW_OnOff_B input is a compound input which needs to be decoded with `Binary Decoder`:
+If you want to control your heat pump through Loxone App (just like I did in the short video above) or Loxone Web Interface, use the `EIB push-button` block. It has the same functionality as a normal push-button but in addition has the State (S) input which can forward the status of a heat pump settings without triggering an action on the output. As a result, you can have a smooth two-directional communication between the main Daikin controller and the Loxone App. Here you have a solution for the DHW On/Off push-button and the DHW Boost push button. Please note that the DHW_OnOff_B input is a compound input which needs to be decoded with `Binary Decoder`:
### 5. Digital Outputs (Relays)
@@ -234,7 +252,7 @@ By default, the main Daikin controller (the user interface mounted at the indoor
Fortunately, 1) Daikin Altherma allows you to connect an external thermostat and 2) Loxone Miniserver can act as an external thermostat.
-**Wiring**. External thermostat is an external 230V relay operated by a temperature sensor (+ some scheduling logic). It controls the heat pump by opening and closing a **230V circuit!** **Danger of death!** Always unplug your heat pump from the mains before connecting wires and consult your heat pump's Installation manual in order to locate the correct wiring terminal. **Proceed at your own risk!** If you know what you are doing, connect the correct wiring terminal of your heat pump (on my Altherma I have used the X2M wiring terminal) to Loxone Miniserver relays. You can use separate relays for heating and cooling and separate relays for main LWT zone and additional LWT zone. Therefore, depending on the complexity of your heating/cooling system, up to 4 external relays can be used.
+**Wiring**. External thermostat is an external 230V relay operated by a temperature sensor (+ some scheduling logic). It controls the heat pump by opening and closing a **230V circuit!** **Danger of death!** Always unplug your heat pump from the mains before connecting wires and consult your heat pump's Installation manual in order to locate the correct wiring terminal. **Proceed at your own risk!** If you know what you are doing, connect the correct wiring terminal of your heat pump (on my Altherma I have used the X2M wiring terminal) to Loxone Miniserver relays. You can use separate relays for heating and cooling and separate relays for main LWT zone and additional LWT zone. Therefore, up to 4 external relays can be used depending on the complexity of your heating/cooling system.
**Heat Pump Configuration**. Enable external thermostat on your heat pump. Consult your installation manual. In my case I have the settings here: `Installer settings > System layout > Standard > [A.2.1.7] Unit control method > Ext RT control`. If you want to use separate relays for heating and cooling, check also `Installer settings > System layout > Options > [A.2.2.4] Contact type main > H/C request`.
@@ -242,24 +260,55 @@ Fortunately, 1) Daikin Altherma allows you to connect an external thermostat and
-It is quite simple. I have a `HVAC Controller` block which serves as a heating and cooling source for 7 `Intelligent Room Controllers` (see the "7 Objects Assigned" note at the bottom of the HVAC block). The HVAC block needs to know the outdoor temperature, so I have connected the `Temperature_Outside_Stabilized` measured by the heat pump. I have wired 3 digital outputs (relays) to the wiring terminal of the heat pump, even though I only use 2 of them. Relay `Ext_Therm_Main_Heating` triggers heating on the main LWT zone (floor heating), relay `Ext_Therm_Add_Cooling` triggers cooling on the additional LWT zone (ceiling cooling panels). I do not use my floor for cooling.
+It is quite simple. I have a `HVAC Controller` block which serves as a heating and cooling source for 7 `Intelligent Room Controllers` (see the "7 Objects Assigned" note at the bottom of the HVAC block). The HVAC block needs to know the outdoor temperature, so I have connected the `Temperature_Outside_Stabilized` measured by the heat pump. Relay `Ext_Therm_Main_Heating` triggers heating on the main LWT zone (underfloor heating), relay `Ext_Therm_Add_Cooling` triggers cooling on the additional LWT zone (ceiling cooling panels). `Ext_Therm_Main_Cooling` is not connected because I do not use floor for cooling.
+
+### 6. Application Recommendations
+
+**Use relays for heating/cooling requests**. Your Loxone automation system can now control the Altherma heat pump through 2 sets of outputs: Virtual Output Commands (UDP) and Digital Outputs (Relays). Each of them is doing a different thing, the two do not replace but complement each other:
+* **Virtual Output Commands** are sent (via UDP) to the Arduino controller and then (via P1/P2 bus) to the main Daikin controller at your indoor unit. These commands allow you to remotely change user settings (Quiet Mode, Schedules), target temperatures (DHW, LWT), turn the DHW on/off, etc. **Whenever you use Virtual Output Commands (UDP), new settings are stored in the main Daikin controller, wearing its EEPROM!** Use these outputs sparingly. For example, the `LWT_Control_OnOff` command completely shuts down heating (though DHW still works). Valves are closed and the heat pump ignores any heating/cooling requests from the internal thermostat (main Daikin controller) or from the external thermostat (Loxone relays). Use this output only if you want to stop the heat pump for longer periods of time (such as holidays).
+* **Digital Outputs** allow you to send heating / cooling requests by closing Loxone Miniserver relays. These relays are connected directly to the heat pump's wiring terminals, not to the main Daikin controller. No new data (settings) are stored in the main Daikin controller's EEPROM. You do wear out your Loxone relay a bit, but relays are easier (and cheaper) to replace than the internal EEPROM of your Daikin controller. Use relays for automated heating / cooling requests, they are meant to be used this way. For example (and in contrast to the LWT_Control_OnOff command mentioned above), the `Ext_Therm_Main_Heating` output only sends a request for heating. When the relay is closed (DO = 1), the heat pump knows there is a demand for heating, and starts compressor in order to maintain the leaving water temperature at a certain level. When the relay is open (DO = 0), compressor stops, no heat is produced but the heat pump remains in a stand-by mode, waiting for new heating request.
+
+**Adjust the heating curve**. Daikin Altherma heat pumps have a built-in heating curve (weather-dependent curve, equithermic curve). Heating curve means that the leaving water temperature (LWT) depends on weather (outdoor temperature). Interestingly, Loxone also has a heating curve, integrated in the `Intelligent Temperature Controller` block. Here are your choices:
+
+* **Altherma heating curve**. Altherma heating curve (weather-dependent curve) can be enabled/disabled in installer settings. Consult your installation manual, in my case it is here: `Installer settings > Space operation > LWT settings > Main > [A.3.1.1.1] LWT setpoint mode`. By default, heating curve should be enabled (`Weather dep.`). Users can configure parameters of the heating curve (`User settings > Set weather dependent > Main > Set weather-dependent heating`). In this example, Altherma will use outdoor temperature to calculate the LWT, Loxone will only send heating requests through `Ext_Therm_Main_Heating` relay:
+
+
-**Application Notes**. I recommend using **both** the Arduino controller (Virtual UDP Outputs) and relays on the Loxone Miniserver (Digital Outputs) for controlling the heat pump. Each of them is doing a different thing, the two do not replace but complement each other. The **controller** (Virtual UDP Outputs) allows you to remotely change user settings (Quiet Mode, Schedules), turn the DHW on/off, change target temperatures (DHW, LWT), etc. Whenever you use the Virtual UDP Outputs, data are written to the main Daikin controller, wearing its EEPROM! So use sparingly. Loxone Miniserver as **external thermostat** (Digital Outputs - Relays) allows you to send heating or cooling requests. No data are written to the Daikin EEPROM, though you do wear out your Loxone relay a bit. Let's compare. The `LWT_Control_OnOff` (Virtual UDP Output) completely shuts down heating (though DHW still works). The valves are shut and the heat pump ignores any heating requests from the internal thermostat (main Daikin controller) or the external thermostat (Loxone relays). On the other side, the `Ext_Therm_Main_Heating` (Digital Output - Relay) only sends a request for heating. When the relay is closed (DO = 1), the heat pump knows there is a demand for heating, the circulation pump is running and the compressor maintains the leaving water temperature at a certain level. When the relay is open (DO = 0), no heat is produced but the heat pump is in a stand-by mode, waiting for a new heating request.
+* **Loxone heating curve**. Loxone heating curve is more advanced than Altherma heating curve, because Loxone uses more variables to calculate the LWT. Not just the outdoor temperature, but also the target room temperature, the difference between target and actual room temperatures, room heating phase / cooling phase. Moreover, Loxone can also adjust the target room temp (thus the requested LWT) based on schedule or presence of people. So, go ahead and completely disable your Altherma's heating curve (set the `LWT setpoint mode` to `Absolute`) and use the Loxone block `Intelligent Temperature Controller` (AQf - Flow Target Temperature) to calculate the LWT. Loxone will send heating requests through `Ext_Therm_Main_Heating` relay and requested leaving water temperature through `Target_Setpoint_LWT_Zone_Main` virtual UDP command. This is the most efficient way of controling your heat pump. The problem is that target LWT values calculated by Loxone change far too often (because outdoor temperature fluctuates throughout the day). Hysteresis setting in Arduino helps you reduce the frequency of LWT values sent to the heat pump, but the number of EEPROM writes will (probably) still exceed the limit (19 writes per day). You can give it a try but I do not recommend this choice.
+
-## Other Systems
+* **Altherma heating curve + adjustments by Loxone**. The `Intelligent Temperature Controller` block can also output AQi - Flow Temperature Increase/Decrease. This increase/decrease is caused by the room temperature difference (see parameter G - Gain) and the target room temperature increase during heating phase (see parameter I - Target temperature increase). In other words, AQi is Loxone's adjustment to the weather-dependent target LWT. We can sent it to the heat pump through the `Deviation_LWT_Zone_Main` virtual UDP command. This is a compromise solution. We will let Altherma calculate the weather-dependent LWT (from the outdoor temperature) and Loxone will calculate the LWT adjustment (from the difference between target and actual room temperature). Since AQi does not change that often, we will have less EEPROM writes. You can try this choice, but:
+ - Set the parameter I - Target temperature increase to zero. Daikin user manual explicitly discourages users from increasing/decreasing the desired room temperature to speed up space heating/cooling. Use only the parameter G - Gain.
+ - Check the number of Daikin EEPROM Writes in the Arduino controller web interface. Make sure that average writes per day (and yesterday writes) remain bellow the limit (19 writes per day).
+
-# Limitations and Known Issues
+## Other systems
+
+#### Home Assistant
+
+Arduino Altherma UDP controller is not suitable for Home Assistant. As far as I know, it is difficult to parse hex UDP messages in HA. Check the table bellow and use another solution (or Node-RED as an intermediary).
+
+#### Node-RED
+
+Import and configure the **[node-red-contrib-buffer-parser](https://flows.nodered.org/node/node-red-contrib-buffer-parser)** package. See [Payload-data-read.md](Payload-data-read.md) how to parse UDP messages (read data from the heat pump). See [Payload-data-write.md](Payload-data-write.md) how to make UDP commands (write to the heat pump).
+
+You can use Node RED as:
+* a rudimentary automation system on its own
+* an intermediary between the Arduino controller and other home automation system
+* an intermediary between the Arduino controller and a time series database and visualisation tool (InfluxDB + Grafana)
+
+# Limitations and known issues
## Portability
-The code was tested on Arduino Uno and Mega, ethernet chips W5100 and W5500. It may work on other platforms, but:
+The code was tested on Arduino Uno, ethernet chips W5100 and W5500. It may work on other platforms, but:
* The random number generator (for random MAC) is seeded through watch dog timer interrupt - this will work only on Arduino (credits to https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library/arduino-random-seed)
* The restart function will also work only on Arduino.
-## Remote IP Settings on the W5500 Chip
+## Remote IP settings on the W5500 Chip
The Ethernet.setRetransmissionCount() and Ethernet.setRetransmissionTimeout() commands do not work on W5500 chips because of a bug in the Ethernet.h library (see [this issue](https://github.com/arduino-libraries/Ethernet/issues/140)). As a result, Arduino fails to read data from the P1/P2 bus (read errors, CRC errors) if certain conditions are met:
* Ethernet shield with the W5500 chip is used.
@@ -268,7 +317,7 @@ The Ethernet.setRetransmissionCount() and Ethernet.setRetransmissionTimeout() co
In this situation (UDP unicast) the W5500 chip checks whether the remote IP exists via ARP request. While the Ethernet.h waits for the ARP response, new P1/P2 packet arrives and is not properly processed which leads to P1/P2 read errors. The solution is simple. If you have a shield with the W5500 chip, set the Send and Receive UDP setting to **To/From Any IP (Broadcast)**.
-## Ethernet Sockets
+## Ethernet sockets
The number of used sockets is determined (by the Ethernet.h library) based on microcontroller RAM. Therefore, even if you use W5500 (which has 8 sockets available) on Arduino Nano, only 4 sockets will be used due to limited RAM on Nano.
@@ -276,13 +325,13 @@ The number of used sockets is determined (by the Ethernet.h library) based on mi
Not everything could fit into the limited flash memory of Arduino Nano / Uno. If you have a microcontroller with more memory (such as Mega), you can enable extra settings in the main sketch by defining ENABLE_DHCP and/or ENABLE_EXTRA_DIAG in advanced settings.
-# What is the Difference from Other Solutions?
+# Comparison with other solutions
-Here is a brief comparison with other solutions (as of April 2023):
+As of April 2023:
| **Project** | **[budulinek/
arduino-altherma-controller](https://github.com/budulinek/arduino-altherma-controller)** | **[Arnold-n/
P1P2Serial](https://github.com/Arnold-n/P1P2Serial)** | **[raomin/
ESPAltherma](https://github.com/raomin/ESPAltherma)** | **[tadasdanielius/
daikin_altherma](https://github.com/tadasdanielius/daikin_altherma)** | **[speleolontra/
daikin_residential_altherma](https://github.com/speleolontra/daikin_residential_altherma)** ||
|------------------------------------|------------------------------------------------------------------------------------|----------------------------------------------------------|-------------------------------------------------------------------------------|------------------------------------------------------------------------------|------------------------------------------------------------------------------|-------------------------------------------|
-| **Hardware** | • Arduino Uno/Mega
• Ethernet Shield
• Custom P1P2 Uno adapter | • Custom all-in-one board | • M5StickC (or any ESP32/ESP8266 board)
• external relay (optional) | • Daikin LAN adapter
(BRP069A62/ BRP069A61
with OLD firmware) | • Daikin LAN adapter
(BRP069A62/ BRP069A61
with NEW firmware) | • Daikin WLAN adapter
(BRP069A78) |
+| **Hardware** | • Arduino Uno
• Ethernet Shield
• Custom P1P2 Uno adapter | • Custom all-in-one board | • M5StickC (or any ESP32/ESP8266 board)
• external relay (optional) | • Daikin LAN adapter
(BRP069A62/ BRP069A61
with OLD firmware) | • Daikin LAN adapter
(BRP069A62/ BRP069A61
with NEW firmware) | • Daikin WLAN adapter
(BRP069A78) |
| **Programable MCUs** | 1
ATmega328P | 2
ATmega328P + ESP8266 | 1
ESP32/8266 | --- | --- ||
| **Connection to Daikin Altherma** | P1/P2 bus | P1/P2 bus | X10A serial port | P1/P2 bus | P1/P2 bus | dedicated slot |
| **Interface** | • Ethernet | • WiFi
• Ethernet (optional) | • WiFi | • Ethernet | • Ethernet | • WiFi |
@@ -298,3 +347,6 @@ Here is a brief comparison with other solutions (as of April 2023):
## Version history
For version history see:
+
+https://github.com/budulinek/arduino-altherma-controller/blob/main/arduino-altherma-controller/arduino-altherma-controller.ino#L3
+
diff --git a/arduino-altherma-controller/advanced_settings.h b/arduino-altherma-controller/advanced_settings.h
index 270f2f2..4f7a6fc 100644
--- a/arduino-altherma-controller/advanced_settings.h
+++ b/arduino-altherma-controller/advanced_settings.h
@@ -46,7 +46,7 @@ const unsigned int WEB_IDLE_TIMEOUT = 400; // Time (ms) from last client d
const unsigned int TCP_DISCON_TIMEOUT = 500; // Timeout (ms) for client DISCON socket command, non-blocking alternative to https://www.arduino.cc/reference/en/libraries/ethernet/client.setconnectiontimeout/
//const unsigned int TCP_RETRANSMISSION_TIMEOUT = 50; // Ethernet controller’s timeout (ms), blocking (see https://www.arduino.cc/reference/en/libraries/ethernet/ethernet.setretransmissiontimeout/)
//const byte TCP_RETRANSMISSION_COUNT = 3; // Number of transmission attempts the Ethernet controller will make before giving up (see https://www.arduino.cc/reference/en/libraries/ethernet/ethernet.setretransmissioncount/)
-const unsigned int TCP_RETRANSMISSION_TIMEOUT = 10; // Ethernet controller’s timeout (ms), blocking (see https://www.arduino.cc/reference/en/libraries/ethernet/ethernet.setretransmissiontimeout/)
+const unsigned int TCP_RETRANSMISSION_TIMEOUT = 50; // Ethernet controller’s timeout (ms), blocking (see https://www.arduino.cc/reference/en/libraries/ethernet/ethernet.setretransmissiontimeout/)
const byte TCP_RETRANSMISSION_COUNT = 3; // Number of transmission attempts the Ethernet controller will make before giving up (see https://www.arduino.cc/reference/en/libraries/ethernet/ethernet.setretransmissioncount/)
const int FETCH_INTERVAL = 2000; // Fetch API interval (ms) for the Modbus Status webpage to renew data from JSON served by Arduino
diff --git a/arduino-altherma-controller/arduino-altherma-controller.ino b/arduino-altherma-controller/arduino-altherma-controller.ino
index 92206d1..14cc0f9 100644
--- a/arduino-altherma-controller/arduino-altherma-controller.ino
+++ b/arduino-altherma-controller/arduino-altherma-controller.ino
@@ -1,21 +1,11 @@
-/* Altherma UDP Controller: Monitors and controls Daikin E-Series (Altherma) through P1/P2 bus.
+/* Altherma UDP Controller: Monitors and controls Daikin E-Series (Altherma) het pumps through P1/P2 bus.
Version history
v0.1 2020-11-30 Initial commit, save history of selected packets, settings
v0.2 2020-12-05 Hysteresis, vertify commands sent to P1P2
v0.3 2020-12-09 More effective and reliable writing to P1P2 bus
v0.4 2020-12-10 Minor tweaks
- v1.0 2023-XX-XX Major upgrade: web interface, store settings in EEPROM, P1P2 error counters
-
-changes:
-- only Daikin E* heat pumps (Altherma)
-- no SW_SCOPE
-- no error budget
-- no write budget (Write Cycles can are displayed via web UI)
-- use single queue for all write packets (0x3X, counter requests, daikin restart, etc.)
-- write all packets after 0x30 (disable #define KLICDA writing after 0x12 packet)
-- write any packets (incl. counter requests, restarts, etc.) only if connected as controller
-- if the main controller sends request to our auxiliary controller, always respond
+ v1.0 2023-04-18 Major upgrade: web interface, store settings in EEPROM, P1P2 error counters
*/
@@ -42,10 +32,6 @@ enum first_last : byte {
LAST
};
-
-
-/****** DEFAULT FACTORY SETTINGS ******/
-
enum status : byte {
PACKET_SEEN, // Packet Type was detected on P1P2 bus
PACKET_SENT, // Packet is sent via UDP
diff --git a/arduino-altherma-controller/src/P1P2Serial_mod/P1P2Serial_mod.cpp b/arduino-altherma-controller/src/P1P2Serial_mod/P1P2Serial_mod.cpp
index 39cf211..0deccf7 100644
--- a/arduino-altherma-controller/src/P1P2Serial_mod/P1P2Serial_mod.cpp
+++ b/arduino-altherma-controller/src/P1P2Serial_mod/P1P2Serial_mod.cpp
@@ -75,7 +75,7 @@
#ifdef __AVR_ATmega2560__
-#error ATmega2560 code has not been tested, use with caution.
+#warning ATmega2560 code has not been tested, use with caution.
// RW using timer5
#define INPUT_CAPTURE_PIN 48 // PL1
diff --git a/pics/loxone10.png b/pics/loxone10.png
new file mode 100644
index 0000000..e491fa5
Binary files /dev/null and b/pics/loxone10.png differ
diff --git a/pics/loxone8.png b/pics/loxone8.png
new file mode 100644
index 0000000..686c689
Binary files /dev/null and b/pics/loxone8.png differ
diff --git a/pics/loxone9.png b/pics/loxone9.png
new file mode 100644
index 0000000..f68cc21
Binary files /dev/null and b/pics/loxone9.png differ