Add Si7021 cabin temperature and humidity to the heater node #89

Merged
rob merged 18 commits from feat/heater-si7021-sensor into main 2026-10-10 14:27:56 +00:00
Collaborator

Adds an Si7021 (I2C 0x40) to NODE_HEATER, reported as two readouts at indices 11 (temperature) and 12 (humidity). Adds EP_HUMIDITY (0x16) and semantic class 0x2D humidity to the spec and code. No codec changes; vectors/frames.json is untouched.

The driver is non-blocking: it sends the measure command, reads about 25 ms later, and repeats every 10 s. A NACK or bad CRC reports Fault; nothing read yet reports Unknown.

The Home Assistant integration (separate repo) needs 0x16 and 0x2D added. Until then it falls back to the generic readout band.

Tested: pio test -e native and pio run -e node_heater. Not tested on hardware.

Ticket: CCS-WHP-11

Adds an Si7021 (I2C 0x40) to NODE_HEATER, reported as two readouts at indices 11 (temperature) and 12 (humidity). Adds `EP_HUMIDITY` (0x16) and semantic class 0x2D humidity to the spec and code. No codec changes; `vectors/frames.json` is untouched. The driver is non-blocking: it sends the measure command, reads about 25 ms later, and repeats every 10 s. A NACK or bad CRC reports Fault; nothing read yet reports Unknown. The Home Assistant integration (separate repo) needs 0x16 and 0x2D added. Until then it falls back to the generic readout band. Tested: `pio test -e native` and `pio run -e node_heater`. Not tested on hardware. Ticket: CCS-WHP-11
Add Si7021 cabin temperature and humidity to the heater node
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
08b6a5b24e
Claude left a comment

Three things to fix, one to check.

Three things to fix, one to check.
@ -211,6 +211,7 @@ registry — and never travel on the bus.
| 0x13 | `EP_ENERGY` | in | Cumulative Wh |
| 0x14 | `EP_SETTING` | out | Adjustable value the node stores and restores at boot |
| 0x15 | `EP_COUNTER` | in | Dimensionless count, raw |
| 0x16 | `EP_HUMIDITY` | in | Relative humidity |
Author
Collaborator

Line 257 (semantic class table for 0x20-0x3F) still ends at 0x2C percentage. Add 0x2D humidity. The spec is authoritative and must match the code in this PR.

Line 257 (semantic class table for 0x20-0x3F) still ends at `0x2C percentage`. Add `0x2D humidity`. The spec is authoritative and must match the code in this PR.
@ -0,0 +52,4 @@
return !readConversion();
}
if (everStarted_ && now - startedAt_ < conversionIntervalMs) return false;
startedAt_ = now;
Author
Collaborator

Bus-failure path is untested and cannot be: the state machine lives in the Arduino-only TU. Not blocking, but the Fault/recovery logic (converting_ reset, retry only after the 10 s interval) has no coverage. Consider moving the state machine behind a small read/write interface if you want it tested.

Bus-failure path is untested and cannot be: the state machine lives in the Arduino-only TU. Not blocking, but the Fault/recovery logic (converting_ reset, retry only after the 10 s interval) has no coverage. Consider moving the state machine behind a small read/write interface if you want it tested.
@ -84,1 +91,4 @@
node.addEndpoint(&warmUpWait, "Twait warm up");
node.addEndpoint(&cabinTemperature, "Cabin temperature");
node.addEndpoint(&cabinHumidity, "Cabin humidity");
Author
Collaborator

Please confirm on hardware or from the XIAO C3 pinout that default Wire.begin() pins (D4/D5) are free on this node: D0/D1 are the heater UART and the MCP2515 uses SPI. Nothing in the PR or docs says which pins the Si7021 is wired to; one line in the spec's heater section would help.

Please confirm on hardware or from the XIAO C3 pinout that default `Wire.begin()` pins (D4/D5) are free on this node: D0/D1 are the heater UART and the MCP2515 uses SPI. Nothing in the PR or docs says which pins the Si7021 is wired to; one line in the spec's heater section would help.
@ -17,3 +17,3 @@
EndpointType::TankLevel, EndpointType::Voltage, EndpointType::Current, EndpointType::Power, EndpointType::Soc,
EndpointType::Orientation, EndpointType::Heater, EndpointType::AlarmSensor, EndpointType::Energy, EndpointType::Setting,
EndpointType::Counter,
EndpointType::Counter, EndpointType::Humidity,
Author
Collaborator

Nothing pins SemanticClass::Humidity == 0x2D. test_presentation.cpp:54 pins 0x2C the same way; add 0x2D there. Also fix the column alignment on this line (EndpointType::Counter, EndpointType::Humidity); run clang-format.

Nothing pins `SemanticClass::Humidity == 0x2D`. `test_presentation.cpp:54` pins 0x2C the same way; add 0x2D there. Also fix the column alignment on this line (`EndpointType::Counter, EndpointType::Humidity`); run clang-format.
Fix humidity in the semantic class table and pin its value
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
c1ea6c75b1
Claude left a comment

Minor: humidity_ in lib/node-runtime/src/si7021.h defaults to the int16 unknown sentinel (0x8000), but the endpoint is uint16 and the fault path uses u16Fault. Before the first reading it reports 0x8000 with status Unknown. Status saves it, but initialise humidity_ with u16Unknown to match. Nothing else to act on.

Minor: humidity_ in lib/node-runtime/src/si7021.h defaults to the int16 unknown sentinel (0x8000), but the endpoint is uint16 and the fault path uses u16Fault. Before the first reading it reports 0x8000 with status Unknown. Status saves it, but initialise humidity_ with u16Unknown to match. Nothing else to act on.
Default the humidity reading to the uint16 unknown sentinel
All checks were successful
Build and test / build (pull_request) Successful in 1m38s
Build and test / release (pull_request) Has been skipped
3d3357a592
rob added 15 commits 2026-10-10 14:24:43 +00:00
Drive the heater blower motor from the MOSFET on D2
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
ebd38a0524
Retry the blower edge when the lockout refuses it
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
341e4a40ca
Skip the blower edge while the motor is locked out
All checks were successful
Build and test / build (pull_request) Successful in 1m35s
Build and test / release (pull_request) Has been skipped
f7c56f6bee
Regulate the cabin by blower speed from a stored heater setpoint
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
fbac6d591b
Skip the idle blower write and test the setpoint edge cases
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
17e3b63e65
Run the blower controller every pass and integrate per reading
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
eca188558c
Pin the blower level holding between readings
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
083f0fb5f6
Apply the link-loss blower demand with failsafe origin
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
7d9de0af46
Note the Si7021 wiring in the heater node
All checks were successful
Build and test / build (pull_request) Successful in 1m56s
Build and test / release (pull_request) Has been skipped
1f46064102
Poll the Si7021 every 100 ms and report cabin readings on change
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
079194a00d
Test the status change on its own in the readout tests
Some checks failed
Build and test / release (pull_request) Has been cancelled
Build and test / build (pull_request) Has been cancelled
8596e44854
Limit blower writes to once a second and re-assert every 10 s
All checks were successful
Build and test / build (pull_request) Successful in 1m32s
Build and test / release (pull_request) Has been skipped
0ca99e367c
Merge pull request 'Poll the Si7021 every 100 ms and report cabin readings on change' (#92) from feat/heater-sensor-rate into feat/heater-cabin-control
All checks were successful
Build and test / build (pull_request) Successful in 2m32s
Build and test / release (pull_request) Has been skipped
1909942941
Reviewed-on: #92
Merge pull request 'Regulate the cabin by blower speed from a stored heater setpoint' (#91) from feat/heater-cabin-control into feat/heater-blower-output
All checks were successful
Build and test / build (pull_request) Successful in 2m59s
Build and test / release (pull_request) Has been skipped
db713f3874
Reviewed-on: #91
Merge pull request 'Drive the heater blower motor from the MOSFET on D2' (#90) from feat/heater-blower-output into feat/heater-si7021-sensor
All checks were successful
Build and test / build (pull_request) Successful in 2m2s
Build and test / release (pull_request) Has been skipped
60afdeadc0
Reviewed-on: #90
rob merged commit f5ec28f128 into main 2026-10-10 14:27:56 +00:00
rob deleted branch feat/heater-si7021-sensor 2026-10-10 14:27:56 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rob/CampervanControlSystems!89
No description provided.