Skip to content

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.

InterfacePeripheralNotes
AS5047U magnetic encoderSPI (DMA)14-bit absolute rotary position
CANFDCAN1
LoggingLPUART1 (DMA)see esw.stlink

Two independent timers, both configured from flash at startup:

TimerRatePurpose
htim16poll_frequencyread the encoder
htim17publish_frequencysend 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:

  • invert flips the direction of travel.
  • position_offset is subtracted, defining where zero is.
  • output_scalar scales the result, which is how a gear ratio is applied.
  • continuous_mode selects whether the reading wraps at a full turn or accumulates across turns.
  • bounded_mode clamps the output to min_bound and max_bound.
MessageBase IDDLCSignals
ABSResetCmd0x802100001reset, clear_faults
ABSZeroCmd0x802200004offset
ESWConfigCmd0x80F000006address, value, apply
ESWProbe0x80F100004data
MessageBase IDDLCSignals
ABSEncoderState0x802000008position (32, signed), velocity (32, signed)
ESWAck0x80F200004data

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.

Definition: config/abs.yaml. Device values live under rover/ra/, for example rover/ra/abs_de_pitch.yaml.

RegisterTypeMeaning
can_iduint8this board’s CAN node ID
host_can_iduint8where to address published state, normally 0x10
sys_cfguint16bit field: continuous_mode (0), bounded_mode (1), invert (2)
output_scalarfloat32applied to the raw reading, e.g. a gear ratio
position_offsetfloat32subtracted from the raw reading; set by ABSZeroCmd
poll_frequencyfloat32encoder read rate, Hz
publish_frequencyfloat32CAN publish rate, Hz
min_boundfloat32lower clamp, used when bounded_mode is set
max_boundfloat32upper clamp, used when bounded_mode is set

28 bytes total. See Register Definitions and CAN Configuration Interface.

Terminal window
./scripts/build.sh --src src/abs --preset Debug
./scripts/build.sh --src src/abs --preset Debug --flash

src/abs is in ci.json, so CI builds it at both presets.