Magnetic Encoder Base
The MagneticEncoderBase is the shared CRTP base class for the magnetic
angle encoders (AS5600 Magnetic Encoder and MT6701 Magnetic Encoder). It holds all of the machinery
common to those encoders:
the periodic update loop (raw-count accumulation + velocity estimation),
the position / velocity accessors (count, radians, degrees, accumulator, RPM),
and the periodic driver that calls
update()at the configured rate.
The concrete encoder supplies exactly one thing - a read() that refreshes
the raw count from the sensor - which the base invokes through static (CRTP)
dispatch, so there is no virtual-call overhead even when the update loop runs at
very high frequency (e.g. 1-2 kHz).
The periodic driver is selected at compile time (per encoder, via KConfig / menuconfig):
a
espp::HighResolutionTimer(default), which has microsecond resolution and is the right choice for sub-millisecond update periods, oran
espp::Timer, which schedules against an absolute wake-up time (drift-free and in phase - important for stable velocity / accumulator state) but is limited to the FreeRTOS tick resolution.
API Reference
Header File
Classes
-
template<typename Derived, bool UseHighResTimer, int CountsPerRevolution, int MinDiff = 2, std::integral RegisterAddressType = std::uint8_t, bool UseAddress = true>
class MagneticEncoderBase : public espp::BasePeripheral<std::uint8_t, true> CRTP base class for magnetic angle encoders (e.g. As5600, Mt6701).
This class holds all of the machinery shared by the magnetic encoders: the periodic update loop (raw-count accumulation + velocity estimation), the position / velocity accessors, and the periodic driver that calls update() at the configured rate. The concrete encoder supplies exactly one thing - a `read(std::error_code&)` that refreshes `count_` from the sensor (and any device-specific state) - which the base invokes through static (CRTP) dispatch, so there is no virtual-call overhead even when the update loop runs at very high frequency (e.g. 1-2 kHz).
The periodic driver is selected at compile time via
UseHighResTimer:`true` (default in the encoders’ Kconfig): an esp_timer-backed espp::HighResolutionTimer, which has microsecond resolution and is the right choice for sub-millisecond update periods.
`false`: an espp::Timer, which schedules against an absolute wake-up time (the k-th callback targets `start + k * period`) so it is periodic and in phase - critical for stable velocity / accumulator state - but is limited to the FreeRTOS tick resolution.
Note
There is an implicit assumption regarding the maximum velocity that can be measured (above which there will be aliasing). The fastest velocity that can be measured is `0.5 / update_period * 60` RPM, i.e. half a rotation in one update period. This also bounds the reliability of the accumulator, since it accumulates position differences every update.
Warning
You should not call update() yourself if you have configured the encoder to run its own timer (run_task = true) or if you have called start().
- Template Parameters:
Derived – The concrete encoder class (CRTP). Must provide `void read(std::error_code&)` which updates `count_`.
UseHighResTimer – If true, drive updates with HighResolutionTimer; if false, drive with espp::Timer.
CountsPerRevolution – Number of raw counts per mechanical revolution (e.g. 4096 for the 12-bit As5600, 16384 for the 14-bit Mt6701).
MinDiff – Minimum count difference required to update the velocity estimate; smaller differences are treated as zero velocity to reject noise / jitter.
RegisterAddressType – Register address type for BasePeripheral.
UseAddress – Whether the peripheral is addressed (I2C) or not (SSI).
Subclassed by espp::Mt6701< Interface >
Public Types
-
using TimerType = std::conditional_t<UseHighResTimer, espp::HighResolutionTimer, espp::Timer>
The periodic driver type selected by
UseHighResTimer.
-
typedef std::function<float(float raw)> velocity_filter_fn
Filter the input raw velocity and return it.
- Param raw:
Most recent raw velocity measured.
- Return:
Filtered velocity.
-
typedef std::function<bool(uint8_t)> probe_fn
Function to probe the peripheral
- Param address:
The address to probe
- Return:
True if the peripheral is found at the given address
Public Functions
-
inline bool needs_zero_search() const
Return whether the sensor needs to search for absolute 0 on startup.
Note
Magnetic angle encoders (using I2C / SPI) always know their absolute angle on startup, so this always returns false.
- Returns:
False.
-
inline int get_count() const
Get the most recently updated raw count value from the encoder.
Note
This value always represents the angle of the encoder modulo one rotation, meaning it only represents the range 0 to 360 degrees.
- Returns:
Raw count value in the range [0, COUNTS_PER_REVOLUTION).
-
inline int64_t get_accumulator() const
Return the accumulated count generated since initialization.
Note
This value is a raw counter value that can be +/-; divide by COUNTS_PER_REVOLUTION to convert it to revolutions. It is stored as a 64-bit value so it does not overflow during long, continuous rotation.
- Returns:
Raw accumulator value.
-
inline void reset_accumulator()
Reset the accumulator to zero.
-
inline float get_mechanical_radians() const
Return the mechanical / shaft angle of the encoder, in radians, within the range [0, 2pi].
- Returns:
Angle in radians of the encoder within the range [0, 2pi].
-
inline float get_mechanical_degrees() const
Return the mechanical / shaft angle of the encoder, in degrees, within the range [0, 360].
- Returns:
Angle in degrees of the encoder within the range [0, 360].
-
inline float get_radians() const
Return the accumulated position of the encoder, in radians.
Note
This can be any value, it is not restricted to [-2pi, 2pi].
- Returns:
Position in radians of the encoder.
-
inline float get_degrees() const
Return the accumulated position of the encoder, in degrees.
Note
This can be any value, it is not restricted to [-360, 360].
- Returns:
Position in degrees of the encoder.
-
inline float get_rpm() const
Return the filtered velocity of the encoder, in RPM.
- Returns:
Filtered velocity (revolutions / minute, RPM).
-
inline void initialize(std::error_code &ec)
Initialize the accumulator to the current position and start the update timer.
- Parameters:
ec – Error code to set if there is an error.
-
inline void initialize(bool run_task, std::error_code &ec)
Initialize the accumulator to the current position and start the update timer, if desired.
Note
If you do not start the timer, you must call update() manually.
- Parameters:
run_task – Whether to start the update timer.
ec – Error code to set if there is an error.
-
inline void update(std::error_code &ec)
Update the state of the encoder by reading the latest data from the encoder and updating the associated state.
Note
You should not call this function if you have started the encoder’s update timer (e.g. run_task = true, or you called start()).
- Parameters:
ec – Error code to set if there is an error.
-
inline bool start()
Start the update timer.
Note
This will start the timer that calls update() at the update_period.
Note
This is only useful if you previously stopped the timer or if you initialized with run_task = false.
- Returns:
True if the timer was started successfully, false otherwise.
-
inline void stop()
Stop the update timer.
Note
This will stop the timer that calls update() at the update_period.
-
inline bool probe(std::error_code &ec) const
Probe the peripheral
Note
This function is thread safe
Note
If the probe function is not set, this function will return false and set the error code to operation_not_supported
Note
This function is only available if UseAddress is true
- Parameters:
ec – The error code to set if there is an error
- Returns:
True if the peripheral is found
-
inline void set_address(uint8_t address)
Set the address of the peripheral
Note
This function is thread safe
Note
This function is only available if UseAddress is true
- Parameters:
address – The address of the peripheral
-
inline void set_probe(const probe_fn &probe)
Set the probe function
Note
This function is thread safe
Note
This should rarely be used, as the probe function is usually set in the constructor. If you need to change the probe function, consider using the set_config function instead.
Note
This function is only available if UseAddress is true
- Parameters:
probe – The probe function
-
inline void set_write(const write_fn &write)
Set the write function
Note
This function is thread safe
Note
This should rarely be used, as the write function is usually set in the constructor. If you need to change the write function, consider using the set_config function instead.
- Parameters:
write – The write function
-
inline void set_read(const read_fn &read)
Set the read function
Note
This function is thread safe
Note
This should rarely be used, as the read function is usually set in the constructor. If you need to change the read function, consider using the set_config function instead.
- Parameters:
read – The read function
-
inline void set_read_register(const read_register_fn &read_register)
Set the read register function
Note
This function is thread safe
Note
This should rarely be used, as the read register function is usually set in the constructor. If you need to change the read register function, consider using the set_config function instead.
- Parameters:
read_register – The read register function
-
inline void set_write_then_read(const write_then_read_fn &write_then_read)
Set the write then read function
Note
This function is thread safe
Note
This should rarely be used, as the write then read function is usually set in the constructor. If you need to change the write then
- Parameters:
write_then_read – The write then read function
-
inline void set_separate_write_then_read_delay(const std::chrono::milliseconds &delay)
Set the delay between the write and read operations in write_then_read
Note
This function is thread safe
Note
This should rarely be used, as the delay is usually set in the constructor. If you need to change the delay, consider using the set_config function instead.
Note
This delay is only used if the write_then_read function is not set to a custom function and the write and read functions are separate functions.
- Parameters:
delay – The delay between the write and read operations in write_then_read
-
inline void set_config(const Config &config)
Set the configuration for the peripheral
Note
This function is thread safe
Note
The configuration should normally be set in the constructor, but this function can be used to change the configuration after the peripheral has been created - for instance if the peripheral could be found on different communications buses.
- Parameters:
config – The configuration for the peripheral
-
inline void set_config(Config &&config)
Set the configuration for the peripheral
Note
This function is thread safe
Note
The configuration should normally be set in the constructor, but this function can be used to change the configuration after the peripheral has been created - for instance if the peripheral could be found on different communications buses.
- Parameters:
config – The configuration for the peripheral
-
inline const Config &config() const
Get the configuration for the peripheral
- Returns:
The configuration for the peripheral
-
inline uint8_t address() const
Get the address of the peripheral
- Returns:
The address of the peripheral
-
inline const std::string &get_name() const
Get the name of the component
Note
This is the tag of the logger
- Returns:
A const reference to the name of the component
-
inline void set_log_tag(const std::string_view &tag)
Set the tag for the logger
- Parameters:
tag – The tag to use for the logger
-
inline espp::Logger::Verbosity get_log_level() const
Get the log level for the logger
See also
See also
- Returns:
The verbosity level of the logger
-
inline void set_log_level(espp::Logger::Verbosity level)
Set the log level for the logger
See also
See also
- Parameters:
level – The verbosity level to use for the logger
-
inline void set_log_verbosity(espp::Logger::Verbosity level)
Set the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls set_log_level
- Parameters:
level – The verbosity level to use for the logger
-
inline espp::Logger::Verbosity get_log_verbosity() const
Get the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls get_log_level
- Returns:
The verbosity level of the logger
-
inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)
Set the rate limit for the logger
See also
Note
Only calls to the logger that have _rate_limit suffix will be rate limited
- Parameters:
rate_limit – The rate limit to use for the logger
Public Static Attributes
-
static constexpr int COUNTS_PER_REVOLUTION = CountsPerRevolution
Int number of counts per revolution for the magnetic encoder.
-
static constexpr float COUNTS_PER_REVOLUTION_F = (float)CountsPerRevolution
Float number of counts per revolution.
-
static constexpr float COUNTS_TO_RADIANS = 2.0f * (float)(M_PI) / COUNTS_PER_REVOLUTION_F
Conversion factor to convert from count value to radians.
-
static constexpr float COUNTS_TO_DEGREES = 360.0f / COUNTS_PER_REVOLUTION_F
Conversion factor to convert from count value to degrees.
-
static constexpr float SECONDS_PER_MINUTE = 60.0f
Conversion factor to convert from seconds to minutes.