4.2 KiB
4.2 KiB
title, date, draft, description, tags
| title | date | draft | description | tags | |||
|---|---|---|---|---|---|---|---|
| CAN Bus IDs and Wire Format | 2026-05-21 | false | Quick reference for CAN bus identifiers, message formats, and on-the-wire data structures. |
|
CAN Bus IDs and Wire Format
A concise technical reference for the PlantCtrl CAN bus protocol.
Quick Reference Table
| CAN ID (hex) | Message Type | Direction | Payload |
|---|---|---|---|
0x03E8 |
Moisture Data - Plant 0, Slot A | Sensor → Controller | u8 plant + u8 slot + u16 hz |
0x0400 |
Identify Command - Plant 0, Slot A | Controller → Sensor | (empty) |
0x042F |
Moisture Data - Plant 15, Slot A | Sensor → Controller | u8 plant + u8 slot + u16 hz |
0x0467 |
Firmware Build - Plant 3, Slot B | Sensor → Controller | u32 build_minutes |
ID Calculation Formula
ID = 0x03E8 + Message_Offset + Plant_Index (+ Slot_Offset if B)
Constants
| Constant | Value (hex) | Description |
|---|---|---|
SENSOR_BASE_ADDRESS |
0x03E8 |
Base address for all messages |
MOISTURE_DATA_OFFSET |
0x00 |
Moisture data group |
IDENTIFY_CMD_OFFSET |
0x20 |
Identify command group |
FIRMWARE_BUILD_OFFSET |
0x40 |
Firmware build group |
B_SLOT_OFFSET |
0x10 |
Offset for Slot B within a group |
Message Type Offsets
pub const MOISTURE_DATA_OFFSET: u16 = 0; // sensor → controller
pub const IDENTIFY_CMD_OFFSET: u16 = 32; // controller → sensor
pub const FIRMWARE_BUILD_OFFSET: u16 = 64; // sensor → controller
On-the-Wire Formats
Moisture Data Frame (Sensor → Controller)
CAN ID: 0x03E8 + offset + plant_index (or + 16 + plant_index for Slot B)
| Byte | Field | Type |
|---|---|---|
| 0 | plant |
u8 (0–15) |
| 1 | sensor |
SensorSlot (A=0, B=1) |
| 2-3 | hz |
u16 big-endian |
Example: Plant 7, Slot A, frequency 45 Hz
CAN ID: 0x0415
Payload: [07 00 00 2D]
plant=7, sensor=A, hz=45 (0x002D)
Firmware Build Frame (Sensor → Controller)
CAN ID: 0x03E8 + 64 + plant_index (or + 80 + plant_index for Slot B)
| Byte | Field | Type |
|---|---|---|
| 0-3 | build_minutes |
u32 big-endian |
Example: Build timestamp 1,745,239,200 minutes since epoch (May 2026)
CAN ID: 0x0440
Payload: [00 00 6A F8]
build_minutes = 1,745,239,200
Identify Command Frame (Controller → Sensor)
CAN ID: 0x03E8 + 32 + plant_index (or + 48 + plant_index for Slot B)
| Byte | Field | Type |
|---|---|---|
| (none) | (empty payload) | - |
Example: Identify Plant 5, Slot A
CAN ID: 0x0410
Payload: (empty)
Addressing Scheme Details
Plant Index Range
- Valid: 0–15 (decimal) or 1–8 on hardware jumpers (mapped internally as 0–7)
- Slot A:
plant_index= jumper value - 1 - Slot B: Same mapping, but ID offset differs by +16
Slot Selection
| Hardware | Internal Value |
|---|---|
| Jumper on PA3 (Low) | Slot A (0) |
| Jumper on PA3 (High) | Slot B (1) |
Error Detection IDs
The sensor module monitors for unexpected messages:
- Moisture Data collision: If a sensor receives moisture data addressed to itself, it triggers error code 1 (1 info blink, 2 warning blinks)
- CAN errors: Bus-off, EWGF, EPVF flags trigger warning LED blinking
Protocol Extensions
To add new message types:
-
Define offset in
canapi/src/lib.rs:pub const NEW_MESSAGE_OFFSET: u16 = 96; // Next available slot -
Implement message struct with bincode serialization
-
Add receive handler on both sides
-
Update documentation
Binary Protocol Reference
bincode v2 Serialization
- u8: Single byte, no sign extension
- u16: 2 bytes big-endian (network order)
- u32: 4 bytes big-endian (network order)
- No varints – fixed size for predictable CAN frame lengths
CAN Frame Structure
| Arbitration Field | Control Field | Data Field (8 bytes) |
|-------------------|---------------|----------------------|
| 11-bit ID | RTR + IDE | Payload (max 4-6 bytes)|
All PlantCtrl messages fit within the 8-byte data field with room for CAN overhead.