diff --git a/components/as5600/include/as5600.hpp b/components/as5600/include/as5600.hpp index d43919274..ba74de4a5 100644 --- a/components/as5600/include/as5600.hpp +++ b/components/as5600/include/as5600.hpp @@ -4,6 +4,7 @@ #include #include +#include "esp_timer.h" #include "base_peripheral.hpp" #include "task.hpp" @@ -40,9 +41,9 @@ class As5600 : public BasePeripheral<> { typedef std::function velocity_filter_fn; static constexpr int COUNTS_PER_REVOLUTION = - 16384; ///< Int number of counts per revolution for the magnetic encoder. + 4096; ///< Int number of counts per revolution for the magnetic encoder (12-bit). static constexpr float COUNTS_PER_REVOLUTION_F = - 16384.0f; ///< Float number of counts per revolution for the magnetic encoder. + 4096.0f; ///< Float number of counts per revolution for the magnetic encoder (12-bit). static constexpr float COUNTS_TO_RADIANS = 2.0f * (float)(M_PI) / COUNTS_PER_REVOLUTION_F; ///< Conversion factor to convert from count value to radians. @@ -162,32 +163,43 @@ class As5600 : public BasePeripheral<> { int read_count(std::error_code &ec) { logger_.info("read_count"); std::lock_guard lock(base_mutex_); - // read the angle count registers + // read the angle count registers (12-bit value: 0-4095) uint8_t angle_h = read_u8_from_register((uint8_t)Registers::ANGLE_H, ec); if (ec) { return 0; } - uint8_t angle_l = read_u8_from_register((uint8_t)Registers::ANGLE_L, ec) >> 2; + uint8_t angle_l = read_u8_from_register((uint8_t)Registers::ANGLE_L, ec); if (ec) { return 0; } - return (int)((angle_h << 6) | angle_l); + // Combine the high byte (bits 11-4) and low byte (bits 3-0) + // ANGLE_H contains bits [11:8] in the lower nibble + // ANGLE_L contains bits [7:0] + return (int)(((angle_h & 0x0F) << 8) | angle_l); } void update(std::error_code &ec) { logger_.info("update"); std::lock_guard lock(base_mutex_); + // update velocity (filtering it) (use member variable instead of static) + uint64_t now_us = esp_timer_get_time(); + uint64_t dt = now_us - prev_time_us_; + float seconds = dt / 1e6f; + prev_time_us_ = now_us; + + if (seconds == 0.0f) { + seconds = update_period_.count(); + } // update raw count auto count = read_count(ec); if (ec) { return; } count_.store(count); - static int prev_count = count_; - // compute diff - int diff = count_ - prev_count; + // compute diff (use member variable instead of static to support multiple instances) + int diff = count_ - prev_count_; // update prev_count - prev_count = count_; + prev_count_ = count_; // check for zero crossing if (diff > COUNTS_PER_REVOLUTION / 2) { // we crossed zero going clockwise (1 -> 359) @@ -199,12 +211,7 @@ class As5600 : public BasePeripheral<> { // update accumulator accumulator_ += diff; logger_.debug("CDA: {}, {}, {}", count_, diff, accumulator_); - // update velocity (filtering it) - static auto prev_time = std::chrono::high_resolution_clock::now(); - auto now = std::chrono::high_resolution_clock::now(); - float elapsed = std::chrono::duration(now - prev_time).count(); - prev_time = now; - float seconds = elapsed ? elapsed : update_period_.count(); + float raw_velocity = (float)(diff) / COUNTS_PER_REVOLUTION_F / seconds * SECONDS_PER_MINUTE; velocity_rpm_ = velocity_filter_ ? velocity_filter_(raw_velocity) : raw_velocity; static float max_velocity = 0.5f / update_period_.count() * SECONDS_PER_MINUTE; @@ -298,5 +305,8 @@ class As5600 : public BasePeripheral<> { std::atomic accumulator_{0}; std::atomic velocity_rpm_{0}; std::unique_ptr task_; + // Instance-specific variables (not static) to support multiple AS5600 sensors + int prev_count_{0}; + uint64_t prev_time_us_{0}; }; } // namespace espp