diff --git a/drivers/stepper/Kconfig.gpio b/drivers/stepper/Kconfig.gpio index 99e35057895..4b43140cd28 100644 --- a/drivers/stepper/Kconfig.gpio +++ b/drivers/stepper/Kconfig.gpio @@ -2,13 +2,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2024 Jilay Sandeep Pandya # SPDX-License-Identifier: Apache-2.0 -menu "GPIO stepper driver" - config GPIO_STEPPER bool "Activate driver for gpio stepper control" depends on DT_HAS_ZEPHYR_GPIO_STEPPER_ENABLED default y - help - GPIO Stepper driver for stepper motor control with darlington arrays or dual H-bridge. - -endmenu diff --git a/samples/drivers/stepper/generic/CMakeLists.txt b/samples/drivers/stepper/generic/CMakeLists.txt new file mode 100644 index 00000000000..3139442c041 --- /dev/null +++ b/samples/drivers/stepper/generic/CMakeLists.txt @@ -0,0 +1,10 @@ + # SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya + # SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(stepper_generic) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/drivers/stepper/generic/Kconfig b/samples/drivers/stepper/generic/Kconfig new file mode 100644 index 00000000000..a9259ff3b8a --- /dev/null +++ b/samples/drivers/stepper/generic/Kconfig @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "Stepper generic sample application" + +config STEPS_PER_REV + int "Steps per revolution" + default 200 + +config STEP_INTERVAL_NS + int "Step interval (ns)" + default 1000000 + +config PING_PONG_N_REV + int "Change direction every N revolutions" + default 1 + +config MONITOR_THREAD_TIMEOUT_MS + int "Monitor thread timeout (ms)" + default 1000 + +config MONITOR_THREAD_STACK_SIZE + int "Monitor thread stack size" + default 1024 + +source "Kconfig.zephyr" diff --git a/samples/drivers/stepper/generic/README.rst b/samples/drivers/stepper/generic/README.rst new file mode 100644 index 00000000000..be4bb7bd01c --- /dev/null +++ b/samples/drivers/stepper/generic/README.rst @@ -0,0 +1,53 @@ +.. zephyr:code-sample:: stepper + :name: Stepper + :relevant-api: stepper_interface + + Rotate a stepper motor in 4 different modes. + +Description +*********** + +This sample demonstrates how to use the stepper driver API to control a stepper motor. The sample +spins the stepper and outputs the events to the console. + +The stepper spins in 4 different modes: ping_pong_relative, ping_pong_absolute, continuous_clockwise +and continuous_anticlockwise. The micro-step interval in nanoseconds can be configured using the +:kconfig:option:`CONFIG_STEP_INTERVAL_NS`. The sample also demonstrates how to use the stepper callback +to change the direction of the stepper after a certain number of steps. + +Pressing any button should change the mode of the stepper. + +The sample also has a monitor thread that prints the actual position of the stepper motor every +:kconfig:option:`CONFIG_MONITOR_THREAD_TIMEOUT_MS` milliseconds. + +Building and Running +******************** + +This project spins the stepper and outputs the events to the console. + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/stepper/generic + :board: nucleo_g071rb + :goals: build flash + +Sample Output +============= + +.. code-block:: console + + *** Booting Zephyr OS build v4.0.0-5289-g0c368e85b117 *** + Actual position: 910 + Actual position: 1821 + mode: ping pong absolute + Actual position: 2410 + mode: rotate cw + Actual position: 2162 + Actual position: 3073 + mode: rotate ccw + Actual position: 3793 + mode: ping pong relative + Actual position: 4607 + Actual position: 5518 + Actual position: 6428 + + diff --git a/samples/drivers/stepper/generic/boards/nucleo_g071rb.overlay b/samples/drivers/stepper/generic/boards/nucleo_g071rb.overlay new file mode 100644 index 00000000000..e392a028cb3 --- /dev/null +++ b/samples/drivers/stepper/generic/boards/nucleo_g071rb.overlay @@ -0,0 +1,17 @@ +/ { + aliases { + stepper = &gpio_stepper; + }; +}; + +/ { + gpio_stepper: gpio_stepper { + compatible = "zephyr,gpio-stepper"; + status = "okay"; + micro-step-res = <2>; + gpios = <&gpioa 9 GPIO_ACTIVE_HIGH>, /* D8 */ + <&gpioc 7 GPIO_ACTIVE_HIGH>, /* D9 */ + <&gpiob 0 GPIO_ACTIVE_HIGH>, /* D10 */ + <&gpioa 7 GPIO_ACTIVE_HIGH>; /* D11 */ + }; +}; diff --git a/samples/drivers/stepper/generic/prj.conf b/samples/drivers/stepper/generic/prj.conf new file mode 100644 index 00000000000..7b579deb99f --- /dev/null +++ b/samples/drivers/stepper/generic/prj.conf @@ -0,0 +1,3 @@ +CONFIG_STEPPER=y +CONFIG_LOG=y +CONFIG_INPUT=y diff --git a/samples/drivers/stepper/generic/sample.yaml b/samples/drivers/stepper/generic/sample.yaml new file mode 100644 index 00000000000..765b3b35c6e --- /dev/null +++ b/samples/drivers/stepper/generic/sample.yaml @@ -0,0 +1,8 @@ +sample: + name: Generic Stepper Sample +tests: + sample.drivers.stepper.generic: + harness: stepper + tags: stepper + platform_allow: nucleo_g071rb + depends_on: gpio input diff --git a/samples/drivers/stepper/generic/src/main.c b/samples/drivers/stepper/generic/src/main.c new file mode 100644 index 00000000000..1262ecd8605 --- /dev/null +++ b/samples/drivers/stepper/generic/src/main.c @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +static const struct device *stepper = DEVICE_DT_GET(DT_ALIAS(stepper)); + +enum stepper_mode { + STEPPER_MODE_PING_PONG_RELATIVE, + STEPPER_MODE_PING_PONG_ABSOLUTE, + STEPPER_MODE_ROTATE_CW, + STEPPER_MODE_ROTATE_CCW, +}; + +static atomic_t stepper_mode = ATOMIC_INIT(STEPPER_MODE_PING_PONG_RELATIVE); + +static int32_t ping_pong_target_position = + CONFIG_STEPS_PER_REV * CONFIG_PING_PONG_N_REV * DT_PROP(DT_ALIAS(stepper), micro_step_res); + +static K_SEM_DEFINE(stepper_generic_sem, 0, 1); + +static void stepper_callback(const struct device *dev, const enum stepper_event event, + void *user_data) +{ + switch (event) { + case STEPPER_EVENT_STEPS_COMPLETED: + k_sem_give(&stepper_generic_sem); + break; + default: + break; + } +} + +static void button_pressed(struct input_event *event, void *user_data) +{ + ARG_UNUSED(user_data); + + if (event->value == 0 && event->type == INPUT_EV_KEY) { + return; + } + enum stepper_mode mode = atomic_get(&stepper_mode); + + if (mode == STEPPER_MODE_ROTATE_CCW) { + atomic_set(&stepper_mode, STEPPER_MODE_PING_PONG_RELATIVE); + } else { + atomic_inc(&stepper_mode); + } + k_sem_give(&stepper_generic_sem); +} + +INPUT_CALLBACK_DEFINE(NULL, button_pressed, NULL); + +int main(void) +{ + printf("Starting generic stepper sample\n"); + if (!device_is_ready(stepper)) { + printf("Device %s is not ready\n", stepper->name); + return -ENODEV; + } + printf("stepper is %p, name is %s\n", stepper, stepper->name); + + stepper_set_event_callback(stepper, stepper_callback, NULL); + stepper_enable(stepper, true); + stepper_set_reference_position(stepper, 0); + stepper_set_microstep_interval(stepper, CONFIG_STEP_INTERVAL_NS); + stepper_move_by(stepper, ping_pong_target_position); + + for (;;) { + k_sem_take(&stepper_generic_sem, K_FOREVER); + switch (atomic_get(&stepper_mode)) { + case STEPPER_MODE_ROTATE_CW: + stepper_run(stepper, STEPPER_DIRECTION_POSITIVE); + printf("mode: rotate cw\n"); + break; + case STEPPER_MODE_ROTATE_CCW: + stepper_run(stepper, STEPPER_DIRECTION_NEGATIVE); + printf("mode: rotate ccw\n"); + break; + case STEPPER_MODE_PING_PONG_RELATIVE: + ping_pong_target_position *= -1; + stepper_move_by(stepper, ping_pong_target_position); + printf("mode: ping pong relative\n"); + break; + case STEPPER_MODE_PING_PONG_ABSOLUTE: + ping_pong_target_position *= -1; + stepper_move_to(stepper, ping_pong_target_position); + printf("mode: ping pong absolute\n"); + break; + } + } + return 0; +} + +static void monitor_thread(void) +{ + for (;;) { + int32_t actual_position; + + stepper_get_actual_position(stepper, &actual_position); + printf("Actual position: %d\n", actual_position); + k_sleep(K_MSEC(CONFIG_MONITOR_THREAD_TIMEOUT_MS)); + } +} + +K_THREAD_DEFINE(monitor_tid, CONFIG_MONITOR_THREAD_STACK_SIZE, monitor_thread, NULL, NULL, NULL, 5, + 0, 0);