From 29ac0650e48b25ed3f006ad9f55d5313e921162e Mon Sep 17 00:00:00 2001 From: HengZhang <841636454@qq.com> Date: Mon, 21 Oct 2024 00:00:00 +0800 Subject: [PATCH] Add latch functionality for stepper motor control This commit introduces the latch functionality for stepper motors in the Zephyr motor driver framework. The latch feature allows the motor to hold its position after completing a movement, which is useful in applications that require precise position control without losing steps due to external forces. Changes include: - Added the `stepper_set_latch()` function to configure whether the motor should latch (hold position) after movement. - Added the `stepper_is_latch()` function to check the current latch configuration. - Updated the stepper driver API to support latch control. This functionality helps maintain the motor's position after movement, preventing unwanted drift when the motor is not in active movement. However, latching consumes more power as it keeps current flowing through the motor windings. --- drivers/stepper/gpio_stepper_controller.c | 22 +++++++++++ include/zephyr/drivers/stepper.h | 48 +++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/drivers/stepper/gpio_stepper_controller.c b/drivers/stepper/gpio_stepper_controller.c index a26f9c0a8a788..7a1aa1c6f4bda 100644 --- a/drivers/stepper/gpio_stepper_controller.c +++ b/drivers/stepper/gpio_stepper_controller.c @@ -39,6 +39,7 @@ struct gpio_stepper_data { uint32_t delay_in_us; int32_t step_count; void *event_cb_user_data; + bool latch; }; static int stepper_motor_set_coil_charge(const struct device *dev) @@ -108,6 +109,11 @@ static void position_mode_task(const struct device *dev) update_coil_charge(dev); } update_remaining_steps(dev->data); + if (data -> step_count == 0 && !data->latch) { + for (uint8_t n_pin = 0; n_pin < NUM_CONTROL_PINS; n_pin++) { + (void)gpio_pin_set_dt(&config->control_pins[n_pin], 0); + } + } } static void velocity_mode_task(const struct device *dev) @@ -296,6 +302,20 @@ static int gpio_stepper_enable(const struct device *dev, bool enable) return 0; } +static int gpio_stepper_set_latch(const struct device *dev, bool is_latch_after_movement) +{ + struct gpio_stepper_data *data = dev->data; + data->latch = is_latch_after_movement; + return 0; +} + +static int gpio_stepper_is_latch(const struct device *dev, bool* latching_state) +{ + struct gpio_stepper_data *data = dev->data; + *latching_state = data->latch; + return 0; +} + static int gpio_stepper_motor_controller_init(const struct device *dev) { struct gpio_stepper_data *data = dev->data; @@ -340,6 +360,8 @@ static int gpio_stepper_motor_controller_init(const struct device *dev) .enable_constant_velocity_mode = gpio_stepper_enable_constant_velocity_mode, \ .set_micro_step_res = gpio_stepper_set_micro_step_res, \ .get_micro_step_res = gpio_stepper_get_micro_step_res, \ + .set_latch = gpio_stepper_set_latch, \ + .is_latch = gpio_stepper_is_latch, \ .set_event_callback = gpio_stepper_set_event_callback, }; #define GPIO_STEPPER_DEVICE_DEFINE(child) \ diff --git a/include/zephyr/drivers/stepper.h b/include/zephyr/drivers/stepper.h index 5ce2c835745af..8caa570d9ac40 100644 --- a/include/zephyr/drivers/stepper.h +++ b/include/zephyr/drivers/stepper.h @@ -184,6 +184,22 @@ typedef void (*stepper_event_callback_t)(const struct device *dev, const enum st typedef int (*stepper_set_event_callback_t)(const struct device *dev, stepper_event_callback_t callback, void *user_data); +/** + * @brief Set the stepper latch after movement. + * + * @see stepper_set_latch() for details. + */ +typedef int (*stepper_set_latch_t)(const struct device *dev, + const bool is_latch_after_movement); + + +/** + * @brief Get the stepper latch state. + * + * @see stepper_is_latch() for details. + */ +typedef int (*stepper_is_latch_t)(const struct device *dev, bool* is_latch_after_movement); + /** * @brief Stepper Motor Controller API */ @@ -199,6 +215,8 @@ __subsystem struct stepper_driver_api { stepper_is_moving_t is_moving; stepper_enable_constant_velocity_mode_t enable_constant_velocity_mode; stepper_set_event_callback_t set_event_callback; + stepper_set_latch_t set_latch; + stepper_is_latch_t is_latch; }; /** @@ -462,6 +480,36 @@ static inline int z_impl_stepper_set_callback(const struct device *dev, return api->set_event_callback(dev, callback, user_data); } +/** + * @brief Set whether the stepper motor should latch after movement. + * + * @param dev Pointer to the device structure for the stepper motor. + * @param is_latch_after_movement Boolean indicating whether the motor should latch after movement. + * @retval -EIO General input / output error + * @retval 0 Success + */ +__syscall int stepper_set_latch(const struct device *dev, bool is_latch_after_movement); + +static inline int z_impl_stepper_set_latch(const struct device *dev, bool is_latch_after_movement) { + const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api; + return api->set_latch(dev, is_latch_after_movement); +} + +/** + * @brief Get the current latch configuration of the stepper motor. + * + * @param dev Pointer to the device structure for the stepper motor. + * @param latching_state Pointer to a boolean where the latch state will be stored. + * @retval -EIO General input / output error + * @retval 0 Success + */ +__syscall int stepper_is_latch(const struct device *dev, bool* latching_state); + +static inline int z_impl_stepper_is_latch(const struct device *dev, bool* latching_state) { + const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api; + return api->is_latch(dev, latching_state); +} + /** * @} */