To build a stable hardware mesh, you must treat the CAN FD bus exactly like a
hardware-level pub/sub event broker. In CAN, nodes don't have MAC addresses;
instead, the messages have IDs. This naturally supports an event-sourced
architecture where the ESP32 publishes a state, and multiple RP2040 edge nodes
subscribe and react simultaneously.
Here is how to design the physical layer and the message schema.
1. The Physical Topology: The Continuous Snake
Unlike Ethernet or USB, CAN cannot be wired as a star (where all limbs connect
centrally to the torso). It must be a single, continuous daisy-chain (a line).
At the high data rates of CAN FD (e.g., 5-8 Mbps), wire branches ("stubs")
cause signal reflections that will instantly crash the bus.
To avoid stubs, the twisted-pair wire must physically weave through the robot
in a single path, with a 120-ohm termination resistor placed exactly at the
two physical ends of the wire.
2. The Message ID Schema (29-Bit Extended)
CAN uses the message ID to resolve collisions. If two nodes talk at the exact
same microsecond, the message with the lowest numerical ID wins arbitration,
and the other node silently backs off and tries again later.
By using the CAN 2.0B 29-bit Extended ID, you can partition the ID into a
bit-field that dictates priority, topic, and routingeffectively building a
lightweight UDP header in hardware.
The Bit Breakdown
* Priority (3 bits): Critical for safety.
* 0x0 = E-Stop / Hardware Fault (Immediate halt).
* 0x1 = IMU sync vectors (Needs lowest jitter).
* 0x2 = High-speed motor targets from the ESP32.
* 0x7 = Background telemetry / Debug strings.
* Topic / Msg Type (10 bits): Defines how the payload should be parsed (e.g.,
0x0A means the payload is an array of 3 floats representing XYZ center of
mass).
* Target Node (8 bits): The destination RP2040. Crucially, reserve 0x00 as a
global broadcast address.
* Sender Node (8 bits): Identifies who is transmitting, preventing two nodes
from ever generating the exact same 29-bit ID (which causes bus errors).
3. Data Packing & The 64-Byte Advantage
Classic CAN limits payloads to 8 bytes. CAN FD allows up to 64 bytes per
frame. This changes the architecture completely: you don't need to send
individual joint commands.
The ESP32 can pack an entire limb's state (e.g., 6 joint angles, 6 velocity
targets, and 6 torque limits = ~48 bytes) into a single CAN FD frame. The
RP2040 edge node receives this single atomic update, parses it into its
dual-core shared memory ring buffer, and applies the new kinematic targets
instantly.
> Key insight: Because CAN is a broadcast medium, if the ESP32 publishes the
global IMU state with a Target Node of 0x00 (Broadcast), the Left Leg RP2040
and Right Leg RP2040 receive the exact same packet at the exact same
microsecond, completely eliminating synchronization drift between the two
legs.
>