Autoterm Heater Protocol

This protocol documentation was created through reverse engineering and may be incomplete or inaccurate.

Findings consolidated from the following community projects:

Autoterm heaters expose a simple binary request/response protocol over a 5V UART link. The display polls the heater periodically with a status request and a panel-temperature heartbeat, and sends control frames (start, stop, settings, ventilation) on demand.

ParameterValue
Signal level5V, 8N1, no flow control
Baud rate9600 or 19200 (model/firmware dependent)

To auto-detect the baud rate, send a Status Request at each candidate rate; the one that yields a parseable reply is the configured one.

Frame Format

All frames share the same envelope:

Example: AA 03 06 00 01 01 ... 05 CC CC
         │  │  │  │  │  └───────┘ └───┘
         │  │  │  │  │      │       │
         │  │  │  │  │      │       └── CRC-16/Modbus (big-endian)
         │  │  │  │  │      └────────── Payload (length = byte 2)
         │  │  │  │  └───────────────── Command ID
         │  │  │  └──────────────────── Reserved (always 0x00)
         │  │  └─────────────────────── Payload length
         │  └────────────────────────── Direction
         └───────────────────────────── Preamble (always 0xAA)
ByteFieldValues
0Preamble0xAA
1Direction0x03 = Display → Heater, 0x04 = Heater → Display
2Payload length (N)Bytes of payload (excludes header and CRC)
3ReservedAlways 0x00
4Command IDSee Commands
5 .. 4+NPayloadCommand-specific
5+N .. 6+NCRC-16/ModbusComputed over bytes 0 .. 4+N, high byte first

CRC-16/Modbus parameters: poly 0xA001, init 0xFFFF, no reflection of the result. The CRC is transmitted big-endian — the high byte goes on the wire first, which is the opposite of the on-bus byte order used by most Modbus implementations.

Responses

Every Display → Heater command receives a reply with direction = 0x04 and the same command ID echoed in byte 4. The reply payload follows one of three patterns: structured data (0x0F status, 0x02 read), a payload echo of the request (0x01, 0x02 write, 0x11, partially 0x23), or empty (0x03). See each command for the exact bytes.

Reply payload contents other than 0x0F status and 0x02 read are taken from community reverse-engineering captures and have not been independently verified.

Commands

IDNameDirReply payload
0x01StartD → H6-byte settings echo
0x02SettingsD → H6-byte settings (write: echo, read: current)
0x03StopD → Hempty
0x0FStatusboth19-byte status
0x11Panel Temperature / Heartbeatboth1-byte echo
0x23VentilationD → H4-byte partial echo

0x01 — Start

Starts a new heating cycle from standby. The 6-byte payload is shared with Settings (0x02); see that section for the field layout.

TX  AA 03 06 00 01 01 00 04 00 00 05 <CRC>      ; example: power mode, level 5
RX  AA 04 06 00 01 01 00 04 00 00 05 <CRC>      ; heater echoes the accepted settings

State then transitions StartingHeating on subsequent status polls.

0x02 — Settings

Two forms share command 0x02:

  • Write (6-byte payload) — update parameters of a running heater without restarting it.
  • Read (empty payload) — query the heater’s active configuration. The heater replies with a 6-byte payload using the same field layout.
AA 03 06 00 02 01 00 02 14 01 05 CC CC      ; write: useWT=1, src=panel, target=20°C, wait=on, level=5
AA 03 00 00 02 9D BD                        ; read request
AA 04 06 00 02 01 00 02 14 01 05 <CRC>      ; read reply (same layout)
Payload byteFieldNotes
0useWT0x01 disables the work-timer (heater runs indefinitely)
1Work timeMinutes of programmed run-time; only meaningful when useWT = 0x00
2Temperature sourceOperating mode — see Temperature source
3Target temperatureSetpoint in °C (unsigned). Ignored when tempSource = 0x04
4Wait mode0x00 = shut down at setpoint, 0x01 = idle-ventilate at setpoint and re-ignite on drop
5Power level0x010x09 (1 = lowest). Used directly in power mode, and as the start power in thermostatic modes

Polling the read form on startup recovers the active mode, setpoint, and power level after a controller restart; polling periodically detects settings changes made by another controller on the bus. OEM panels poll it every few seconds.

0x03 — Stop

Stops the heater. State transitions StoppingCoolingStandby over the next polls.

TX  AA 03 00 00 03 5D 7C
RX  AA 04 00 00 03 29 7D      ; empty-payload ack

No request payload; the reply also carries no payload.

0x0F — Status

Polls the heater for its current state and sensor readings.

Request (no payload):

AA 03 00 00 0F 58 7C

Response (19-byte payload):

AA 04 13 00 0F  03 00 00 0A 7F 00 84 01 B2 04 00 37 37 00 6D 00 6D 00 64  C3 0A
                │  │     │  │           └──┴── heat exchanger temp (K)
                │  │     │  └────────────────── external temp sensor
                │  │     └───────────────────── internal temp
                │  └─────────────────────────── state minor
                └────────────────────────────── state major
Payload byteFieldEncoding
0State majorSee Heater state
1State minorSee Heater state
2UnknownSeen 0x00
3Internal temperatureSigned 8-bit, °C
4External temperature sensorSigned 8-bit, °C. 0x7F = sensor disconnected
5UnknownSeen 0x00
6UnknownSeen 0x84
7–8Heat exchanger temperatureu16 big-endian, Kelvin (°C = value − 273)
9UnknownSeen 0x04
10UnknownSeen 0x00
11UnknownSeen 0x37
12UnknownSeen 0x37
13UnknownSeen 0x00
14Fan tachometerRPM ÷ 60 (revolutions per second)
15UnknownSeen 0x00
16Pump frequencyHz × 100 (value 0x6D = 1.09 Hz)
17UnknownSeen 0x00
18UnknownSeen 0x64

Decoding example

For the response frame above:

State:       major=0x03, minor=0x00 → Heating
Internal:    0x0A = 10 → 10°C
External:    0x7F → sensor disconnected
Heat exch.:  0x01B2 = 434 → 434 − 273 = 161°C
Fan:         0x6D = 109 → 109 × 60 = 6540 RPM
Pump:        0x6D = 109 → 109 × 0.01 = 1.09 Hz

0x11 — Panel Temperature / Heartbeat

Pushes the panel-side temperature to the heater and doubles as the mandatory heartbeat. The display must send this once per second regardless of the configured Temperature source; the heater flags “no panel” after roughly three seconds of silence. The heater echoes the same frame back as an acknowledgement.

AA 03 01 00 11 1A 76 D0      ; request: panel temp = 26°C
AA 04 01 00 11 1A B6 65      ; echo
ByteFieldEncoding
5Panel temperatureSigned 8-bit, °C. 0x7F signals “no panel sensor”

When tempSource = 0x02 (panel), the byte is the value the heater regulates against. In all other modes the byte is still required but informational — 0x7F is the conventional choice and what OEM panels send when no panel sensor is fitted.

0x23 — Ventilation

Runs the fan only, without ignition.

TX  AA 03 04 00 23 FF FF 08 FF E1 0B      ; ventilation level 8
RX  AA 04 04 00 23 FF FF 08 43 B6 4B      ; bytes 0–2 mirror the request, byte 3 differs
Payload byteFieldValues
0UnknownAlways 0xFF in the request
1UnknownAlways 0xFF in the request
2Ventilation level0x000x09
3Unknown0xFF in the request; the heater replies with a different value (purpose unknown)

Field Reference

Temperature source

ValueModeBehaviour
0x01Internal sensor thermostaticRegulates against the heater’s intake-air sensor. Inaccurate because that probe sits in the heater’s cabin air inlet, not the living space
0x02Panel sensor thermostaticRegulates against the temperature the display pushes via 0x11
0x03External sensor thermostaticRegulates against a separate probe plugged directly into the heater harness
0x04Power modeNo thermostat — heater runs at a fixed power level (1 – 9). Bytes 3 and 4 of the Settings payload are ignored

Heater state

Encoded as a (major, minor) pair in the Status response. The major byte identifies the overall phase; the minor byte gives a sub-step.

MajorMinorStateDescription
0x000x01StandbyIdle, waiting for commands
0x010x00CoolingPost-shutdown cool-down (fan running, no flame)
0x010x01VentilationFan-only mode (after ventilation command)
0x02anyStartingIgnition sequence in progress
0x03anyHeatingStable heating
0x040x00StoppingShutdown sequence in progress

Timing

ParameterValue
Poll interval (status + heartbeat)1 s
Heater silence tolerance before “no panel” fault~3 s
Response timeout600 ms
Consecutive missed responses tolerated before link is considered down2

Operating Procedures

Startup — recover heater state

After the controller connects (or reconnects) it does not know whether the heater is in standby, mid-burn, or shutting down. To sync up:

  1. Send 0x11 — establishes the link and proves the baud rate.
  2. Send 0x0F — reveals the current operating state.
  3. Send 0x02 read — reveals the active mode, setpoint, and power level.

From there the controller enters the periodic-poll cadence below.

Periodic poll

Every second:

  1. Display → Heater: 0x11 with current panel temperature (or 0x7F if no panel sensor)
  2. Heater → Display: heartbeat echo
  3. Display → Heater: 0x0F
  4. Heater → Display: Status response

The 0x02 read can be re-issued every few seconds to pick up settings changes made by other controllers on the bus.

Start heating at power level 5

  1. Display → Heater: 0x01 with payload 01 00 04 00 00 05
  2. Heater → Display: 0x01 reply echoing the 6-byte settings payload
  3. Subsequent polls show state transitioning StartingHeating.

Change power level while running

  1. Display → Heater: 0x02 write with new power level in payload byte 5
  2. Heater → Display: 0x02 reply echoing the 6-byte settings payload

Stop

  1. Display → Heater: 0x03
  2. Heater → Display: 0x03 reply with empty payload
  3. State transitions StoppingCoolingStandby over the next polls.