7.0 KiB
title, date, draft, description, tags
| title | date | draft | description | tags | |||
|---|---|---|---|---|---|---|---|
| CAN Bus Protocol | 2026-05-21 | false | Complete documentation of the CAN bus communication protocol between PlantCtrl sensor modules and main controller. |
|
CAN Bus Protocol
The PlantCtrl system uses a custom CAN bus-based communication protocol to connect sensor modules (moisture sensors) with the MainBoard controller. This modular design allows for scalable, reliable digital communication even over long cable runs and in electrically noisy environments.
Overview
- Protocol: Standard CAN 2.0A (11-bit identifier)
- Baud Rate: 50 kbps
- Base Address:
0x03E8(decimal 1000) - Maximum Plants: 16 per sensor module
- Sensors per Plant: 2 slots (A and B) for redundancy or larger planters
CAN Bus IDs
All messages use the standard base address 0x03E8 with message-specific offsets. The ID structure is:
ID = 0x03E8 + Message_Offset + Plant_Index (+ Slot_Offset if B)
Message Groups
| Group | Offset (hex) | Direction | Description |
|---|---|---|---|
| Moisture Data | 0x00 |
Sensor → Controller | Periodic moisture readings |
| Identify Command | 0x20 |
Controller → Sensor | LED identification command |
| Firmware Build | 0x40 |
Sensor → Controller | Compile-time build timestamp |
Plant Addressing (Slots A & B)
Each plant gets two sensor slots:
- Slot A: Base offset + plant index (0–15)
- Slot B: Base offset + 16 + plant index (0–15)
Example ID Calculations
| Message Type | Plant | Slot | CAN ID (hex) |
|---|---|---|---|
| Moisture Data | 0 | A | 0x03E8 |
| Moisture Data | 7 | A | 0x0415 |
| Moisture Data | 15 | A | 0x042F |
| Identify Command | 0 | A | 0x0400 |
| Firmware Build | 3 | B | 0x0467 |
Message Formats
All messages are serialized using bincode v2 (fixed-size integers, no varints). Each message fits within a single CAN frame.
Moisture Data (Sensor → Controller)
Sent periodically by each sensor module. Contains:
| Field | Type | Description |
|---|---|---|
plant |
u8 | Plant index (0–15) |
sensor |
SensorSlot | A or B slot |
hz |
u16 | Measured frequency in Hz |
Total size: 4 bytes (fits easily in CAN frame)
Identify Command (Controller → Sensor)
Sent by the controller to trigger an LED identification sequence on the sensor module.
| Field | Type | Description |
|---|---|---|
| (empty) | - | No payload data |
Purpose: When received, the sensor blinks its status LED for a few seconds to confirm it's online and properly configured.
Firmware Build (Sensor → Controller)
Sent immediately after receiving an Identify Command. Contains:
| Field | Type | Description |
|---|---|---|
build_minutes |
u32 | Compile-time timestamp in minutes since Unix epoch |
Purpose: Allows the controller to track firmware versions and deployment history without requiring a separate request.
Sensor Configuration
Each sensor module is configured via hardware jumpers on startup. The configuration is read by the CH32V203 MCU and determines:
- Whether it's Slot A or B for a plant
- The plant index (1–8)
Hardware Switches
| Pin | Function |
|---|---|
| PA3 | Slot selector: Low = A, High = B |
| PA4 | Address bit 1 (value: 1) |
| PA5 | Address bit 2 (value: 2) |
| PA6 | Address bit 3 (value: 4) |
| PA7 | Address bit 4 (value: 8) |
Valid Addresses
- Allowed: 1–8 (binary combinations of bits 1,2,4,8)
- Invalid: 0 or >8 (will trigger error code)
Example Configurations
| Address | Binary | Jumpers |
|---|---|---|
| 1 | 0001 |
PA4 only |
| 3 | 0011 |
PA4 + PA5 |
| 7 | 0111 |
PA4 + PA5 + PA6 |
| 8 | 1000 |
PA7 only |
Error Detection & Blink Codes
The sensor module performs floating pin detection at startup. If any configuration pin is left floating (not connected to VCC or GND), the system enters an error state and blinks a diagnostic code.
Error Code Table
| Code | Cause | LED Pattern |
|---|---|---|
| 1 | PB4 floating (bit 1) | 1 blink info, 2 blinks warning |
| 2 | PB5 floating (bit 2) | 2 blinks info, 2 blinks warning |
| 3 | PB6 floating (bit 3) | 3 blinks info, 2 blinks warning |
| 4 | PB7 floating (bit 4) | 4 blinks info, 2 blinks warning |
| 5 | PB3 floating (A/B selector) | 5 blinks info, 2 blinks warning |
| 6 | Invalid address (0 or >8) | 6 blinks info, 2 blinks warning |
LED Indicators
- Info LED (PA10): Green – indicates information state
- Warning LED (PA9): Yellow/Orange – indicates error/warning state
The blink pattern repeats 5 times, then the system resets automatically.
Address Collision Detection
The protocol includes built-in collision detection. If a sensor receives a moisture data packet addressed to itself, it triggers an error sequence:
- Blink code: 1 info blink, 2 warning blinks
- Log message: "We should never receive moisture packets addressed to ourselves"
This indicates another node is using the same jumper configuration.
CAN Bus Robustness Features
The firmware implements several features for reliable operation:
Automatic Retransmission (NART)
Enabled on the CH32V203 CAN controller to recover from transient errors without manual intervention.
Resync Jump Width (SJW = 4TQ)
Increased from default (1TQ) to improve jitter tolerance over long cable runs. This allows the receiver to resynchronize with the bit stream even if timing drifts slightly.
Error Status Monitoring
The controller monitors CAN error registers for:
- Bus-off condition (
BOFF) - Error warning flag (
EWGF) - Error passive flag (
EPVF)
When errors are detected, warning LEDs blink and the system logs the status.
Troubleshooting
Sensor Not Detected
- Check all jumpers – ensure no floating pins
- Verify address is 1–8 (not 0 or >8)
- Confirm slot selector (A/B) matches expected configuration
- Listen for CAN traffic with a CAN analyzer
- Check error blink codes on the sensor module
Address Collision
- Two sensors using identical jumper settings will cause collisions
- Use the collision detection feature to identify duplicate addresses
- Reconfigure one of the conflicting sensors to a different address
Communication Errors
- Bus-off: Check CAN termination resistors (120Ω at each end)
- High error rate: Verify cable quality and shielding
- Intermittent errors: Check for electrical noise from pumps or motors
Future Extensions
The protocol is designed to be extensible. New message types can be added by:
- Defining a new offset in
canapi/src/lib.rs - Implementing the corresponding message struct with bincode serialization
- Adding receive handlers on both sensor and controller sides
- Documenting the new ID range and format
The current design supports up to 64 distinct message types (16 plants × 2 slots × 2 directions) while maintaining a clean, plant-indexed addressing scheme.