Browse Source

samples: stepper: add generic stepper sample

Add a generic stepper sample with gpio-stepper

Signed-off-by: Jilay Pandya <jilay.pandya@outlook.com>
pull/84672/head
Jilay Pandya 5 months ago committed by Benjamin Cabé
parent
commit
b5ff37297d
  1. 6
      drivers/stepper/Kconfig.gpio
  2. 10
      samples/drivers/stepper/generic/CMakeLists.txt
  3. 26
      samples/drivers/stepper/generic/Kconfig
  4. 53
      samples/drivers/stepper/generic/README.rst
  5. 17
      samples/drivers/stepper/generic/boards/nucleo_g071rb.overlay
  6. 3
      samples/drivers/stepper/generic/prj.conf
  7. 8
      samples/drivers/stepper/generic/sample.yaml
  8. 112
      samples/drivers/stepper/generic/src/main.c

6
drivers/stepper/Kconfig.gpio

@ -2,13 +2,7 @@ @@ -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

10
samples/drivers/stepper/generic/CMakeLists.txt

@ -0,0 +1,10 @@ @@ -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})

26
samples/drivers/stepper/generic/Kconfig

@ -0,0 +1,26 @@ @@ -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"

53
samples/drivers/stepper/generic/README.rst

@ -0,0 +1,53 @@ @@ -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
<repeats endlessly>

17
samples/drivers/stepper/generic/boards/nucleo_g071rb.overlay

@ -0,0 +1,17 @@ @@ -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 */
};
};

3
samples/drivers/stepper/generic/prj.conf

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
CONFIG_STEPPER=y
CONFIG_LOG=y
CONFIG_INPUT=y

8
samples/drivers/stepper/generic/sample.yaml

@ -0,0 +1,8 @@ @@ -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

112
samples/drivers/stepper/generic/src/main.c

@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya.
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/stepper.h>
#include <zephyr/input/input.h>
#include <zephyr/kernel.h>
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);
Loading…
Cancel
Save