Skip to main content

Boards, roles & node IDs

Reference. Firmware: uc2-ESP, platformio.ini and main/config/<env>/PinConfig.h.

Roles​

RolecanRoleWhat it does
Standalone0serial JSON only, all devices local
CAN master1node 1; serial JSON in, routes each device locally or via SDO to a satellite
CAN slave (satellite)2executes OD writes, reports via TPDO; still accepts serial JSON on its own USB
Bridge2slave that also sends SDOs to other nodes (PS4 controller, PTZ keyboard, M5 dial)

Role and node ID come from the build. Values stored in NVS (/config_set, /can_act) override the build. They survive CAN firmware updates and pio run -t upload; a full web-flash resets them.

Firmware environments​

Release images (web flasher, youseetoo/uc2-esp32-binaries) are full images flashed at 0x0, named by board ID, e.g. uc2-can-master.bin, uc2-can-slave-motor.bin. The FRAME firmware server inside ImSwitch OS uses esp32_<env>.bin (app only) and esp32_<env>_merged.bin.

EnvBoardRoleDefault nodeSerial baudCAN TX / RX
UC2_3, UC2_4standalone v3 / v4 (ESP32 DevKit)standalone—115200—
UC2_canopen_standalone_v4_releasestandalone v4master (hybrid)1115200GPIO32 / GPIO33
UC2_canopen_masterHAT+ v2 ESP32master1921600GPIO17 / GPIO18
UC2_canopen_slave_motorstepper backpack (XIAO ESP32-S3)slave11 (CI: _motA/X/Y/Z = 10/11/12/13)USB-CDCD2 GPIO3 / D1 GPIO2
UC2_canopen_slave_accelmotorXIAO, AccelStepperslave11USB-CDCD2 / D1
UC2_canopen_slave_laserlaser interface (XIAO)slave20USB-CDCD3 GPIO4 / D10 GPIO9
UC2_canopen_slave_ledillumination / LED ring (XIAO)slave30USB-CDCD4 GPIO5 / D5 GPIO6
UC2_canopen_slave_galvogalvo interface (XIAO)slave40USB-CDCD4 GPIO5 / D7 GPIO44
UC2_canopen_slave_gpioE-stop / collision / I2C bridge (XIAO)slave60USB-CDCD2 / D1
UC2_canopen_bridge_ptzPelco PTZ keyboard (XIAO)bridge61USB-CDCD2 / D1
UC2_canopen_bridge_ps4_usbhostDS4 over USB-OTG (XIAO)bridge5USB-CDCGPIO13 / GPIO14
m5stack_dialM5 Dialbridge62USB-CDCGPIO2 / GPIO1

Most CAN envs also exist as _release and _debug; _debug builds print more log lines on the serial port. Do not build *_default envs: they pick up a stale PinConfig.h.

Default node IDs​

NodeDevice
1master (HAT+ or standalone v4)
5PS4 bridge
10, 11, 12, 13motor A, X, Y, Z
20laser board (channels 0–3 = OD sub 1–4)
30LED / illumination board (also laser id 4 on sub 1)
40galvo
60GPIO satellite
61, 62PTZ bridge, M5 dial
  • Motor satellites built without an axis suffix are all node 11. Set unique IDs before connecting several (how).
  • The master receives motor feedback only from nodes 10–13.
  • uc2canopen (NODE.*) and ImSwitch's UC2CANOpenManager use different defaults: motor A 14, LED 20, laser 21, galvo 30. Pass node IDs explicitly.

Default routing on the masters​

Logical ids → where /motor_act, /laser_act, … go. Inspect with {"task":"/route_get"}.

Device idUC2_canopen_master (HAT+)UC2_canopen_standalone_v4_*
motor / home / TMC 0–3 (A X Y Z)node 10–13, sub id+1local
motor ≥ 4——
laser 0–3node 20, sub 1–4local (pins for 1–3)
laser 4node 30, sub 1node 30, sub 1
LED arraynode 30node 30 + local mirror
galvonode 40node 40
digital I/O, gpio, i2c with "node"node 60node 60

Bus wiring​

ItemValue
Bitrate500 kbit/s
ConnectorJST-XH 4: 1 GND · 2 +12 V · 3 CAN_H · 4 CAN_L (HAT+ J102, galvo J1001; daisy-chain)
Termination120 Ω at both physical ends only. Solder jumpers (open by default): HAT+ v2 JP801, HAT+ v1 JP1001, stepper backpack JP502, laser interface JP301, galvo JP2001
TransceiversSN65HVD230 (3.3 V), not isolated
Bus powerHAT+: switched 12 V on pin 2; off via ESP32 GPIO4, Pi GPIO23, E-stop, or {"task":"/state_act","power":0}

HAT+ v2 Raspberry Pi side​

HAT+ v2 connections

Pi pinGPIOUse
8 / 1014 / 15UART to ESP32 (parallel to USB-C CP2102)
11 / 3617 / 16RTS / DTR auto-program (JP901 / JP902)
19, 21, 23, 24SPI0 + CE0MCP2515
3212MCP2515 interrupt
1623bus power off (high = off)
3 / 52 / 3I2C-1, via JP101/JP102 (open by default)

MCP2515 crystal: 12 MHz. Device-tree overlay: dtoverlay=mcp2515-can0,oscillator=12000000,interrupt=12.