Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Change Stepper API to use step interval #83726

Merged
merged 3 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/hardware/peripherals/stepper.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ Configure Stepper Driver
and :c:func:`stepper_get_micro_step_res`.
- Configure **reference position** in microsteps using :c:func:`stepper_set_reference_position`
and :c:func:`stepper_get_actual_position`.
- Set **max velocity** in micro-steps per second using :c:func:`stepper_set_max_velocity`
- Set **step interval** in nanoseconds between steps using :c:func:`stepper_set_microstep_interval`
- **Enable** the stepper driver using :c:func:`stepper_enable`.

Control Stepper
===============

- **Move by** +/- micro-steps also known as **relative movement** using :c:func:`stepper_move_by`.
- **Move to** a specific position also known as **absolute movement** using :c:func:`stepper_move_to`.
- Run continuously with a **constant velocity** in a specific direction until
- Run continuously with a **constant step interval** in a specific direction until
a stop is detected using :c:func:`stepper_run`.
- Check if the stepper is **moving** using :c:func:`stepper_is_moving`.
- Register an **event callback** using :c:func:`stepper_set_event_callback`.
Expand Down
7 changes: 7 additions & 0 deletions doc/releases/migration-guide-4.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,17 @@ Stepper
* Renamed the ``compatible`` from ``zephyr,gpio-steppers`` to :dtcompatible:`zephyr,gpio-stepper`.
* Renamed the ``stepper_set_actual_position`` function to :c:func:`stepper_set_reference_position`.
* Renamed the ``stepper_enable_constant_velocity_mode`` function to :c:func:`stepper_run`.
The function does not take a velocity parameter anymore. Set the desired speed using the
:c:func:`stepper_set_microstep_interval` function beforehand.
* Renamed the ``stepper_move`` function to :c:func:`stepper_move_by`.
* Renamed the ``stepper_set_target_position`` function to :c:func:`stepper_move_to`.
* Renamed the ``stepper_set_max_velocity`` function to :c:func:`stepper_set_microstep_interval`.
The function now takes the step interval in nanoseconds. This allows for a more precise control.
* Deprecating setting max velocity via :c:func:`stepper_run`.
* The :kconfig:option:`STEPPER_ADI_TMC_RAMP_GEN` is now deprecated and is replaced with the new
:kconfig:option:`STEPPER_ADI_TMC5041_RAMP_GEN` option.
* To control the velocity for :dtcompatible:`adi,tmc5041` stepper driver, use
:c:func:`tmc5041_stepper_set_max_velocity` or :c:func:`tmc5041_stepper_set_ramp`.

SPI
===
Expand Down
2 changes: 1 addition & 1 deletion drivers/stepper/adi_tmc/adi_tmc22xx_stepper_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ static DEVICE_API(stepper, tmc22xx_stepper_api) = {
.set_reference_position = step_dir_stepper_common_set_reference_position,
.get_actual_position = step_dir_stepper_common_get_actual_position,
.move_to = step_dir_stepper_common_move_to,
.set_max_velocity = step_dir_stepper_common_set_max_velocity,
.set_microstep_interval = step_dir_stepper_common_set_microstep_interval,
.run = step_dir_stepper_common_run,
.set_event_callback = step_dir_stepper_common_set_event_callback,
.set_micro_step_res = tmc22xx_stepper_set_micro_step_res,
Expand Down
21 changes: 3 additions & 18 deletions drivers/stepper/adi_tmc/adi_tmc5041_stepper_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ static int tmc5041_stepper_move_by(const struct device *dev, const int32_t micro
return 0;
}

static int tmc5041_stepper_set_max_velocity(const struct device *dev, uint32_t velocity)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not remove this function for now, I'll create a PR right after this PR is merged exposing this function from the trinamic api. This function is quite relevant for the use-cases where you do not want to set the entire ramp and just want to cut the speed by a certain fraction.

int tmc5041_stepper_set_max_velocity(const struct device *dev, uint32_t velocity)
{
const struct tmc5041_stepper_config *config = dev->config;
const struct tmc5041_config *tmc5041_config = config->controller->config;
Expand Down Expand Up @@ -477,19 +477,13 @@ static int tmc5041_stepper_move_to(const struct device *dev, const int32_t micro
return 0;
}

static int tmc5041_stepper_run(const struct device *dev, const enum stepper_direction direction,
const uint32_t velocity)
static int tmc5041_stepper_run(const struct device *dev, const enum stepper_direction direction)
{
LOG_DBG("Stepper motor controller %s run with velocity %d", dev->name, velocity);
LOG_DBG("Stepper motor controller %s run", dev->name);
const struct tmc5041_stepper_config *config = dev->config;
const struct tmc5041_config *tmc5041_config = config->controller->config;
struct tmc5041_stepper_data *data = dev->data;
const uint32_t clock_frequency = tmc5041_config->clock_frequency;
uint32_t velocity_fclk;
int err;

velocity_fclk = tmc5xxx_calculate_velocity_from_hz_to_fclk(velocity, clock_frequency);

if (config->is_sg_enabled) {
err = stallguard_enable(dev, false);
if (err != 0) {
Expand All @@ -504,10 +498,6 @@ static int tmc5041_stepper_run(const struct device *dev, const enum stepper_dire
if (err != 0) {
return -EIO;
}
err = tmc5041_write(config->controller, TMC5041_VMAX(config->index), velocity_fclk);
if (err != 0) {
return -EIO;
}
break;

case STEPPER_DIRECTION_NEGATIVE:
Expand All @@ -516,10 +506,6 @@ static int tmc5041_stepper_run(const struct device *dev, const enum stepper_dire
if (err != 0) {
return -EIO;
}
err = tmc5041_write(config->controller, TMC5041_VMAX(config->index), velocity_fclk);
if (err != 0) {
return -EIO;
}
break;
}

Expand Down Expand Up @@ -724,7 +710,6 @@ static int tmc5041_stepper_init(const struct device *dev)
.enable = tmc5041_stepper_enable, \
.is_moving = tmc5041_stepper_is_moving, \
.move_by = tmc5041_stepper_move_by, \
.set_max_velocity = tmc5041_stepper_set_max_velocity, \
.set_micro_step_res = tmc5041_stepper_set_micro_step_res, \
.get_micro_step_res = tmc5041_stepper_get_micro_step_res, \
.set_reference_position = tmc5041_stepper_set_reference_position, \
Expand Down
9 changes: 4 additions & 5 deletions drivers/stepper/fake_stepper_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ DEFINE_FAKE_VALUE_FUNC(int, fake_stepper_is_moving, const struct device *, bool

DEFINE_FAKE_VALUE_FUNC(int, fake_stepper_move_by, const struct device *, int32_t);

DEFINE_FAKE_VALUE_FUNC(int, fake_stepper_set_max_velocity, const struct device *, uint32_t);
DEFINE_FAKE_VALUE_FUNC(int, fake_stepper_set_microstep_interval, const struct device *, uint64_t);

DEFINE_FAKE_VALUE_FUNC(int, fake_stepper_set_micro_step_res, const struct device *,
enum stepper_micro_step_resolution);
Expand All @@ -39,8 +39,7 @@ DEFINE_FAKE_VALUE_FUNC(int, fake_stepper_get_actual_position, const struct devic

DEFINE_FAKE_VALUE_FUNC(int, fake_stepper_move_to, const struct device *, int32_t);

DEFINE_FAKE_VALUE_FUNC(int, fake_stepper_run, const struct device *, enum stepper_direction,
uint32_t);
DEFINE_FAKE_VALUE_FUNC(int, fake_stepper_run, const struct device *, enum stepper_direction);

DEFINE_FAKE_VALUE_FUNC(int, fake_stepper_set_event_callback, const struct device *,
stepper_event_callback_t, void *);
Expand Down Expand Up @@ -92,7 +91,7 @@ static void fake_stepper_reset_rule_before(const struct ztest_unit_test *test, v
RESET_FAKE(fake_stepper_enable);
RESET_FAKE(fake_stepper_move_by);
RESET_FAKE(fake_stepper_is_moving);
RESET_FAKE(fake_stepper_set_max_velocity);
RESET_FAKE(fake_stepper_set_microstep_interval);
RESET_FAKE(fake_stepper_set_micro_step_res);
RESET_FAKE(fake_stepper_get_micro_step_res);
RESET_FAKE(fake_stepper_set_reference_position);
Expand Down Expand Up @@ -128,7 +127,7 @@ static DEVICE_API(stepper, fake_stepper_driver_api) = {
.enable = fake_stepper_enable,
.move_by = fake_stepper_move_by,
.is_moving = fake_stepper_is_moving,
.set_max_velocity = fake_stepper_set_max_velocity,
.set_microstep_interval = fake_stepper_set_microstep_interval,
.set_micro_step_res = fake_stepper_set_micro_step_res,
.get_micro_step_res = fake_stepper_get_micro_step_res,
.set_reference_position = fake_stepper_set_reference_position,
Expand Down
44 changes: 17 additions & 27 deletions drivers/stepper/gpio_stepper_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct gpio_stepper_data {
uint8_t coil_charge;
struct k_work_delayable stepper_dwork;
int32_t actual_position;
uint32_t delay_in_us;
uint64_t delay_in_ns;
int32_t step_count;
bool is_enabled;
stepper_event_callback_t callback;
Expand Down Expand Up @@ -111,10 +111,10 @@ static void update_remaining_steps(struct gpio_stepper_data *data)
{
if (data->step_count > 0) {
data->step_count--;
(void)k_work_reschedule(&data->stepper_dwork, K_USEC(data->delay_in_us));
(void)k_work_reschedule(&data->stepper_dwork, K_NSEC(data->delay_in_ns));
} else if (data->step_count < 0) {
data->step_count++;
(void)k_work_reschedule(&data->stepper_dwork, K_USEC(data->delay_in_us));
(void)k_work_reschedule(&data->stepper_dwork, K_NSEC(data->delay_in_ns));
} else {
if (!data->callback) {
LOG_WRN_ONCE("No callback set");
Expand Down Expand Up @@ -154,7 +154,7 @@ static void velocity_mode_task(const struct device *dev)

(void)stepper_motor_set_coil_charge(dev);
update_coil_charge(dev);
(void)k_work_reschedule(&data->stepper_dwork, K_USEC(data->delay_in_us));
(void)k_work_reschedule(&data->stepper_dwork, K_NSEC(data->delay_in_ns));
}

static void stepper_work_step_handler(struct k_work *work)
Expand Down Expand Up @@ -187,8 +187,8 @@ static int gpio_stepper_move_by(const struct device *dev, int32_t micro_steps)
return -ECANCELED;
}

if (data->delay_in_us == 0) {
LOG_ERR("Velocity not set or invalid velocity set");
if (data->delay_in_ns == 0) {
LOG_ERR("Step interval not set or invalid step interval set");
return -EINVAL;
}
K_SPINLOCK(&data->lock) {
Expand Down Expand Up @@ -229,8 +229,8 @@ static int gpio_stepper_move_to(const struct device *dev, int32_t micro_steps)
return -ECANCELED;
}

if (data->delay_in_us == 0) {
LOG_ERR("Velocity not set or invalid velocity set");
if (data->delay_in_ns == 0) {
LOG_ERR("Step interval not set or invalid step interval set");
return -EINVAL;
}
K_SPINLOCK(&data->lock) {
Expand All @@ -251,29 +251,24 @@ static int gpio_stepper_is_moving(const struct device *dev, bool *is_moving)
return 0;
}

static int gpio_stepper_set_max_velocity(const struct device *dev, uint32_t velocity)
static int gpio_stepper_set_microstep_interval(const struct device *dev,
uint64_t microstep_interval_ns)
{
struct gpio_stepper_data *data = dev->data;

if (velocity == 0) {
LOG_ERR("Velocity cannot be zero");
return -EINVAL;
}

if (velocity > USEC_PER_SEC) {
LOG_ERR("Velocity cannot be greater than %d micro_steps_per_second", USEC_PER_SEC);
if (microstep_interval_ns == 0) {
LOG_ERR("Step interval is invalid.");
return -EINVAL;
}

K_SPINLOCK(&data->lock) {
data->delay_in_us = USEC_PER_SEC / velocity;
data->delay_in_ns = microstep_interval_ns;
}
LOG_DBG("Setting Motor Speed to %d", velocity);
LOG_DBG("Setting Motor step interval to %llu", microstep_interval_ns);
return 0;
}

static int gpio_stepper_run(const struct device *dev, const enum stepper_direction direction,
const uint32_t velocity)
static int gpio_stepper_run(const struct device *dev, const enum stepper_direction direction)
{
struct gpio_stepper_data *data = dev->data;

Expand All @@ -285,12 +280,7 @@ static int gpio_stepper_run(const struct device *dev, const enum stepper_directi
K_SPINLOCK(&data->lock) {
data->run_mode = STEPPER_RUN_MODE_VELOCITY;
data->direction = direction;
if (velocity != 0) {
data->delay_in_us = USEC_PER_SEC / velocity;
(void)k_work_reschedule(&data->stepper_dwork, K_NO_WAIT);
} else {
(void)k_work_cancel_delayable(&data->stepper_dwork);
}
(void)k_work_reschedule(&data->stepper_dwork, K_NO_WAIT);
}
return 0;
}
Expand Down Expand Up @@ -377,7 +367,7 @@ static DEVICE_API(stepper, gpio_stepper_api) = {
.set_reference_position = gpio_stepper_set_reference_position,
.get_actual_position = gpio_stepper_get_actual_position,
.move_to = gpio_stepper_move_to,
.set_max_velocity = gpio_stepper_set_max_velocity,
.set_microstep_interval = gpio_stepper_set_microstep_interval,
.run = gpio_stepper_run,
.set_micro_step_res = gpio_stepper_set_micro_step_res,
.get_micro_step_res = gpio_stepper_get_micro_step_res,
Expand Down
40 changes: 15 additions & 25 deletions drivers/stepper/step_dir/step_dir_stepper_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,40 +228,36 @@ int step_dir_stepper_common_move_by(const struct device *dev, const int32_t micr
struct step_dir_stepper_common_data *data = dev->data;
const struct step_dir_stepper_common_config *config = dev->config;

if (data->max_velocity == 0) {
LOG_ERR("Velocity not set or invalid velocity set");
if (data->microstep_interval_ns == 0) {
LOG_ERR("Step interval not set or invalid step interval set");
return -EINVAL;
}

K_SPINLOCK(&data->lock) {
data->run_mode = STEPPER_RUN_MODE_POSITION;
data->step_count = micro_steps;
config->timing_source->update(dev, data->max_velocity);
config->timing_source->update(dev, data->microstep_interval_ns);
update_direction_from_step_count(dev);
config->timing_source->start(dev);
}

return 0;
}

int step_dir_stepper_common_set_max_velocity(const struct device *dev, const uint32_t velocity)
int step_dir_stepper_common_set_microstep_interval(const struct device *dev,
const uint64_t microstep_interval_ns)
{
struct step_dir_stepper_common_data *data = dev->data;
const struct step_dir_stepper_common_config *config = dev->config;

if (velocity == 0) {
LOG_ERR("Velocity cannot be zero");
return -EINVAL;
}

if (velocity > USEC_PER_SEC) {
LOG_ERR("Velocity cannot be greater than %d micro steps per second", USEC_PER_SEC);
if (microstep_interval_ns == 0) {
LOG_ERR("Step interval cannot be zero");
return -EINVAL;
}

K_SPINLOCK(&data->lock) {
data->max_velocity = velocity;
config->timing_source->update(dev, velocity);
data->microstep_interval_ns = microstep_interval_ns;
config->timing_source->update(dev, microstep_interval_ns);
}

return 0;
Expand Down Expand Up @@ -294,15 +290,15 @@ int step_dir_stepper_common_move_to(const struct device *dev, const int32_t valu
struct step_dir_stepper_common_data *data = dev->data;
const struct step_dir_stepper_common_config *config = dev->config;

if (data->max_velocity == 0) {
LOG_ERR("Velocity not set or invalid velocity set");
if (data->microstep_interval_ns == 0) {
LOG_ERR("Step interval not set or invalid step interval set");
return -EINVAL;
}

K_SPINLOCK(&data->lock) {
data->run_mode = STEPPER_RUN_MODE_POSITION;
data->step_count = value - data->actual_position;
config->timing_source->update(dev, data->max_velocity);
config->timing_source->update(dev, data->microstep_interval_ns);
update_direction_from_step_count(dev);
config->timing_source->start(dev);
}
Expand All @@ -318,22 +314,16 @@ int step_dir_stepper_common_is_moving(const struct device *dev, bool *is_moving)
return 0;
}

int step_dir_stepper_common_run(const struct device *dev, const enum stepper_direction direction,
const uint32_t velocity)
int step_dir_stepper_common_run(const struct device *dev, const enum stepper_direction direction)
{
struct step_dir_stepper_common_data *data = dev->data;
const struct step_dir_stepper_common_config *config = dev->config;

K_SPINLOCK(&data->lock) {
data->run_mode = STEPPER_RUN_MODE_VELOCITY;
data->direction = direction;
data->max_velocity = velocity;
config->timing_source->update(dev, velocity);
if (velocity != 0) {
config->timing_source->start(dev);
} else {
config->timing_source->stop(dev);
}
config->timing_source->update(dev, data->microstep_interval_ns);
config->timing_source->start(dev);
}

return 0;
Expand Down
15 changes: 7 additions & 8 deletions drivers/stepper/step_dir/step_dir_stepper_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ struct step_dir_stepper_common_data {
enum stepper_direction direction;
enum stepper_run_mode run_mode;
int32_t actual_position;
uint32_t max_velocity;
uint64_t microstep_interval_ns;
int32_t step_count;
stepper_event_callback_t callback;
void *event_cb_user_data;
Expand Down Expand Up @@ -141,13 +141,14 @@ int step_dir_stepper_common_init(const struct device *dev);
int step_dir_stepper_common_move_by(const struct device *dev, const int32_t micro_steps);

/**
* @brief Set the maximum velocity in micro_steps per second.
* @brief Set the step interval of the stepper motor.
*
* @param dev Pointer to the device structure.
* @param velocity Maximum velocity in micro_steps per second.
* @param microstep_interval_ns The step interval in nanoseconds.
* @return 0 on success, or a negative error code on failure.
*/
int step_dir_stepper_common_set_max_velocity(const struct device *dev, const uint32_t velocity);
int step_dir_stepper_common_set_microstep_interval(const struct device *dev,
const uint64_t microstep_interval_ns);

/**
* @brief Set the reference position of the stepper motor.
Expand Down Expand Up @@ -186,15 +187,13 @@ int step_dir_stepper_common_move_to(const struct device *dev, const int32_t valu
int step_dir_stepper_common_is_moving(const struct device *dev, bool *is_moving);

/**
* @brief Run the stepper with a given velocity in a given direction.
* @brief Run the stepper with a given direction and step interval.
*
* @param dev Pointer to the device structure.
* @param direction The direction of movement (positive or negative).
* @param velocity The velocity in micro_steps per second.
* @return 0 on success, or a negative error code on failure.
*/
int step_dir_stepper_common_run(const struct device *dev, const enum stepper_direction direction,
const uint32_t velocity);
int step_dir_stepper_common_run(const struct device *dev, const enum stepper_direction direction);

/**
* @brief Set a callback function for stepper motor events.
Expand Down
Loading
Loading