03Electronics & wiring
Two custom PCBs tie every actuator onto one local network: CAN for the motor buses, TTL serial for the hands and neck, Ethernet and USB 3 for the bandwidth. One battery powers everything — nothing trails behind the robot. Pinouts and harness drawings: MABEL_Wiring_Guide.pdf.
Bus map
| Bus | Physical | Devices | Owner MCU / link |
|---|---|---|---|
| Base CAN | CAN, 120 Ω both ends | 6 × SPARK (IDs 1–6) | Base Teensy 4.1 → Ethernet |
| Arm left | CAN can0 | 7 × DaMiao (IDs 1–7) | Arms Teensy → Ethernet |
| Arm right | CAN can1 | 7 × DaMiao (IDs 1–7) | |
| Body CAN | CAN | Torso DM-J10422P + neck yaw DaMiao | the arms Teensy’s third CAN bus (since 2026-07-28). USB-CAN dongles are the documented fallback, not the primary path |
| Hand left | 1 MHz half-duplex TTL | 17 × Feetech (16 finger + wrist) | USB serial adapter (CH340) |
| Hand right | 1 MHz half-duplex TTL | 17 × Feetech | USB serial adapter (CH340) |
| Neck TTL | 1 Mbaud half-duplex TTL | 2 × Dynamixel XC330-T181 (roll, pitch) | U2D2 on the Jetson |
| Lift | USB serial | BTS7960 + encoder | RP2040 Pico |
ls -l /dev/serial/by-id/) and register it left/right in
hardware_bridge/mabel_hw/config.py; the software then binds sides
correctly no matter which port they land on.
Install order
- Land both custom PCBs — the base board in the chassis, the body board on its printed mount. The gerbers are NOT released yet (tracked in BOM/data/open_items.csv).
- Fan power out from the single pack. The bus is 24 V with a 24→12 V buck for the low rails, distributed through a blade-fuse box — fuse per the wiring guide. A 6-port 2.5 GbE switch is the onboard network spine.
- Bring up the CAN buses — base (6 SPARK), body (torso + neck yaw), and the two arm buses. Terminate every chain at both ends.
- Bring up the serial buses — one TTL chain per hand, the neck pair through the U2D2, the lift Pico over USB.
- Connect the sensing — head stereo camera (USB 3), wrist cameras, 2D lidar, and (Maximum tier) the base depth camera.
- Wire Ethernet — base Teensy and arms Teensy to the Jetson (directly or through the Ethernet expansion board — see network plan).
Network plan
The robot's internal network is a flat 192.168.124.0/24:
| Node | Address | Notes |
|---|---|---|
| Jetson (host) | 192.168.124.2 | assigned on whichever wired port answers |
| Base Teensy | 192.168.124.10 | swerve + lift relay |
| Arms Teensy | 192.168.124.11 | both arm CAN buses |
The Teensys are port-agnostic: each may plug into the Jetson's direct NIC, a QSFP breakout lane, or the Ethernet expansion board (a small switch that puts several devices behind one port). The bring-up script discovers which port a Teensy actually answers on (ARP probe) and pins a host route to it at runtime — you do not hand-configure interfaces. A 100M link speed means a Teensy is plugged straight in; 10G means it is behind the expansion board.
Service ports (host)
Every client — browser, iPhone, Vision Pro — speaks to these; identical for the simulator and the real robot:
| Port | Service |
|---|---|
| 9090 | teleop WebSocket — the one wire contract (control + state + map) |
| 8080 | camera video (MJPEG per camera, + /cameras.json roster, + web console) |
| 9091 / 9092 | UDP-JPEG / H.264 low-latency video |
| 9600 | telemetry plane — joints/control/status/lidar JSON (read-only) |
| 9601–9605 | pointclouds per camera + SLAM mesh/pose/grid (read-only) |
| 9610 | audio duplex (robot mic up / operator voice down) |
| 9620–9623 | dedicated per-camera video tees |
| 8094 | Control Center web studio |
Audio
A USB sound card (VID:PID 0c76:1203) drives an 8 Ω / 5 W speaker
pair and the microphone. It is identified by USB identity, not port — replug
it anywhere and it reconnects. (Its serial number is hard-coded by the vendor,
which is why identity is VID:PID here, unlike the hands.)
Power, and the one thing that is not wired
One 24 V supply, one buck converter, and a 12 V rail under it. Three loads get their own line straight from the supply, and the reason is the same in each case: motor spikes must not reach the compute.
| Load | Rail | Taps from |
|---|---|---|
| Jetson Thor | 24 V | the supply, on its own line |
| Torso bus | 24 V | the supply — feeds both arms and the neck yaw |
| Arms, per joint group | 24 V | the torso bus: J1+J2, J3+J4, J5+J6+J7 |
| Lift controller | 24 V | the supply, on its own line — the biggest current spike on the robot |
| 6 base motor drivers | 12 V | the buck |
| Ethernet board (and both Teensies) | 12 V | the buck |
| USB expansion board | 12 V | the buck — ten devices; never run it bus-powered |
| Left / right hand | 12 V | the buck. Power only; data goes over USB |
| Neck Dynamixel bus | 12 V | the buck. The U2D2 itself is USB-powered |
Never share a return run: Thor, the lift controller and the torso bus each get their own pair. And the buck converter is a single point of failure — if the hands, the base and the whole USB tree die at once, check it first.
There is no hardware E-stop in this guide, because there is not one in
the build. What exists is a software stop —
hw.estop() on /mabel/hw/base/estop, lease-free and
bypassing arbitration by design — and that is not the same thing as a switch
that de-energises the actuators independently of the host. The safety notes
assume the hardware path; the BOM tracks the switch and contactor as an
uncosted open item at $30–80. Fit one before you first energise the arms.
Things that will cost you an evening
- The lidar browns out on a weak USB port. Its adapter feeds the whole unit from USB 5 V and the motor start surges about 1.5 A. On an underpowered port the serial link goes dark the instant the motor engages and only a replug revives it. Use a powered hub or a root port.
- The two wrist cameras share one USB-2 hub and cap at about
15 Hz for the pair. Pin them by hub port with the udev rules in
hardware_bridge/install/(1-4.1.1 is right, 1-4.1.2 is left) or they swap sides on reboot. - Head and base cameras go direct to Thor. Everything on the hub is either slow or a single wrist stream.
- Label both ends of every cable before you power up, and bind the
cameras and the lidar to udev by serial. On 2026-07-08 the left hand's
auto-claim grabbed the RPLIDAR's adapter and sprayed servo packets at the
lidar until it wedged; that is why there is no blind
/dev/ttyUSB0fallback anywhere in the config. - Every CAN chain should read about 60 Ω across H and L — two 120 Ω terminators in parallel. Nothing in the repo checks this for you; measure it.
Wiring completion check
- Every CAN chain measures ~60 Ω across H/L (two 120 Ω terminators in parallel)
- Both hand chains and the neck pair answer a servo scan on the bench
- Both Teensys answer ping at their addresses from the Jetson
- All cameras enumerate (
lsusb) on the powered hub, wrist ports noted - One battery, no wall tether; current-limited supply on hand for first power-on