Skip to content

System Setup Discovery Protocol

John Lifsey edited this page Apr 7, 2026 · 1 revision

Overview

When the thermostat enters System Setup mode (triggered by the user at the thermostat), it temporarily switches its bus address from 0x20 to 0x1F ("SystemInit") and drives a multi-phase discovery and commissioning sequence across the RS-485 bus.

The physical layer is the standard ABCD bus: RS-485 half-duplex at 38400,8,N,1. See Infinity Protocol Hardware and Infinity Framing Protocol for background.


Device Address Map

Hex Addr Device Present Notes
0x1F SystemInit Active during setup Thermostat assumes this address during commissioning
0x20 Thermostat Active Resumes after SystemInit phase
0x210x28 Thermostat1–8 Scanned, no reply Additional thermostat / Smart Sensor slots
0x40 IndoorUnit Active Furnace / Air Handler
0x41 IndoorUnit1 Scanned, no reply Probed by IndoorUnit itself
0x42 IndoorUnit2 Scanned, no reply Probed by SystemInit — "select indoor evaporator"
0x50 OutdoorUnit Scanned, no reply Outdoor slot 0
0x51 OutdoorUnit1 Scanned, no reply
0x52 OutdoorUnit2 Active Heat pump in this system
0x54 OutdoorUnit4 Scanned, no reply
0x600x61 ZoneControl Scanned, no reply
0x80 NIM Scanned, no reply
0x0E Device 14 Scanned, no reply Unknown class — receives 10 attempts per register (vs 2 for others)
0x92 SAM Active See SAM ASCII Protocol

See Infinity - known devices for the full address scheme with community-verified models.


Frame Structure

All frames use the standard CarBus format documented in Infinity Framing Protocol:

[DST] [DST_ID] [SRC] [SRC_ID] [LEN] [00 00] [FUNC] [PAYLOAD...] [CRC16]
  1B     1B      1B     1B      1B     2B      1B      LEN-3B       2B

Function codes observed during setup

Hex Name Description
0x0b READ Request to read a register
0x06 REPLY Response with register data (also used as write-ACK)
0x0c WRITE Write data to a register
0x15 EXCEPTION Error/NAK — payload 0x04 means "no such register" or device not responding

Example: Thermostat reads register 0x0104 from IndoorUnit

Request:  40 01 20 01 03 00 00 0b 00 01 04 6d 7e
          dst=0x40  src=0x20  len=3  func=READ  reg=0x0104  CRC

Reply:    20 01 40 01 7b 00 00 06 00 01 04 [120 bytes data] 50 3a
          dst=0x20  src=0x40  len=0x7b  func=REPLY  reg=0x0104  CRC

Replies swap the address pairs. Broadcast uses [F1 F1] as the destination pair.


Key Registers

Register Name Purpose
0x0104 device_info Device identification — 120-byte payload (model, serial, software version)
0x0202 time Time broadcast (weekday, hour, minute)
0x0203 date Date broadcast (month, day, year)
0x0302 status Indoor/outdoor unit operating status
0x0303 status2 Additional outdoor status
0x0304 config Unit configuration parameters
0x0305 demand Heating/cooling demand (written to indoor unit)
0x0306 capabilities Unit capability flags
0x0307 control Control register (written to indoor unit)
0x030a config2 Extended configuration
0x030d sam_status SAM status — 7 data bytes: 3 sensor values + 4 reserved
0x030e table_list List of supported register table IDs
0x0310 sensors1 Sensor readings group 1
0x0311 sensors2 Sensor readings group 2
0x031c setup_complete Appears at end of airflow test — setup-complete / airflow-calibration register
0x031e param Parameter register
0x0316 indoor_ext Extended indoor unit data
0x0402 airflow_data Airflow calibration/measurement data
0x0403 mode Operating mode control
0x0404 equipment Equipment configuration
0x0409 aux_status Auxiliary equipment status
0x040d fault Fault/diagnostic register
0x041e tstat_probe Thermostat presence probe (scans for additional thermostats)
0x0602 odu_status Outdoor unit status
0x0604 odu_config Outdoor unit configuration
0x0605 odu_demand Outdoor unit demand (written)
0x0608 odu_fault Outdoor unit fault register
0x060a odu_ident Outdoor unit identification (compressor/coil model strings)
0x060b odu_control Outdoor unit control register
0x060d odu_mode Outdoor unit mode
0x060e odu_tables Outdoor unit performance tables
0x0610 odu_setpoint Outdoor unit setpoint
0x0612 odu_param Outdoor unit parameters
0x061a odu_flag Outdoor unit flag
0x061e odu_config2 Outdoor unit config 2 (written frequently)
0x061f odu_perf Outdoor unit performance data (float values)
0x3005 sam_poll_1 SAM bus polling register (phase 1)
0x3003 sam_poll_2 SAM bus polling register (phase 2)
0x3405 nim_probe NIM/zone controller presence probe
0x3c0c sam_poll_3 SAM bus polling register
0x3c0d sam_poll_4 SAM bus polling register
0x3c14 sam_poll_5 SAM bus polling register
0x3e01 tabledef Table definition query (outdoor unit)
0x3e02 sys_config System configuration broadcast
0x3e08 dev14_probe Device 0x0E presence probe
0x3e0a odu_probe2 Secondary outdoor unit probe

Discovery Sequence — Full Timeline

All timestamps are relative to T=0 = first SystemInit frame. The thermostat drives the entire discovery.

Phase 1: SystemInit Commissioning Agent (T+0s – T+8s)

The thermostat switches to address 0x1F (SystemInit) and broadcasts initialization:

[T+0.0s]  SystemInit -> Broadcast  WRITE 0305 (demand=all zeros)
[T+0.1s]  SystemInit -> Broadcast  WRITE 3e02 (sys_config=0x00)
[T+0.1s]  SystemInit -> Broadcast  WRITE 0605 (odu_demand=all zeros)

This triplet repeats every ~1.3 seconds as a heartbeat throughout the SystemInit phase.

SystemInit probes IndoorUnit2 (0x42) — "Select indoor evaporator":

[T+0.5s]  SystemInit -> 0x42  READ 030d — no reply (2 attempts)
[T+0.7s]  SystemInit -> 0x42  READ 031b — no reply (2 attempts)
[T+0.8s]  SystemInit -> 0x42  READ 0404 — no reply (2 attempts)

This probe cycle for 0x42 repeats ~4 times. Each register gets exactly 2 attempts before moving on. SystemInit then deep-probes 0x42 with registers 030a, 0403, 0407, 040b, 040c, 040f, 0410, 0411, 0413, 0414 — all no reply.

SystemInit reads known IndoorUnit (0x40):

[T+1.1s]  SystemInit -> 0x40  READ 0104 → reply (device_info)
[T+1.3s]  SystemInit -> 0x40  READ 0306 → reply
[T+1.5s]  SystemInit -> 0x40  READ 030a → reply
[T+3.6s]  SystemInit -> 0x40  READ 0402, 0403, 0409 → replies

Phase 2: Extended Device Scanning (T+10s – T+45s)

The thermostat (back as 0x20) scans for all possible devices.

Outdoor unit slot scan:

[T+11s]   Thermostat -> 0x50  READ 3e01 — 2x, no reply
[T+12s]   Thermostat -> 0x51  READ 061f — 2x, no reply
[T+14s]   Thermostat -> 0x50, 0x51, 0x54  READ 0104 — 2x each, no reply

Device 0x0E scan (receives 10 attempts per register — significantly more than other addresses):

[T+11s]   Thermostat -> 0x0E  READ 3e08 — 10 attempts, no reply
[T+13s]   Thermostat -> 0x0E  READ 3e01 — 10 attempts, no reply
[T+13s]   Thermostat -> 0x0E  READ 3e0a — 10 attempts, no reply

NIM scan:

[T+12s]   Thermostat -> 0x80  READ 3405 — 2x, no reply (4 rounds)

Indoor unit sub-unit scan (initiated by IndoorUnit itself):

[T+21s]   IndoorUnit(0x40) -> 0x41  READ 030a — no reply (6 attempts)

Zone controller scan — "Zoning: No zones found":

[T+31s]   Thermostat -> 0x60, 0x61  READ 3405 — 2x each, 4 rounds through T+40s

Additional thermostat scan (sequential):

[T+31s]   Thermostat -> 0x21..0x28  READ 041e — 2x each, 2 rounds

Phase 3: Configuration Screens (T+45s – T+250s)

The thermostat displays "Filter type", "Humidifier", "UV lights", "Summary" screens. Traffic is sparse — the thermostat waits for user input. Periodic polling of IndoorUnit and OutdoorUnit2 continues at reduced frequency. No new device scanning.

Phase 4: Airflow Test & Completion (T+250s – T+300s)

Register 0x031c first appears — this is a setup-complete / airflow-calibration register not present during earlier phases:

[T+294s]  Thermostat -> IndoorUnit   WRITE 031c  payload=0c0000000000000000000000
[T+294s]  Thermostat -> OutdoorUnit2 WRITE 031c  payload=440000000000000000000000

"Done" appears on screen at ~T+300s.

Phase 5: Post-Setup Steady State (T+300s+)

Normal polling resumes with 0x031c now included in the regular write cycle.


Device Discovery Probe Summary

How the thermostat discovers each device type

Device Probe Register Probe Address(es) Attempts per Addr Retry Rounds
IndoorUnit 0x0104 0x40 1 (gets reply) 1
IndoorUnit1 0x030a 0x41 6 2
IndoorUnit2 0x030d,0x031b,0x0404,0x0104 0x42 2 each ~4 cycles
OutdoorUnit 0x3e01,0x3e0a,0x0104,0x030a 0x50 2 each 2
OutdoorUnit1 0x061f,0x0104,0x030a 0x51 2 each 1
OutdoorUnit2 0x0104 0x52 1 (gets reply) 1
OutdoorUnit4 0x0104,0x030a 0x54 2 each 1
SAM 0x0104,0x030d 0x92 3 continuous
ZoneControl 0x3405 0x60,0x61 2 4 rounds
NIM 0x3405 0x80 2 4 rounds
Device 0x0E 0x3e08,0x3e01,0x3e0a 0x0E 10 each 2
Thermostat1-8 0x041e 0x210x28 2 each 2 rounds

Discovery order

  1. IndoorUnit2 (0x42) — T+0.5s (SystemInit probes, no reply)
  2. IndoorUnit (0x40) — T+1s (gets reply)
  3. OutdoorUnit (0x50), OutdoorUnit1 (0x51), OutdoorUnit4 (0x54) — T+11-14s
  4. Device 0x0E — T+11-13s
  5. NIM (0x80) — T+12-24s
  6. IndoorUnit1 (0x41) — T+21s (probed by IndoorUnit, not thermostat)
  7. ZoneControl (0x60, 0x61) — T+31-40s
  8. Thermostat1-8 (0x210x28) — T+31-38s

IndoorUnit (0x40), OutdoorUnit2 (0x52), and SAM (0x92) are already known from pre-setup steady-state polling and are not re-discovered.


Steady-State Polling Cycle

After setup, the thermostat repeats this cycle approximately every 4–6 seconds:

┌─ READ 0104 from IndoorUnit ──────────── device identification
├─ READ 0104 from OutdoorUnit2 ─────────── device identification
├─ READ 0306 from IndoorUnit ──────────── capabilities
├─ READ 030a from IndoorUnit ──────────── configuration
├─ READ 0104 from SAM (3x on NET bus) ── SAM identification
├─ READ 0302 from OutdoorUnit2 ────────── status
├─ READ 0303 from OutdoorUnit2 ────────── status2
├─ READ 0604 from OutdoorUnit2 ────────── ODU config
├─ READ 0608 from OutdoorUnit2 ────────── ODU fault
├─ READ 060e from OutdoorUnit2 ────────── ODU tables
├─ READ 061f from OutdoorUnit2 ────────── ODU performance
├─ WRITE 061e to OutdoorUnit2 ─────────── ODU config2
├─ WRITE 0610 to OutdoorUnit2 ─────────── ODU setpoint
├─ WRITE 0612 to OutdoorUnit2 ─────────── ODU param
├─ WRITE 0605 to OutdoorUnit2 ─────────── ODU demand
├─ WRITE 061a to OutdoorUnit2 ─────────── ODU flag
├─ WRITE 060d to OutdoorUnit2 ─────────── ODU mode
├─ WRITE 061e to OutdoorUnit2 ─────────── ODU config2 (repeat)
├─ WRITE 060b to OutdoorUnit2 ─────────── ODU control
├─ READ 0404 from IndoorUnit ──────────── equipment config
├─ READ 040d from IndoorUnit ──────────── fault register
├─ WRITE 0305 to IndoorUnit ───────────── demand
├─ WRITE 0403 to IndoorUnit ───────────── mode
├─ WRITE 0409 to IndoorUnit ───────────── aux status
├─ WRITE 0307 to IndoorUnit ───────────── control
├─ READ 030d from IndoorUnit ──────────── sam_status (returns zeros)
├─ READ 030d from OutdoorUnit2 ────────── sam_status (returns zeros)
├─ READ 030d from SAM ─────────────────── sam_status (returns sensor data)
├─ READ 0316 from IndoorUnit ──────────── extended data
├─ READ 0402 from IndoorUnit ──────────── airflow data
├─ READ 0409 from IndoorUnit ──────────── aux status
└─ [Exception burst to SAM on NET bus]

Write command payloads (thermostat → OutdoorUnit2, idle state)

Register Payload (hex) Notes
0x061e 0f 3f 40 00 00 06 00 00 00 Config — written twice per cycle
0x0610 00 00 00 00 Setpoint = 0 (idle)
0x0612 22 b8 00 00 00 00 00 00 00 00 Parameter
0x0605 00 00 00 00 01 00 00 Demand with flag byte
0x061a 01 Single flag byte
0x060d 00 Mode = off
0x060b 01 04 63 00 00 00 00 Control register

SAM Communication During Setup

The SAM sits on the same RS-485 bus as all other devices (see Infinity Protocol Hardware). It continuously polls the thermostat and replies to reads addressed to 0x92 throughout the setup process.

SAM bus polling pattern

The SAM cycles through these registers, polling the thermostat approximately every 65ms:

Register Approx. Duration Notes
0x3c14 2-10s blocks Most frequent
0x3c0d 2-8s blocks
0x3c0c 2-8s blocks
0x3005 2-5s blocks
0x3003 1-3s blocks

SAM replies

Register 0x0104 (device_info):

Offset  Len  Field
0       3    Register header: 00 01 04
3       50   Device name (ASCII, null-padded)
53      16   Software version (ASCII)
69      20   Model number (ASCII, null-padded)
89      12   Serial number (ASCII)
101     24   Reference (ASCII, null-padded)

Total payload: 125 bytes (3 header + 122 data). Frame LEN = 0x7b (123).

Register 0x030d (sam_status):

Offset  Len  Field
0       3    Register header: 00 03 0d
3       1    val1 (sensor reading)
4       1    val2
5       1    val3
6       4    Reserved (always 0x00)

Exception frames

The thermostat sends exception frames (func=0x15, payload=0x04) addressed to the SAM when it has no data to report. These are not errors — they are "nothing to report" signals. The SAM should silently ignore them.

Pattern: bursts of 1-35 frames at ~67ms spacing, always identical:

92 01 20 01 01 00 00 15 04 66 2a

Clone this wiki locally