#ifndef __AXIS_HPP #define __AXIS_HPP #ifndef __ODRIVE_MAIN_H #error "This file should not be included directly. Include odrive_main.h instead." #endif // Warning: Do not reorder these enum values. // The state machine uses ">" comparision on them. enum AxisState_t { AXIS_STATE_UNDEFINED = 0, // void run_control_loop(const T& update_handler) { while (requested_state_ == AXIS_STATE_UNDEFINED) { // look for errors at axis level and also all subcomponents bool checks_ok = do_checks(); // Update all estimators // Note: updates run even if checks fail bool updates_ok = do_updates(); if (!checks_ok || !updates_ok) break; // Run main loop function, defer quitting for after wait // TODO: change arming logic to arm after waiting bool main_continue = update_handler(); // Check we meet deadlines after queueing ++loop_counter_; // Wait until the current measurement interrupt fires if (!wait_for_current_meas()) { // maybe the interrupt handler is dead, let's be // safe and float the phases safety_critical_disarm_motor_pwm(motor_); update_brake_current(); error_ |= ERROR_CURRENT_MEASUREMENT_TIMEOUT; break; } if (!main_continue) break; } } bool run_sensorless_spin_up(); bool run_sensorless_control_loop(); bool run_closed_loop_control_loop(); bool run_idle_loop(); void run_state_machine_loop(); const AxisHardwareConfig_t& hw_config_; AxisConfig_t& config_; Encoder& encoder_; SensorlessEstimator& sensorless_estimator_; Controller& controller_; Motor& motor_; TrapezoidalTrajectory& trap_; osThreadId thread_id_; volatile bool thread_id_valid_ = false; // variables exposed on protocol Error_t error_ = ERROR_NONE; bool enable_step_dir_ = false; // auto enabled after calibration, based on config.enable_step_dir AxisState_t requested_state_ = AXIS_STATE_STARTUP_SEQUENCE; AxisState_t task_chain_[10] = { AXIS_STATE_UNDEFINED }; AxisState_t& current_state_ = task_chain_[0]; uint32_t loop_counter_ = 0; // Communication protocol definitions auto make_protocol_definitions() { return make_protocol_member_list( make_protocol_property("error", &error_), make_protocol_property("enable_step_dir", &enable_step_dir_), make_protocol_ro_property("current_state", ¤t_state_), make_protocol_property("requested_state", &requested_state_), make_protocol_ro_property("loop_counter", &loop_counter_), make_protocol_object("config", make_protocol_property("startup_motor_calibration", &config_.startup_motor_calibration), make_protocol_property("startup_encoder_index_search", &config_.startup_encoder_index_search), make_protocol_property("startup_encoder_offset_calibration", &config_.startup_encoder_offset_calibration), make_protocol_property("startup_closed_loop_control", &config_.startup_closed_loop_control), make_protocol_property("startup_sensorless_control", &config_.startup_sensorless_control), make_protocol_property("enable_step_dir", &config_.enable_step_dir), make_protocol_property("counts_per_step", &config_.counts_per_step), make_protocol_property("ramp_up_time", &config_.ramp_up_time), make_protocol_property("ramp_up_distance", &config_.ramp_up_distance), make_protocol_property("spin_up_current", &config_.spin_up_current), make_protocol_property("spin_up_acceleration", &config_.spin_up_acceleration), make_protocol_property("spin_up_target_vel", &config_.spin_up_target_vel) ), make_protocol_function("get_temp", *this, &Axis::get_temp), make_protocol_object("motor", motor_.make_protocol_definitions()), make_protocol_object("controller", controller_.make_protocol_definitions()), make_protocol_object("encoder", encoder_.make_protocol_definitions()), make_protocol_object("sensorless_estimator", sensorless_estimator_.make_protocol_definitions()), make_protocol_object("trap_traj", trap_.make_protocol_definitions()) ); } }; DEFINE_ENUM_FLAG_OPERATORS(Axis::Error_t) #endif /* __AXIS_HPP */