HF-AS5047U Driver  0.1.0-dev
HF-AS5047U C++ Driver
Loading...
Searching...
No Matches
as5047u.hpp
Go to the documentation of this file.
1
6#pragma once
9#include "as5047u_version.h"
10#include <algorithm>
11#include <array>
12#include <atomic>
13#include <bitset>
14#include <cmath> // for M_PI and math functions
15#include <cstdint>
16#include <cstdio> // for printf
17#include <functional> // for std::function
18#include <utility> // for std::pair
19
20// Error flags from ERRFL register
21enum class AS5047U_Error : uint16_t {
22 None = 0,
23 AgcWarning = 1 << 0,
24 MagHalf = 1 << 1,
25 P2ramWarning = 1 << 2,
26 P2ramError = 1 << 3,
27 FramingError = 1 << 4,
28 CommandError = 1 << 5,
29 CrcError = 1 << 6,
30 WatchdogError = 1 << 7,
31 OffCompError = 1 << 9,
32 CordicOverflow = 1 << 10
33};
34
35// -----------------------------------------------------------------------------
36// Type definitions
37// -----------------------------------------------------------------------------
38#include "as5047u_types.hpp" // For FrameFormat enum
39
40// -----------------------------------------------------------------------------
41// Default configuration values
42// -----------------------------------------------------------------------------
43#include "as5047u_config.hpp" // defines AS5047U_CFG namespace with defaults
44
45// -----------------------------------------------------------------------------
46// as5047u Namespace
47// -----------------------------------------------------------------------------
48namespace as5047u {
49
51enum class AngleUnit : uint8_t {
52 Lsb,
53 Degrees,
55};
56
58enum class VelocityUnit : uint8_t {
59 Lsb,
62 Rpm
63};
64
82template <typename SpiType>
83class AS5047U {
84public:
85 //------------------------------------------------------------------
86 // Constructor and destructor
87 //------------------------------------------------------------------
88
95 explicit AS5047U(SpiType& bus, FrameFormat format = AS5047U_CFG::DEFAULT_FRAME_FORMAT) noexcept;
96
97 ~AS5047U() = default;
98
100 static constexpr uint8_t ComputeCRC8(uint16_t data16) {
101 uint8_t crc = 0xC4;
102 for (int i = 0; i < 16; ++i) {
103 bool bit = ((data16 >> (15 - i)) & 1) ^ ((crc >> 7) & 1);
104 crc = (crc << 1) ^ (bit ? 0x1D : 0x00);
105 }
106 return crc ^ 0xFF;
107 }
108
109 //------------------------------------------------------------------
110 // High-level API
111 //------------------------------------------------------------------
116 void SetFrameFormat(FrameFormat format) noexcept;
117
125 [[nodiscard]] uint16_t GetAngle(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
126
132 [[nodiscard]] float GetAngle(AngleUnit unit,
133 uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
134
139 [[nodiscard]] float GetAngleDegrees(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
140
145 [[nodiscard]] float GetAngleRadians(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
146
154 [[nodiscard]] uint16_t GetRawAngle(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
155
162 [[nodiscard]] int16_t GetVelocity(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
163
169 [[nodiscard]] float GetVelocity(VelocityUnit unit,
170 uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
171
173 struct Angle {
174 static constexpr float DEG_PER_LSB = 360.0F / 16384.0F;
175 static constexpr float RAD_PER_LSB = (2.0F * static_cast<float>(M_PI)) / 16384.0F;
176
177 static constexpr uint16_t DegreesToLsb(float degrees) noexcept {
178 return static_cast<uint16_t>((degrees * 16384.0F) / 360.0F) & 0x3FFF;
179 }
180
181 static constexpr uint16_t RadiansToLsb(float radians) noexcept {
182 return static_cast<uint16_t>((radians * 16384.0F) / (2.0F * static_cast<float>(M_PI))) & 0x3FFF;
183 }
184 };
185
187 struct Velocity {
188 static constexpr float DEG_PER_LSB = 24.141F;
189 static constexpr float RAD_PER_LSB = DEG_PER_LSB * M_PI / 180.0F;
190 static constexpr float RPM_PER_LSB = DEG_PER_LSB * (60.0F / 360.0F);
191 };
192
197 [[nodiscard]] float GetVelocityDegPerSec(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
202 [[nodiscard]] float GetVelocityRadPerSec(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
207 [[nodiscard]] float GetVelocityRPM(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
208
215 [[nodiscard]] uint8_t GetAGC(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
216
223 [[nodiscard]] uint16_t GetMagnitude(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
224
231 [[nodiscard]] uint16_t GetErrorFlags(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
232
236 void DumpStatus() const;
237
244 [[nodiscard]] uint16_t GetZeroPosition(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
245
250 bool SetZeroPosition(uint16_t angle_lsb, uint8_t retries = AS5047U_CFG::CRC_RETRIES);
251
263 bool SetDirection(bool clockwise, uint8_t retries = AS5047U_CFG::CRC_RETRIES);
264
269 bool SetABIResolution(uint8_t resolution_bits, uint8_t retries = AS5047U_CFG::CRC_RETRIES);
270
275 bool SetUVWPolePairs(uint8_t pairs, uint8_t retries = AS5047U_CFG::CRC_RETRIES);
276
281 bool SetIndexPulseLength(uint8_t lsb_len, uint8_t retries = AS5047U_CFG::CRC_RETRIES);
282
302 bool ConfigureInterface(bool abi, bool uvw, bool pwm, uint8_t retries = AS5047U_CFG::CRC_RETRIES);
303
305 bool SetDynamicAngleCompensation(bool enable, uint8_t retries = AS5047U_CFG::CRC_RETRIES);
306
308 bool SetAdaptiveFilter(bool enable, uint8_t retries = AS5047U_CFG::CRC_RETRIES);
309
316 bool SetFilterPreset(FilterPreset preset,
317 uint8_t retries = AS5047U_CFG::CRC_RETRIES);
318
326 bool SetFilterParameters(uint8_t k_min, uint8_t k_max,
327 uint8_t retries = AS5047U_CFG::CRC_RETRIES);
328
330 [[nodiscard]] bool GetAdaptiveFilterEnabled(uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
331
333 [[nodiscard]] std::pair<uint8_t, uint8_t> GetFilterParameters(
334 uint8_t retries = AS5047U_CFG::CRC_RETRIES) const;
335
344 bool Set150CTemperatureMode(bool enable, uint8_t retries = AS5047U_CFG::CRC_RETRIES);
345
363 bool ProgramOTP();
364
373 void SetPad(uint8_t pad) noexcept;
374
387 uint8_t retries = AS5047U_CFG::CRC_RETRIES);
388
394
405 uint8_t retries = AS5047U_CFG::CRC_RETRIES);
406
412
419
431 template <typename RegT>
432 RegT ReadReg() const {
433 return decode<RegT>(readRegister(RegT::ADDRESS));
434 }
435
446 template <typename RegT>
447 bool WriteReg(const RegT& reg, uint8_t retries = AS5047U_CFG::CRC_RETRIES) {
448 return writeRegister(RegT::ADDRESS, encode(reg), retries);
449 }
450
456
457 // ===========================================================================
458 // Driver Version
459 // ===========================================================================
460
465 static constexpr const char* GetDriverVersion() noexcept {
466 return HF_AS5047U_VERSION_STRING;
467 }
468
470 static constexpr uint8_t GetDriverVersionMajor() noexcept {
471 return HF_AS5047U_VERSION_MAJOR;
472 }
473
475 static constexpr uint8_t GetDriverVersionMinor() noexcept {
476 return HF_AS5047U_VERSION_MINOR;
477 }
478
480 static constexpr uint8_t GetDriverVersionPatch() noexcept {
481 return HF_AS5047U_VERSION_PATCH;
482 }
483
484private:
485 //------------------------------------------------------------------
486 // Low-level helpers
487 //------------------------------------------------------------------
488 // Low level register access helpers
489 uint16_t rawReadRegister(uint16_t addr) const;
490 uint16_t readRegister(uint16_t addr) const;
491 bool writeRegister(uint16_t addr, uint16_t val, uint8_t retries) const;
492
493 SpiType& spi_;
494 FrameFormat frame_format_;
495 uint8_t pad_byte_{0};
496
497 mutable std::atomic<uint16_t> sticky_errors_{0};
498 void updateStickyErrors(uint16_t err_fl) const;
499
500 // Helper functions implemented inline for templates
501 template <typename RegT>
502 static constexpr uint16_t encode(const RegT& r) {
503 return r.value;
504 }
505
506 template <typename RegT>
507 static constexpr RegT decode(uint16_t raw) {
508 RegT r{};
509 r.value = raw;
510 return r;
511 }
512};
513
514// Template member function definitions must be in header
515template <typename SpiType>
516AS5047U<SpiType>::AS5047U(SpiType& bus, FrameFormat format) noexcept
517 : spi_(bus), frame_format_(format) {
518 // No further initialization (use sensor defaults unless configured).
519}
520
521template <typename SpiType>
522inline bool AS5047U<SpiType>::SetDirection(bool clockwise, uint8_t retries) {
523 auto s2 = ReadReg<AS5047U_REG::SETTINGS2>();
524 s2.bits.DIR = clockwise ? 0 : 1;
525 return WriteReg(s2, retries);
526}
527
528// Public API: Get driver version string
529inline const char* GetDriverVersion() noexcept {
530 return HF_AS5047U_VERSION_STRING;
531}
532
533} // namespace as5047u
534
535// Include template implementation
536#define AS5047U_HEADER_INCLUDED
537// NOLINTNEXTLINE(bugprone-suspicious-include) - Intentional: template implementation file
538#include "../src/as5047u.ipp"
539#undef AS5047U_HEADER_INCLUDED
AS5047U_Error
Definition as5047u.hpp:21
@ CommandError
Invalid SPI command received.
@ P2ramWarning
ECC corrected 1 bit in P2RAM customer area.
@ OffCompError
Internal offset compensation not finished.
@ P2ramError
ECC detected 2+ uncorrectable errors in P2RAM.
@ AgcWarning
AGC reached minimum (0) or maximum (255) value.
@ FramingError
SPI framing error.
@ WatchdogError
Internal oscillator or watchdog not working proper.
@ CrcError
CRC error during SPI communication.
@ MagHalf
Magnetic field is half of regulated value (AGC=255)
@ CordicOverflow
CORDIC algorithm overflow.
Template implementation of AS5047U driver methods.
Compile-time configuration options for the AS5047U driver.
Register definitions for the AS5047U Rotary Position Sensor.
CRTP-based SPI bus interface for AS5047U driver.
Type definitions for the AS5047U driver.
FilterPreset
Presets for the adaptive velocity/angle filter (Dynamic Filter System).
Definition as5047u_types.hpp:26
FrameFormat
Supported SPI frame formats for AS5047U communication.
Definition as5047u_types.hpp:12
AS5047U magnetic rotary sensor driver class.
Definition as5047u.hpp:83
float GetVelocityDegPerSec(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Get rotational velocity in degrees per second.
Definition as5047u.ipp:124
bool SetAdaptiveFilter(bool enable, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Enable/disable the adaptive filter (Dynamic Filter System).
Definition as5047u.ipp:280
~AS5047U()=default
uint16_t GetRawAngle(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Read the 14-bit absolute angle without dynamic compensation (raw angle).
Definition as5047u.ipp:77
void SetPad(uint8_t pad) noexcept
Set the daisy-chain pad byte for 32-bit SPI frames.
Definition as5047u.ipp:461
AS5047U(SpiType &bus, FrameFormat format=AS5047U_CFG::DEFAULT_FRAME_FORMAT) noexcept
Construct a new AS5047U encoder driver.
Definition as5047u.hpp:516
bool ProgramOTP()
Permanently program current settings into OTP memory.
Definition as5047u.ipp:358
AS5047U_REG::SETTINGS3::Hysteresis GetHysteresis() const
Get current incremental output hysteresis setting.
Definition as5047u.ipp:474
uint16_t GetMagnitude(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Read the current magnetic field magnitude (14-bit value).
Definition as5047u.ipp:154
uint16_t GetErrorFlags(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Read and clear error flags.
Definition as5047u.ipp:169
static constexpr uint8_t GetDriverVersionPatch() noexcept
Get the compiled driver patch version number.
Definition as5047u.hpp:480
static constexpr uint8_t GetDriverVersionMajor() noexcept
Get the compiled driver major version number.
Definition as5047u.hpp:470
static constexpr const char * GetDriverVersion() noexcept
Get the compiled driver version string.
Definition as5047u.hpp:465
bool SetDynamicAngleCompensation(bool enable, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Enable/disable Dynamic Angle Error Compensation (DAEC).
Definition as5047u.ipp:273
AS5047U_REG::SETTINGS2::AngleOutputSource GetAngleOutputSource() const
Get currently selected angle output source for 0x3FFF reads.
Definition as5047u.ipp:488
bool SetFilterPreset(FilterPreset preset, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Set adaptive filter from a preset (easiest way to configure filter).
Definition as5047u.ipp:297
uint16_t GetAngle(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Read the 14-bit absolute angle with dynamic compensation (DAEC active).
Definition as5047u.ipp:38
bool ConfigureInterface(bool abi, bool uvw, bool pwm, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Configure interface outputs (ABI, UVW) and PWM output.
Definition as5047u.ipp:254
float GetVelocityRPM(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Get rotational velocity in revolutions per minute.
Definition as5047u.ipp:134
RegT ReadReg() const
Reads data from a specified register in the AS5047U sensor.
Definition as5047u.hpp:432
void SetFrameFormat(FrameFormat format) noexcept
Set the SPI frame format (16, 24, or 32-bit).
Definition as5047u.ipp:21
bool SetABIResolution(uint8_t resolution_bits, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Set the ABI (incremental encoder) resolution.
Definition as5047u.ipp:218
bool SetDirection(bool clockwise, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Define the rotation direction for increasing angle.
Definition as5047u.hpp:522
float GetAngleDegrees(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Read absolute angle in degrees.
Definition as5047u.ipp:67
bool SetUVWPolePairs(uint8_t pairs, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Set the number of pole pairs for UVW commutation outputs.
Definition as5047u.ipp:228
uint16_t GetZeroPosition(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Get the currently configured soft zero position offset (14-bit).
Definition as5047u.ipp:181
bool WriteReg(const RegT &reg, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Writes data to a specified register in the AS5047U sensor.
Definition as5047u.hpp:447
static constexpr uint8_t GetDriverVersionMinor() noexcept
Get the compiled driver minor version number.
Definition as5047u.hpp:475
bool Set150CTemperatureMode(bool enable, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Set temperature mode for 150°C operation (NOISESET bit).
Definition as5047u.ipp:351
bool SetHysteresis(AS5047U_REG::SETTINGS3::Hysteresis hysteresis, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Set incremental output hysteresis level.
Definition as5047u.ipp:466
static constexpr uint8_t ComputeCRC8(uint16_t data16)
Definition as5047u.hpp:100
std::pair< uint8_t, uint8_t > GetFilterParameters(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Read current K_min and K_max register codes (0–7 each).
Definition as5047u.ipp:337
bool GetAdaptiveFilterEnabled(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Read whether the adaptive filter is enabled.
Definition as5047u.ipp:323
void DumpStatus() const
Dump formatted status and diagnostics using printf.
Definition as5047u.ipp:710
bool SetZeroPosition(uint16_t angle_lsb, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Set a new zero reference position (soft offset).
Definition as5047u.ipp:209
bool SetAngleOutputSource(AS5047U_REG::SETTINGS2::AngleOutputSource source, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Select which angle register (0x3FFF) is returned on reads.
Definition as5047u.ipp:480
bool SetFilterParameters(uint8_t k_min, uint8_t k_max, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Set adaptive filter parameters (K_min and K_max as 3-bit register codes).
Definition as5047u.ipp:287
int16_t GetVelocity(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Read the current rotational velocity (signed 14-bit).
Definition as5047u.ipp:92
AS5047U_Error GetStickyErrorFlags() const
Retrieve and clear the accumulated sticky error flags.
Definition as5047u.ipp:454
AS5047U_REG::DIA GetDiagnostics() const
Read the full diagnostic register (DIA).
Definition as5047u.ipp:494
float GetAngleRadians(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Read absolute angle in radians.
Definition as5047u.ipp:72
bool SetIndexPulseLength(uint8_t lsb_len, uint8_t retries=AS5047U_CFG::CRC_RETRIES)
Set the index pulse width for ABI output.
Definition as5047u.ipp:236
float GetVelocityRadPerSec(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Get rotational velocity in radians per second.
Definition as5047u.ipp:129
uint8_t GetAGC(uint8_t retries=AS5047U_CFG::CRC_RETRIES) const
Read the current Automatic Gain Control (AGC) value (0-255).
Definition as5047u.ipp:139
constexpr FrameFormat DEFAULT_FRAME_FORMAT
Definition as5047u_config.hpp:20
constexpr uint8_t CRC_RETRIES
Definition as5047u_config.hpp:26
Definition as5047u.ipp:17
VelocityUnit
Units for velocity-returning APIs.
Definition as5047u.hpp:58
const char * GetDriverVersion() noexcept
Definition as5047u.hpp:529
AngleUnit
Units for angle-returning APIs.
Definition as5047u.hpp:51
DIA – Diagnostic register (0x3FF5, read-only)
Definition as5047u_registers.hpp:180
AngleOutputSource
Angle data source for 0x3FFF output (Data_select bit)
Definition as5047u_registers.hpp:644
Hysteresis
Incremental output hysteresis (HYS) settings:
Definition as5047u_registers.hpp:714
Angle conversion helpers.
Definition as5047u.hpp:173
static constexpr uint16_t RadiansToLsb(float radians) noexcept
Definition as5047u.hpp:181
static constexpr float RAD_PER_LSB
Definition as5047u.hpp:175
static constexpr uint16_t DegreesToLsb(float degrees) noexcept
Definition as5047u.hpp:177
static constexpr float DEG_PER_LSB
Definition as5047u.hpp:174
Helper constants and methods for velocity unit conversions.
Definition as5047u.hpp:187
static constexpr float RPM_PER_LSB
Definition as5047u.hpp:190
static constexpr float DEG_PER_LSB
Definition as5047u.hpp:188
static constexpr float RAD_PER_LSB
Definition as5047u.hpp:189