diff --git a/Firmware/MotorControl/axis.cpp b/Firmware/MotorControl/axis.cpp index 43ee9ce2..2136ebcb 100644 --- a/Firmware/MotorControl/axis.cpp +++ b/Firmware/MotorControl/axis.cpp @@ -135,47 +135,55 @@ float Axis::get_temp() { bool Axis::run_lockin_spin() { // Spiral up current for softer rotor lock-in float x = 0.0f; - run_control_loop([&](){ + run_control_loop([&]() { float phase = wrap_pm_pi(config_.lockin_ramp_time * x); float I_mag = config_.lockin_current * x; x += current_meas_period / config_.lockin_ramp_time; if (!motor_.update(I_mag, phase)) - return error_ |= ERROR_MOTOR_FAILED, false; + return false; return x < 1.0f; }); if (error_ != ERROR_NONE) return false; - // Accelerate + // Spin states float distance = config_.lockin_ramp_time; float phase = wrap_pm_pi(distance); float vel = distance / config_.lockin_ramp_time; - bool vel_done = false; - bool dist_done = false; - run_control_loop([&](){ + + // Function of states to check if we are done + auto spin_done = [&](bool vel_override = false) -> bool { + bool done = false; + if (config_.lockin_finish_on_vel || vel_override) + done = done || vel >= config_.lockin_vel; + if (config_.lockin_finish_on_distance) + done = done || fabsf(distance) >= fabsf(config_.lockin_finish_distance); + if (config_.lockin_finish_on_enc_idx) + done = done || encoder_.index_found_; + return done; + }; + + // Accelerate + run_control_loop([&]() { vel += config_.lockin_accel * current_meas_period; distance += vel * current_meas_period; phase = wrap_pm_pi(phase + vel * current_meas_period); + if (!motor_.update(config_.lockin_current, phase)) - return error_ |= ERROR_MOTOR_FAILED, false; - vel_done = vel >= config_.lockin_vel; - dist_done = fabsf(distance) >= fabsf(config_.lockin_finish_distance); - if (config_.lockin_finish_on_distance) - return !vel_done && !dist_done; - else - return !vel_done; + return false; + return !spin_done(true); //vel_override to go to next phase }); // Constant speed - if (config_.lockin_finish_on_distance) { - vel = config_.lockin_vel; - run_control_loop([&](){ + if (!spin_done()) { + vel = config_.lockin_vel; // reset to actual specified vel to avoid small integration error + run_control_loop([&]() { distance += vel * current_meas_period; phase = wrap_pm_pi(phase + vel * current_meas_period); + if (!motor_.update(config_.lockin_current, phase)) - return error_ |= ERROR_MOTOR_FAILED, false; - dist_done = fabsf(distance) >= fabsf(config_.lockin_finish_distance); - return !dist_done; + return false; + return !spin_done(); }); } diff --git a/Firmware/MotorControl/axis.hpp b/Firmware/MotorControl/axis.hpp index 7b4c7bf2..31dc1488 100644 --- a/Firmware/MotorControl/axis.hpp +++ b/Firmware/MotorControl/axis.hpp @@ -55,7 +55,9 @@ public: float lockin_ramp_distance = 4 * M_PI; // [rad] float lockin_accel = 400.0f; // [rad/s^2] float lockin_vel = 400.0f; // [rad/s] - bool lockin_finish_on_distance = false; // false: finish on target vel + bool lockin_finish_on_vel = false; + bool lockin_finish_on_distance = false; + bool lockin_finish_on_enc_idx = false; float lockin_finish_distance = 1000.0f; // [rad] }; @@ -196,8 +198,10 @@ public: make_protocol_property("lockin_ramp_distance", &config_.lockin_ramp_distance), make_protocol_property("lockin_accel", &config_.lockin_accel), make_protocol_property("lockin_vel", &config_.lockin_vel), + make_protocol_property("lockin_finish_distance", &config_.lockin_finish_distance), + make_protocol_property("lockin_finish_on_vel", &config_.lockin_finish_on_vel), make_protocol_property("lockin_finish_on_distance", &config_.lockin_finish_on_distance), - make_protocol_property("lockin_finish_distance", &config_.lockin_finish_distance) + make_protocol_property("lockin_finish_on_enc_idx", &config_.lockin_finish_on_enc_idx) ), make_protocol_function("get_temp", *this, &Axis::get_temp), make_protocol_object("motor", motor_.make_protocol_definitions()),