Skip to content

EncoderManager

Owns up to four AS5047U magnetic angle encoders. Vortex V1 has a chip select wired for one encoder (AS5047U_POSITION_ENCODER, GPIO20) and two external chip selects that can each take another, but no encoder is created automatically: you create each device. Source: EncoderManager.h.

API

Call Notes
CreateAs5047uDevice(index, SpiDeviceId, config = default) Creates an encoder on one of the board's chip selects; also an overload taking a BaseSpi&
DeleteDevice(index) Removes it
ReadAngle(index, uint16_t& counts), ReadAngleDegrees(index, double& deg) 14-bit angle, or degrees
ReadVelocityRPM(index, double& rpm) Velocity from the sensor
ReadDiagnostics(index, As5047uDiagnostics&) Error flags (one ERRFL read) and the manager's counters
ReadFieldStrength(index, EncoderFieldStrength&) AGC value and CORDIC magnitude: how strong the magnet looks
SetZeroPosition(index, counts) Zero offset
ReadAllAngles(...), ReadAllVelocities(...), CheckAllDevicesHealth() Every active device, under the manager lock
GetAs5047uHandler(index), VisitDriver(index, fn) The handler, or fn(driver) on the typed driver under the manager and handler locks, for chip features the manager does not wrap
IsDeviceValid, GetActiveDeviceIndices, GetAvailableDevices, GetDeviceType Device bookkeeping
GetLastError(), GetSystemDiagnostics(EncoderSystemDiagnostics&), DumpStatistics() Counters and the last error

Example: create the onboard-slot encoder and read it

#include "api/Vortex.h"
#include "managers/EncoderManager.h"

auto& enc = Vortex::GetInstance().encoders;
if (enc.CreateAs5047uDevice(0, SpiDeviceId::AS5047U_POSITION_ENCODER)) {
    double deg = 0.0;
    if (enc.ReadAngleDegrees(0, deg) == EncoderError::SUCCESS) {
        // deg is the shaft angle, 0 to 360
    }
}

Pitfalls

  • Nothing to read until you create a device. EnsureInitialized() succeeds with zero devices.
  • SPI2 is shared with the TMC9660 (when on SPI) and the external slots.
  • Every read takes the manager lock and the handler lock for the SPI exchange, and so does VisitDriver(); keep the function you pass short, because it blocks every other encoder call. See Threading.
  • The TMC9660 can use the same encoder. The position benches feed the AS5047U angle to the host while the TMC9660 uses its own ABN input; decide which side owns the feedback before you close a loop on it.