No description
  • C++ 98.6%
  • Python 0.8%
  • Shell 0.5%
  • C 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Robert Marshall 17768cd349
All checks were successful
Build and test / build (push) Successful in 4m45s
Build and test / release (push) Successful in 58s
Merge pull request 'Make the kitchen strip a WS2805 RGBCCT colour light' (#107) from feat/kitchen-cct into main
Reviewed-on: #107
2026-10-13 20:24:18 +00:00
.forgejo/workflows Trim and fix comments in build.yml 2026-09-28 07:23:59 +01:00
docs Give the colour light its own PK_COLOUR presentation kind 2026-10-13 20:51:13 +01:00
lib Give the colour light its own PK_COLOUR presentation kind 2026-10-13 20:51:13 +01:00
scripts Trim comments in scripts 2026-09-28 07:23:59 +01:00
src Make the CCT light an RGBCCT colour light with hue and saturation 2026-10-13 20:23:31 +01:00
test Give the colour light its own PK_COLOUR presentation kind 2026-10-13 20:51:13 +01:00
tools Give the colour light its own PK_COLOUR presentation kind 2026-10-13 20:51:13 +01:00
vectors Give the colour light its own PK_COLOUR presentation kind 2026-10-13 20:51:13 +01:00
.clang-format Formatting 2026-09-04 17:11:05 +01:00
.editorconfig The whole point of using tabs is to not enforce and indent size; it should be up to the renderer 2026-09-05 21:16:38 +01:00
.gitignore Check the build id on the images the release publishes 2026-09-20 12:16:34 +01:00
CLAUDE.md Remove debug print from the kitchen touch handler and rewrap docs 2026-10-13 20:19:03 +01:00
CONTRIBUTING.md Finish rewrapping the native environment paragraph 2026-10-13 20:25:06 +01:00
platformio.ini Add LED strip frame-buffer driver and strip animation library 2026-10-13 20:18:59 +01:00
README.md Remove command origin and the manual lockout 2026-10-13 18:20:53 +01:00

Campervan Control Systems

Control systems for a campervan, talking to each other over a dedicated CAN bus at 250 kbps. Most controllers are Seeed Studio XIAO boards with the XIAO CAN Bus Expansion Board. Controllers lists the ones that are not.

docs/can-protocol.md is the authority for all firmware. If code and that document disagree, the document is wrong and gets fixed in the same pull request as the code.

Layout

docs/can-protocol.md      Protocol specification. Read this first.
docs/hardware.md          Boards, pins, driver polarity, touch sensing, wiring.
docs/host-simulator.md    Running a node on Linux with no hardware.
docs/bus-diagnostics.md   Reading a node's [bus] serial output when it goes quiet.
docs/autoterm-diagnostics.md
                          What the heater's state and phase readouts mean.
lib/can-protocol/         Wire protocol (can::): IDs, codecs, units, registries.
                          Header-only, no Arduino dependency. Keep it that way.
lib/node-runtime/         Shared runtime (ctrl::): bus handling, endpoints,
                          failsafe, peer liveness.
src/<node>/main.cpp       One directory per controller.
src/host_sim/             The runtime as a Linux binary on SocketCAN.
test/                     Native tests, run on the host with no hardware.

The two libraries are split on purpose. lib/can-protocol has no Arduino dependency, which is what lets the codecs and the runtime's general paths be tested on the host. Using millis() or Serial in there breaks that.

Building

pio run                        # build every node
pio run -e node_lighting       # build one node
pio run -e node_lighting -t upload
pio device monitor             # 115200 baud
pio test -e native             # run the test suite on the host
pio run -e host_sim            # build the host simulator

Every node uses the min_spiffs.csv partition table, which gives each OTA slot 1.875 MB. A board last flashed before that change needs one cabled -t upload to move over, because the partition table cannot change over the air.

.forgejo/workflows/build.yml runs the tests and builds every node. Pull requests publish nothing. Every push to main publishes a CalVer release (YYYY.MM.<nth build that month>) as a Forgejo release and a campervan-firmware package. See CONTRIBUTING.md.

Running a node with no hardware

scripts/host_sim.sh

This runs the real runtime on a virtual CAN interface, announcing as the lighting node, so Home Assistant or any other consumer has a node to talk to. It can be muted, delayed and driven from the keyboard. docs/host-simulator.md has the details.

Controllers

Node ID Environment Board CAN
Lighting, dimmable ceiling circuits 0x10 node_lighting LOLIN32 (ESP32) native TWAI + WCMCU-230
Kitchen, under-cabinet strip and touch 0x11 node_kitchen XIAO ESP32S3 MCP2515 over SPI
Bathroom, PIR and extractor 0x12 node_bathroom XIAO ESP32C3 MCP2515 over SPI
Water heater, immersion element switching 0x41 node_water_heater XIAO ESP32C3 MCP2515 over SPI

NODE_BRIDGE (0x01) is a Raspberry Pi running Home Assistant and the van's display. Its code lives in its own repository.

docs/hardware.md covers why the lighting node is a different board, the pin assignments, driver polarity, touch sensing and bus wiring.

Contributing

CONTRIBUTING.md has the conventions, the branch and pull request rules, and how to allocate a node ID or an endpoint index.