Quickstart¶
Read an angle from your MCU: wire four SPI signals and the supply, write a one-method port class, call three driver functions.
1. Wire it¶
| MCU | AS5047U pin | Notes |
|---|---|---|
| SPI SCLK | 2 (CLK) | SPI mode 1 (CPOL = 0, CPHA = 1), up to 10 MHz; start at 1 MHz |
| SPI MOSI | 4 (MOSI) | The chip samples it on the falling clock edge |
| SPI MISO | 3 (MISO) | High-impedance while CSn is high |
| GPIO or hardware CS | 1 (CSn) | Active low; one frame per CSn low period |
| 3.3 V | 11 (VDD) and 12 (VDD3V3), tied | 3.3 V mode, 3.0 V to 3.6 V. For 5 V mode see Hardware |
| GND | 13 (GND) and 5 (TEST) | TEST must be grounded |
Put 100 nF from VDD to GND at the pins. Center a diametrically magnetized magnet over the package; the field must be 35 mT to 70 mT at the die. The Hardware page has every pin, the timing and the 5 V wiring.
2. Add the driver¶
Add the repository as a submodule and link the hf_as5047u CMake target (or add inc/ to your include path and
build with C++20). Installation covers CMake and ESP-IDF.
3. Write the port¶
The port is the only platform code: one transfer() that sends len bytes and receives len bytes with CSn held
low, and returns false on a bus error. Replace the three platform_* calls with your SDK's.
class MySpi : public as5047u::SpiInterface<MySpi> {
public:
// One frame of 2, 3 or 4 bytes, full duplex, CSn low for the whole frame.
// SPI mode 1 (CPOL = 0, CPHA = 1), MSB first, up to 10 MHz.
// Return false on a bus error: the driver call that sent the frame then fails.
bool transfer(const uint8_t* tx, uint8_t* rx, std::size_t len) {
platform_cs_low();
const bool ok = platform_spi_exchange(tx, rx, len);
platform_cs_high(); // the chip executes the frame here; >= 350 ns high
return ok;
}
};
Porting explains the contract and points to the ESP-IDF port the examples use.
4. Read the angle¶
#include "as5047u.hpp"
#include <cstdio>
int print_angle(MySpi& spi) {
as5047u::AS5047U<MySpi> encoder(spi, FrameFormat::SPI_24); // CRC on every frame
const auto dia = encoder.GetDiagnostics(); // 1. chip up, magnet in range?
if (dia.bits.LoopsFinished == 0U || dia.bits.MagHalf_flag != 0U) {
return -1; // no supply, no SPI or no magnet
}
const float degrees = encoder.GetAngleDegrees(2); // 2. angle, 2 retries on CRC
const float rpm = encoder.GetVelocityRPM(); // 3. velocity
std::printf("%.2f deg %.1f rpm AGC %u\n", degrees, rpm, encoder.GetAGC());
return 0;
}
What each step does:
- The constructor only stores the port and the frame format; it does not talk to the chip.
SPI_24puts a CRC on every frame. GetDiagnostics()reads the DIA register.LoopsFinishedis set once the chip's internal loops have settled after power-on (at most 10 ms);MagHalf_flagis set when the field is too weak.GetAngleDegrees(2)reads ANGLECOM and repeats the read up to two times if the chip reports a CRC or framing error.GetVelocityRPM()andGetAGC()read VEL and AGC.
This example is built by the host CI, so it compiles against the current headers.
If it does not work¶
| Symptom | First thing to check |
|---|---|
print_angle() returns -1, every register reads 0 |
MISO wiring, supply, CSn toggling per frame |
Every register reads 0x3FFF |
MISO floating or stuck high; SPI mode (it must be mode 1) |
MagHalf_flag set, AGC at 255 |
Magnet too far or too weak (Troubleshooting) |
| Angle jumps or does not follow the shaft | Magnet off-centre or not diametrically magnetized |
Next¶
- API guide: velocity, diagnostics, error flags, outputs, raw registers.
- Configuration: settings for commutation and for low-noise positioning.
- Examples: complete ESP32 applications.