diff --git a/Firmware/MotorControl/encoder.cpp b/Firmware/MotorControl/encoder.cpp index b861b28f..7bdddb0d 100644 --- a/Firmware/MotorControl/encoder.cpp +++ b/Firmware/MotorControl/encoder.cpp @@ -22,7 +22,9 @@ bool Encoder::apply_config(ODriveIntf::MotorIntf::MotorType motor_type) { update_pll_gains(); if (config_.pre_calibrated) { - if (config_.mode == Encoder::MODE_HALL || config_.mode == Encoder::MODE_SINCOS) + if (config_.mode == Encoder::MODE_HALL && config_.hall_calibrated) + is_ready_ = true; + if (config_.mode == Encoder::MODE_SINCOS) is_ready_ = true; if (motor_type == Motor::MOTOR_TYPE_ACIM) is_ready_ = true; @@ -213,7 +215,7 @@ bool Encoder::run_hall_calibration() { }; states_seen_count_.fill(0); - hall_calibrated_ = false; + config_.hall_calibrated = false; bool success = axis_->run_lockin_spin(lockin_config, false, loop_cb); sample_hall_states_ = false; @@ -266,6 +268,11 @@ bool Encoder::run_offset_calibration() { return false; } + if (config_.mode == MODE_HALL && !config_.hall_calibrated) { + set_error(ERROR_HALL_NOT_CALIBRATED_YET); + return false; + } + // We use shadow_count_ to do the calibration, but the offset is used by count_in_cpr_ // Therefore we have to sync them for calibration shadow_count_ = count_in_cpr_; @@ -559,7 +566,7 @@ bool Encoder::update() { if (sample_hall_states_) { states_seen_count_[hall_state_]++; } - if (hall_calibrated_) { + if (config_.hall_calibrated) { int32_t hall_cnt; if (decode_hall((hall_state_ ^ config_.hall_polarity), &hall_cnt)) { delta_enc = hall_cnt - count_in_cpr_; diff --git a/Firmware/MotorControl/encoder.hpp b/Firmware/MotorControl/encoder.hpp index 71542649..5d3d8348 100644 --- a/Firmware/MotorControl/encoder.hpp +++ b/Firmware/MotorControl/encoder.hpp @@ -32,7 +32,8 @@ public: float bandwidth = 1000.0f; bool find_idx_on_lockin_only = false; // Only be sensitive during lockin scan constant vel state bool ignore_illegal_hall_state = false; // dont error on bad states like 000 or 111 - uint8_t hall_polarity; + uint8_t hall_polarity = 0; + bool hall_calibrated = false; uint16_t abs_spi_cs_gpio_pin = 1; uint16_t sincos_gpio_pin_sin = 3; uint16_t sincos_gpio_pin_cos = 4; @@ -113,7 +114,6 @@ public: // Updated by low_level pwm_adc_cb uint8_t hall_state_ = 0x0; // bit[0] = HallA, .., bit[2] = HallC bool sample_hall_states_ = false; - bool hall_calibrated_ = false; std::array states_seen_count_; // for hall polarity calibration float sincos_sample_s_ = 0.0f; diff --git a/Firmware/odrive-interface.yaml b/Firmware/odrive-interface.yaml index 6de402ef..0f8d3d14 100644 --- a/Firmware/odrive-interface.yaml +++ b/Firmware/odrive-interface.yaml @@ -980,7 +980,6 @@ interfaces: calib_scan_response: readonly float32 pos_abs: int32 spi_error_rate: readonly float32 - hall_calibrated: readonly bool config: c_is_class: False attributes: @@ -1000,6 +999,8 @@ interfaces: calib_scan_distance: float32 calib_scan_omega: float32 ignore_illegal_hall_state: bool + hall_polarity: uint8 + hall_calibrated: bool sincos_gpio_pin_sin: type: uint16 doc: Analog sine signal of a sin/cos encoder. The corresponding GPIO must be in `GPIO_MODE_ANALOG_IN`.