mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-21 07:04:10 +08:00
make step/dir pins configurable
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
# Unreleased Features
|
||||
Please add a note of your changes below this heading if you make a Pull Request.
|
||||
|
||||
## Added
|
||||
* Make step dir gpio pins configurable.
|
||||
|
||||
## Fixed
|
||||
* Would ERROR_CONTROL_DEADLINE_MISSED along with every ERROR_PHASE_RESISTANCE_OUT_OF_RANGE.
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ Axis::Axis(const AxisHardwareConfig_t& hw_config,
|
||||
controller_.axis_ = this;
|
||||
motor_.axis_ = this;
|
||||
trap_.axis_ = this;
|
||||
|
||||
decode_step_dir_pins();
|
||||
}
|
||||
|
||||
static void step_cb_wrapper(void* ctx) {
|
||||
@@ -67,24 +69,37 @@ bool Axis::wait_for_current_meas() {
|
||||
// step/direction interface
|
||||
void Axis::step_cb() {
|
||||
if (step_dir_active_) {
|
||||
GPIO_PinState dir_pin = HAL_GPIO_ReadPin(hw_config_.dir_port, hw_config_.dir_pin);
|
||||
GPIO_PinState dir_pin = HAL_GPIO_ReadPin(dir_port_, dir_pin_);
|
||||
float dir = (dir_pin == GPIO_PIN_SET) ? 1.0f : -1.0f;
|
||||
controller_.pos_setpoint_ += dir * config_.counts_per_step;
|
||||
}
|
||||
};
|
||||
|
||||
// @brief Enables or disables step/dir input
|
||||
void Axis::set_step_dir_enabled(bool enable) {
|
||||
if (enable) {
|
||||
void Axis::load_default_step_dir_pin_config(
|
||||
const AxisHardwareConfig_t& hw_config, Config_t* config) {
|
||||
config->step_gpio_pin = hw_config.step_gpio_pin;
|
||||
config->dir_gpio_pin = hw_config.dir_gpio_pin;
|
||||
}
|
||||
|
||||
void Axis::decode_step_dir_pins() {
|
||||
step_port_ = get_gpio_port_by_pin(config_.step_gpio_pin);
|
||||
step_pin_ = get_gpio_pin_by_pin(config_.step_gpio_pin);
|
||||
dir_port_ = get_gpio_port_by_pin(config_.dir_gpio_pin);
|
||||
dir_pin_ = get_gpio_pin_by_pin(config_.dir_gpio_pin);
|
||||
}
|
||||
|
||||
// @brief (de)activates step/dir input
|
||||
void Axis::set_step_dir_active(bool active) {
|
||||
if (active) {
|
||||
// Set up the direction GPIO as input
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
GPIO_InitStruct.Pin = hw_config_.dir_pin;
|
||||
GPIO_InitStruct.Pin = dir_pin_;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(hw_config_.dir_port, &GPIO_InitStruct);
|
||||
HAL_GPIO_Init(dir_port_, &GPIO_InitStruct);
|
||||
|
||||
// Subscribe to rising edges of the step GPIO
|
||||
GPIO_subscribe(hw_config_.step_port, hw_config_.step_pin, GPIO_PULLDOWN,
|
||||
GPIO_subscribe(step_port_, step_pin_, GPIO_PULLDOWN,
|
||||
step_cb_wrapper, this);
|
||||
|
||||
step_dir_active_ = true;
|
||||
@@ -92,7 +107,7 @@ void Axis::set_step_dir_enabled(bool enable) {
|
||||
step_dir_active_ = false;
|
||||
|
||||
// Unsubscribe from step GPIO
|
||||
GPIO_unsubscribe(hw_config_.step_port, hw_config_.step_pin);
|
||||
GPIO_unsubscribe(step_port_, step_pin_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +182,6 @@ bool Axis::run_sensorless_spin_up() {
|
||||
|
||||
// Note run_sensorless_control_loop and run_closed_loop_control_loop are very similar and differ only in where we get the estimate from.
|
||||
bool Axis::run_sensorless_control_loop() {
|
||||
set_step_dir_enabled(config_.enable_step_dir);
|
||||
run_control_loop([this](){
|
||||
if (controller_.config_.control_mode >= Controller::CTRL_MODE_POSITION_CONTROL)
|
||||
return error_ |= ERROR_POS_CTRL_DURING_SENSORLESS, false;
|
||||
@@ -180,12 +194,11 @@ bool Axis::run_sensorless_control_loop() {
|
||||
return false; // set_error should update axis.error_
|
||||
return true;
|
||||
});
|
||||
set_step_dir_enabled(false);
|
||||
return check_for_errors();
|
||||
}
|
||||
|
||||
bool Axis::run_closed_loop_control_loop() {
|
||||
set_step_dir_enabled(config_.enable_step_dir);
|
||||
set_step_dir_active(config_.enable_step_dir);
|
||||
run_control_loop([this](){
|
||||
// Note that all estimators are updated in the loop prefix in run_control_loop
|
||||
float current_setpoint;
|
||||
@@ -195,7 +208,7 @@ bool Axis::run_closed_loop_control_loop() {
|
||||
return false; // set_error should update axis.error_
|
||||
return true;
|
||||
});
|
||||
set_step_dir_enabled(false);
|
||||
set_step_dir_active(false);
|
||||
return check_for_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,9 +45,12 @@ public:
|
||||
bool startup_sensorless_control = false; //<! enable sensorless control after calibration/startup
|
||||
bool enable_step_dir = false; //<! enable step/dir input after calibration
|
||||
// For M0 this has no effect if enable_uart is true
|
||||
|
||||
float counts_per_step = 2.0f;
|
||||
|
||||
// Defaults loaded from hw_config in load_configuration in main.cpp
|
||||
uint16_t step_gpio_pin = 0;
|
||||
uint16_t dir_gpio_pin = 0;
|
||||
|
||||
// Spinup settings
|
||||
float ramp_up_time = 0.4f; // [s]
|
||||
float ramp_up_distance = 4 * M_PI; // [rad]
|
||||
@@ -74,7 +77,10 @@ public:
|
||||
bool wait_for_current_meas();
|
||||
|
||||
void step_cb();
|
||||
void set_step_dir_enabled(bool enable);
|
||||
void set_step_dir_active(bool enable);
|
||||
void decode_step_dir_pins();
|
||||
static void load_default_step_dir_pin_config(
|
||||
const AxisHardwareConfig_t& hw_config, Config_t* config);
|
||||
|
||||
bool check_DRV_fault();
|
||||
bool check_PSU_brownout();
|
||||
@@ -168,6 +174,13 @@ public:
|
||||
// variables exposed on protocol
|
||||
Error_t error_ = ERROR_NONE;
|
||||
bool step_dir_active_ = false; // auto enabled after calibration, based on config.enable_step_dir
|
||||
|
||||
// updated from config in constructor, and on protocol hook
|
||||
GPIO_TypeDef* step_port_;
|
||||
uint16_t step_pin_;
|
||||
GPIO_TypeDef* dir_port_;
|
||||
uint16_t dir_pin_;
|
||||
|
||||
State_t requested_state_ = AXIS_STATE_STARTUP_SEQUENCE;
|
||||
State_t task_chain_[10] = { AXIS_STATE_UNDEFINED };
|
||||
State_t& current_state_ = task_chain_[0];
|
||||
@@ -189,6 +202,10 @@ public:
|
||||
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("step_gpio_pin", &config_.step_gpio_pin,
|
||||
[](void* ctx) { static_cast<Axis*>(ctx)->decode_step_dir_pins(); }, this),
|
||||
make_protocol_property("dir_gpio_pin", &config_.dir_gpio_pin,
|
||||
[](void* ctx) { static_cast<Axis*>(ctx)->decode_step_dir_pins(); }, this),
|
||||
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),
|
||||
|
||||
@@ -21,10 +21,12 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
GPIO_TypeDef* step_port;
|
||||
uint16_t step_pin;
|
||||
GPIO_TypeDef* dir_port;
|
||||
uint16_t dir_pin;
|
||||
// GPIO_TypeDef* step_port;
|
||||
// uint16_t step_pin;
|
||||
// GPIO_TypeDef* dir_port;
|
||||
// uint16_t dir_pin;
|
||||
uint16_t step_gpio_pin;
|
||||
uint16_t dir_gpio_pin;
|
||||
size_t thermistor_adc_ch;
|
||||
osPriority thread_priority;
|
||||
} AxisHardwareConfig_t;
|
||||
@@ -74,10 +76,12 @@ const size_t thermistor_num_coeffs = sizeof(thermistor_poly_coeffs)/sizeof(therm
|
||||
const BoardHardwareConfig_t hw_configs[2] = { {
|
||||
//M0
|
||||
.axis_config = {
|
||||
.step_port = GPIO_1_GPIO_Port,
|
||||
.step_pin = GPIO_1_Pin,
|
||||
.dir_port = GPIO_2_GPIO_Port,
|
||||
.dir_pin = GPIO_2_Pin,
|
||||
// .step_port = GPIO_1_GPIO_Port,
|
||||
// .step_pin = GPIO_1_Pin,
|
||||
// .dir_port = GPIO_2_GPIO_Port,
|
||||
// .dir_pin = GPIO_2_Pin,
|
||||
.step_gpio_pin = 1,
|
||||
.dir_gpio_pin = 2,
|
||||
.thermistor_adc_ch = 15,
|
||||
.thread_priority = (osPriority)(osPriorityHigh + (osPriority)1),
|
||||
},
|
||||
@@ -111,15 +115,19 @@ const BoardHardwareConfig_t hw_configs[2] = { {
|
||||
//M1
|
||||
.axis_config = {
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 5
|
||||
.step_port = GPIO_7_GPIO_Port,
|
||||
.step_pin = GPIO_7_Pin,
|
||||
.dir_port = GPIO_8_GPIO_Port,
|
||||
.dir_pin = GPIO_8_Pin,
|
||||
// .step_port = GPIO_7_GPIO_Port,
|
||||
// .step_pin = GPIO_7_Pin,
|
||||
// .dir_port = GPIO_8_GPIO_Port,
|
||||
// .dir_pin = GPIO_8_Pin,
|
||||
.step_gpio_pin = 7,
|
||||
.dir_gpio_pin = 8,
|
||||
#else
|
||||
.step_port = GPIO_3_GPIO_Port,
|
||||
.step_pin = GPIO_3_Pin,
|
||||
.dir_port = GPIO_4_GPIO_Port,
|
||||
.dir_pin = GPIO_4_Pin,
|
||||
// .step_port = GPIO_3_GPIO_Port,
|
||||
// .step_pin = GPIO_3_Pin,
|
||||
// .dir_port = GPIO_4_GPIO_Port,
|
||||
// .dir_pin = GPIO_4_Pin,
|
||||
.step_gpio_pin = 3,
|
||||
.dir_gpio_pin = 4,
|
||||
#endif
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 3
|
||||
.thermistor_adc_ch = 4,
|
||||
|
||||
@@ -65,6 +65,8 @@ void load_configuration(void) {
|
||||
motor_configs[i] = Motor::Config_t();
|
||||
trap_configs[i] = TrapezoidalTrajectory::Config_t();
|
||||
axis_configs[i] = Axis::Config_t();
|
||||
// Default step/dir pins are different, so we need to explicitly load them
|
||||
Axis::load_default_step_dir_pin_config(hw_configs[i].axis_config, &axis_configs[i]);
|
||||
}
|
||||
} else {
|
||||
user_config_loaded_ = true;
|
||||
@@ -179,7 +181,7 @@ int odrive_main(void) {
|
||||
#if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR >= 3
|
||||
if (board_config.enable_uart) {
|
||||
axes[0]->config_.enable_step_dir = false;
|
||||
axes[0]->set_step_dir_enabled(false);
|
||||
axes[0]->set_step_dir_active(false);
|
||||
SetGPIO12toUART();
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user