Skip to main content

CANopen object dictionary

Reference. Source of truth: uc2-ESP/lib/uc2_od/OD.c (hand-maintained). Every role (master, satellites, bridges) runs the same OD; what a node does with an object depends on its build.

EDS files

DOCUMENTATION/openUC2_satellite.eds is generated from tools/canopen/uc2_canopen_registry.yaml, not from OD.c. It lists 21 objects that do not exist on the device, wrong identity/heartbeat/PDO defaults, and wrong sizes for 0x2609/0x260A. openUC2_satellite_new.eds is an older snapshot. Neither the firmware nor uc2canopen loads an EDS. Use the tables below.

Bus and services​

ItemValue
StackCANopenNode v4.0 on ESP32 TWAI
Bitrate500 kbit/s, fixed (LSS bit-timing changes are ignored)
Identifiers11-bit
NMTno NMT master; every node boots straight to OPERATIONAL
Heartbeatevery node, 1000 ms (0x1017); no heartbeat consumer configured
SDOone server per node: request 0x600+n, response 0x580+n; block transfer supported (OTA)
SYNC0x080, sent only by the master during a strobed sweep
EMCY0x080+n; codes 0xFF01–0xFF07 = closed-loop axis faults
LSSslave only; serial number = lower 32 bits of the MAC
Identity 0x1018vendor 0x00001234, product 0x1, revision 1 (placeholders)

PDOs​

The master sends commands only via SDO. PDOs carry feedback.

PDOCOB-IDProducerContent (bytes)Timing
TPDO10x180+nevery node0x2001:01 position i32 · 0x2004:01 status u8 · 0x2016:01 homing u8 (6)on change, inhibit 10 ms, event 500 ms
TPDO20x280+nGPIO satellite (60), PTZ bridge (61)0x2300:01–04 4× u8 · 0x2310:01–02 2× u16 (8)on change only
TPDO30x380+nmotor satellites with sync latch on0x200C:01 latched position i32 · 0x200D:01 count u16 (6)after each SYNC
RPDO1–40x18A–0x18Dconsumed by every nodeTPDO1 of nodes 10–13 → slot 0–3 of 0x2001/0x2004/0x2016—

Status byte (0x2004): bit 0 = running, bit 1 = 1 Hz toggle (keep-alive). Homing byte (0x2016): 0 idle, 1 homing, 2 done, 3 timeout.

Conventions​

  • Arrays: sub 0 = count (ro), sub 1…N = elements.
  • Motor-type arrays: sub = stepperid + 1 (A = 1, X = 2, Y = 3, Z = 4). A single-axis motor satellite maps any sub to its one physical axis for move, home and hard-limit objects. 0x2005 and 0x2020–0x2026 are read from sub 2 only.
  • Laser arrays: sub = channel + 1.
  • All manufacturer values are 0 after boot.
  • "doorbell" = writing the value triggers an action; the node clears it.

Manufacturer objects​

Motor 0x2000–0x200E​

IndexNameTypeAccMeaning
0x2000 [4]target_positionI32rwsteps
0x2001 [4]actual_positionI32ro*steps (TPDO1)
0x2002 [4]speedU32rwsteps/s, sent signed (sign = jog direction)
0x2003command_wordU8rwdoorbell: bit n (0–3) = start slot n, bit n+4 = stop slot n
0x2004 [4]status_wordU8ro*bit 0 running, bit 1 keep-alive toggle
0x2005 [4]enableU8rw1 = driver on
0x2006 [4]accelerationU32rwsteps/s²; 0 = keep previous
0x2007 [4]is_absoluteU8rw0 relative, 1 absolute
0x200B [4]is_foreverU8rw1 = jog until stop
0x200C [4]sync_positionI32roposition latched at SYNC (TPDO3)
0x200D [4]sync_countU16roSYNCs latched since enable
0x200E [4]sync_latch_enableU8rw≠ 0 enables latch + TPDO3, resets count

ro* = declared rw in OD.c; treat as read-only. 0x2008/0x2009 (min/max position) and 0x200A (jerk) exist but are not used.

Homing 0x2010–0x2016​

IndexNameTypeMeaning
0x2010 [4]commandU8doorbell: 1 = home, 2 = hard home (new)
0x2011 [4]speedU32steps/s (max speed = 2 × speed)
0x2012 [4]directionI8−1 / 1
0x2013 [4]timeoutU32ms
0x2014 [4]endstop_releaseI32steps
0x2015 [4]endstop_polarityU80 NO, 1 NC
0x2016 [4]statusU80 idle, 1 homing, 2 done, 3 timeout (TPDO1)

TMC2209 and hard limits 0x2020–0x2032​

IndexNameTypeMeaning
0x2020 [4]microstepsU160 = keep default
0x2021 [4]rms_currentU16mA
0x2022 [4]stallguard_thresholdU8
0x2023/0x2024 [4]coolstep_semin / semaxU8
0x2025/0x2026 [4]blank_time / toffU8
0x2027 [4]stall_countU32not populated
0x2030 [4]hardlimit_commandU8doorbell: 1 = clear trip
0x2031 [4]hardlimit_enabledU8
0x2032 [4]hardlimit_polarityU8

Closed-loop axis 0x2040–0x204B (motor satellites with encoder)​

IndexNameTypeAccMeaning
0x2040measured_stepsI32roencoder position in steps
0x2041position_error_stepsI32ro
0x2042modeU8rw0 open loop, 1 monitor, 2 correct, 3 servo
0x2043healthU8ro
0x2044faultU8ro0 none … 7 encoder noise
0x2045resetU8rwdoorbell 1–3
0x2046/0x2047calibrated / referencedU8ro
0x2048calibrateU8rwdoorbell
0x2049counts_per_step_q16I32rwQ16.16
0x204Abacklash_stepsI32rw
0x204Braw_countsI32ro

Laser 0x2100–0x210A​

IndexNameTypeMeaning
0x2100 [4]pwm_valueU16duty, applied on change
0x2107 [4]strobe_enableU8new. 1 = one flash per SYNC; node writes 0 back if refused
0x2108 [4]strobe_delay_usU32new. µs after SYNC
0x2109 [4]strobe_width_usU32new. µs
0x210A [4]strobe_countU32new. flashes fired (ro)

0x2101–0x2103 (max value, PWM frequency, resolution) and 0x2106 (safety state) exist but are not used.

LED array 0x2200–0x2221​

IndexNameTypeMeaning
0x2200modeU80 off, 1 fill, 2 left, 3 right, 4 top, 5 bottom half; others → fill
0x2201brightnessU80–255 (0 ignored)
0x2202uniform_colourU320x00RRGGBB
0x2210pixel_dataDOMAINN × {r,g,b}, ≤ 256 px (segmented SDO)
0x2211single_pixel5 bytesu16 index (LE), r, g, b
0x2212shape5 bytesshape (0 rings, 1 circle), radius, r, g, b
0x2220pattern_idU8starts a pattern
0x2221pattern_speedU16

0x2203 (pixel count) is not populated.

GPIO satellite 0x2300–0x2354​

IndexNameTypeMeaning
0x2300 [8]digital_input_stateU8sub 1 E-stop, 2–3 inputs, sub 4 flags (bit 0 collision trip, bit 1 E-stop). TPDO2
0x2301 [8]digital_output_commandU8sub 1–2 = DO1/DO2; 0xFF = pulse
0x2310 [8]analog_input_valueU16sub 1 filtered, sub 2 raw ADC. TPDO2
0x2330collision_referenceU16ADC counts (manual baseline)
0x2331collision_thresholdU16ADC counts
0x2332collision_sensitivityU8consecutive samples
0x2333collision_commandU81 calibrate, 2 auto, 3 manual
0x2334/0x2336collision_mean / sigmaU16ro
0x2335collision_modeU80 auto, 1 manual
0x2350i2c_command40 bytesaddr7, flags (bit 0 STOP), rd_len, wr_len, delay_ms, data…
0x2351i2c_triggerU8≠ 0 executes
0x2352i2c_statusU80 idle, 1 busy, 2 ok, 0x80|err
0x2353i2c_response40 bytesread data
0x2354i2c_resp_lenU8valid bytes in 0x2353

The PTZ bridge reuses 0x2300 sub 1–4 for key events (type, arg, sequence, 0x80 marker). 0x2340 (encoder position) is not populated.

System 0x2500–0x250A​

IndexNameTypeAccMeaning
0x2500firmware_versionVSTRING 64ro
0x2501board_nameVSTRING 64ropublished image name, e.g. esp32_UC2_canopen_slave_motor_release_motX.bin
0x2503uptime_secondsU32ro
0x2504free_heap_bytesU32ro
0x2505can_error_counterU32ronot populated
0x2507reboot_commandU8rw1 = reboot after 200 ms
0x2508build_timestampVSTRING 32ro
0x2509mac_addressVSTRING 18roAA:BB:CC:DD:EE:FF
0x250Acommanded_node_idU8rw1–127; saved to NVS, node restarts CANopen after 250 ms under the new ID

Galvo 0x2600–0x2610​

IndexNameTypeMeaning
0x2600 [2]target_positionI32X/Y, DAC 0–4095
0x2602command_wordU81 goto, 2 line, 3 raster, 4 stop, 5 e-stop
0x2603status_wordU8bit 0/1 = running
0x2604scan_speedU32sample period in µs
0x2605/0x2606n_steps_line / n_steps_pixelU16nx / ny
0x2607d_steps_lineU16bidirectional flag
0x2608d_steps_pixelU16line settle samples
0x2609/0x260At_pre_us / t_post_usU16pre / fly samples
0x260B/0x260Cx_start / y_startI32
0x260D/0x260Ex_step / y_stepI32
0x260Fcamera_trigger_modeU8camera trigger enable (enable_trigger)
0x2610points_dataDOMAIN{u8 trigger, u16 n} + n × {u16 x, u16 y, u32 dwell_us}, n ≤ 256

0x2601 (actual position) is not populated.

Firmware update 0x2F00–0x2F05​

IndexNameTypeMeaning
0x2F00firmware_dataDOMAINimage, SDO block download
0x2F01firmware_sizeU32write starts the update; 0 aborts; max 0x140000
0x2F02firmware_crc32U32zlib CRC-32 of the image; 0 skips the check. Write before 0x2F01.
0x2F03statusU80 idle, 1 receiving, 2 verifying, 3 complete, 0xFF error
0x2F04bytes_receivedU32
0x2F05error_codeU81 no partition, 2 begin, 3 write, 4 CRC, 5 commit, 6 size 0, 7 too large

The node reboots into the new image 2 s after status 3. A transfer idle for 30 s is aborted.

In the EDS but not on the device​

0x2104, 0x2105 (despeckle), 0x2204, 0x2205 (LED layout), 0x2302, 0x2311, 0x2320 (DIO mask, filtered ADC, DAC), 0x2341, 0x2342 (encoder), 0x2400–0x2403 (joystick), 0x2502 (module bitmask), 0x2506 (CPU temperature), 0x2700–0x2705 (PID). SDO access returns abort 0x06020000.