Absolute Encoder (ABS)
Reads a magnetic absolute encoder on a joint and publishes its position and velocity on the CAN
bus. Firmware lives in src/abs.
Absolute encoders keep their reading across a power cycle, so a joint knows where it is at boot without a homing sequence. This is what the arm’s differential and other joints use for position feedback.
Hardware
Section titled “Hardware”| Interface | Peripheral | Notes |
|---|---|---|
| AS5047U magnetic encoder | SPI (DMA) | 14-bit absolute rotary position |
| CAN | FDCAN1 | |
| Logging | LPUART1 (DMA) | see esw.stlink |
Behavior
Section titled “Behavior”Two independent timers, both configured from flash at startup:
| Timer | Rate | Purpose |
|---|---|---|
htim16 | poll_frequency | read the encoder |
htim17 | publish_frequency | send ABSEncoderState |
Both default to 30 Hz in the .ioc and are overwritten by the configured values during init().
Decoupling them means you can poll fast for a smooth velocity estimate while publishing slowly to
keep bus load down.
The raw encoder reading is transformed before publishing, using the configured options:
invertflips the direction of travel.position_offsetis subtracted, defining where zero is.output_scalarscales the result, which is how a gear ratio is applied.continuous_modeselects whether the reading wraps at a full turn or accumulates across turns.bounded_modeclamps the output tomin_boundandmax_bound.
CAN Interface
Section titled “CAN Interface”Receives
Section titled “Receives”| Message | Base ID | DLC | Signals |
|---|---|---|---|
ABSResetCmd | 0x80210000 | 1 | reset, clear_faults |
ABSZeroCmd | 0x80220000 | 4 | offset |
ESWConfigCmd | 0x80F00000 | 6 | address, value, apply |
ESWProbe | 0x80F10000 | 4 | data |
| Message | Base ID | DLC | Signals |
|---|---|---|---|
ABSEncoderState | 0x80200000 | 8 | position (32, signed), velocity (32, signed) |
ESWAck | 0x80F20000 | 4 | data |
Zeroing
Section titled “Zeroing”ABSZeroCmd takes the encoder’s current raw reading, writes it to the position_offset register
and applies it immediately. The joint is therefore zeroed wherever it is standing when the
command arrives, so move it to the reference position first.
Because position_offset is a configuration register, the new zero is written to flash and
survives a power cycle.
tools/scripts/abs_zero.py does this for the arm’s differential pitch and roll encoders, but with
hardcoded CAN IDs (0x37, 0x38) on can1. Read it before running it.
Configuration
Section titled “Configuration”Definition: config/abs.yaml. Device values live under rover/ra/, for example
rover/ra/abs_de_pitch.yaml.
| Register | Type | Meaning |
|---|---|---|
can_id | uint8 | this board’s CAN node ID |
host_can_id | uint8 | where to address published state, normally 0x10 |
sys_cfg | uint16 | bit field: continuous_mode (0), bounded_mode (1), invert (2) |
output_scalar | float32 | applied to the raw reading, e.g. a gear ratio |
position_offset | float32 | subtracted from the raw reading; set by ABSZeroCmd |
poll_frequency | float32 | encoder read rate, Hz |
publish_frequency | float32 | CAN publish rate, Hz |
min_bound | float32 | lower clamp, used when bounded_mode is set |
max_bound | float32 | upper clamp, used when bounded_mode is set |
28 bytes total. See Register Definitions and CAN Configuration Interface.
Building
Section titled “Building”./scripts/build.sh --src src/abs --preset Debug./scripts/build.sh --src src/abs --preset Debug --flashsrc/abs is in ci.json, so CI builds it at both presets.