fix various issues

- overcurrent error during motor calibration (this is caused by
overshoot. For now we just ignore the current limit during motor
calibration as we did before)
- factor 2 error at encoder calibration
- set error flag if Motor::arm() is called while the brake resistor is
enabled but disarmed.
- only arm brake resistor if enabled
- auto-arm brake resistor on clear_errors()
This commit is contained in:
Samuel Sadok
2020-11-13 18:45:49 +01:00
parent d653abfac2
commit a6587f8d8a
6 changed files with 23 additions and 9 deletions
+4 -4
View File
@@ -228,7 +228,7 @@ bool Encoder::run_offset_calibration() {
axis_->open_loop_controller_.target_voltage_ = axis_->motor_.config_.motor_type != Motor::MOTOR_TYPE_GIMBAL ? 0.0f : axis_->motor_.config_.calibration_current;
axis_->open_loop_controller_.target_vel_ = 0.0f;
axis_->open_loop_controller_.total_distance_ = 0.0f;
axis_->open_loop_controller_.phase_ = wrap_pm_pi(0 - config_.calib_scan_distance / 2.0f);
axis_->open_loop_controller_.phase_ = axis_->open_loop_controller_.initial_phase_ = wrap_pm_pi(0 - config_.calib_scan_distance / 2.0f);
axis_->motor_.current_control_.enable_current_control_src_ = (axis_->motor_.config_.motor_type != Motor::MOTOR_TYPE_GIMBAL);
axis_->motor_.current_control_.Idq_setpoint_src_.connect_to(&axis_->open_loop_controller_.Idq_setpoint_);
@@ -324,9 +324,9 @@ bool Encoder::run_offset_calibration() {
axis_->motor_.disarm();
config_.phase_offset = encvaluesum / (num_steps * 2);
int32_t residual = encvaluesum - ((int64_t)config_.phase_offset * (int64_t)(num_steps * 2));
config_.phase_offset_float = (float)residual / (float)(num_steps * 2) + 0.5f; // add 0.5 to center-align state to phase
config_.phase_offset = encvaluesum / num_steps;
int32_t residual = encvaluesum - ((int64_t)config_.phase_offset * (int64_t)num_steps);
config_.phase_offset_float = (float)residual / (float)num_steps + 0.5f; // add 0.5 to center-align state to phase
is_ready_ = true;
return true;
+6 -1
View File
@@ -76,6 +76,9 @@ bool brake_resistor_saturated = false;
// @brief Arms the brake resistor
void safety_critical_arm_brake_resistor() {
CRITICAL_SECTION() {
for (size_t i = 0; i < AXIS_COUNT; ++i) {
axes[i].motor_.I_bus_ = 0.0f;
}
brake_resistor_armed = true;
htim2.Instance->CCR3 = 0;
htim2.Instance->CCR4 = TIM_APB1_PERIOD_CLOCKS + 1;
@@ -164,7 +167,9 @@ void start_adc_pwm() {
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);
safety_critical_arm_brake_resistor();
if (odrv.config_.enable_brake_resistor) {
safety_critical_arm_brake_resistor();
}
}
// @brief ADC1 measurements are written to this buffer by DMA
+3
View File
@@ -161,6 +161,9 @@ void ODrive::clear_errors() {
axis.error_ = Axis::ERROR_NONE;
}
error_ = ERROR_NONE;
if (odrv.config_.enable_brake_resistor) {
safety_critical_arm_brake_resistor();
}
}
extern "C" {
+8 -3
View File
@@ -198,8 +198,10 @@ bool Motor::arm(PhaseControlLaw<3>* control_law) {
control_law_->reset();
}
if (brake_resistor_armed) {
if (!odrv.config_.enable_brake_resistor || brake_resistor_armed) {
is_armed_ = true;
} else {
error_ |= Motor::ERROR_BRAKE_RESISTOR_DISARMED;
}
}
@@ -217,7 +219,7 @@ bool Motor::arm(PhaseControlLaw<3>* control_law) {
*/
void Motor::apply_pwm_timings(uint16_t timings[3], bool tentative) {
CRITICAL_SECTION() {
if (!brake_resistor_armed) {
if (odrv.config_.enable_brake_resistor && !brake_resistor_armed) {
disarm_with_error(ERROR_BRAKE_RESISTOR_DISARMED);
}
@@ -609,7 +611,10 @@ void Motor::current_meas_cb(uint32_t timestamp, std::optional<Iph_ABC_t> current
float Inorm_sq = 2.0f / 3.0f * (SQ(current_meas_->phA)
+ SQ(current_meas_->phB)
+ SQ(current_meas_->phC));
if (Inorm_sq > SQ(Itrip)) {
// Hack: we disable the current check during motor calibration because
// it tends to briefly overshoot when the motor moves to align flux with I_alpha
if (Inorm_sq > SQ(Itrip) && (axis_->current_state_ != Axis::AXIS_STATE_MOTOR_CALIBRATION)) {
disarm_with_error(ERROR_CURRENT_LIMIT_VIOLATION);
}
} else if (is_armed_) {
@@ -5,7 +5,7 @@
void OpenLoopController::update(uint32_t timestamp) {
auto [prev_Id, prev_Iq] = Idq_setpoint_.get_previous().value_or(float2D{0.0f, 0.0f});
auto [prev_Vd, prev_Vq] = Vdq_setpoint_.get_previous().value_or(float2D{0.0f, 0.0f});
float phase = phase_.get_previous().value_or(0.0f);
float phase = phase_.get_previous().value_or(initial_phase_);
float phase_vel = phase_vel_.get_previous().value_or(0.0f);
(void)prev_Iq; // unused
@@ -18,6 +18,7 @@ public:
float target_vel_ = 0.0f;
float target_current_ = 0.0f;
float target_voltage_ = 0.0f;
float initial_phase_ = 0.0f;
// State/Outputs
uint32_t timestamp_ = 0;