1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <zephyr/device.h>
7 #include <zephyr/drivers/gpio.h>
8 #include <zephyr/drivers/stepper.h>
9 #include <zephyr/input/input.h>
10 #include <zephyr/kernel.h>
11
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(stepper, CONFIG_STEPPER_LOG_LEVEL);
14
15 static const struct device *stepper = DEVICE_DT_GET(DT_ALIAS(stepper));
16
17 enum stepper_mode {
18 STEPPER_MODE_ENABLE,
19 STEPPER_MODE_PING_PONG_RELATIVE,
20 STEPPER_MODE_PING_PONG_ABSOLUTE,
21 STEPPER_MODE_ROTATE_CW,
22 STEPPER_MODE_ROTATE_CCW,
23 STEPPER_MODE_STOP,
24 STEPPER_MODE_DISABLE,
25 };
26
27 static atomic_t stepper_mode = ATOMIC_INIT(STEPPER_MODE_DISABLE);
28
29 static int32_t ping_pong_target_position =
30 CONFIG_STEPS_PER_REV * CONFIG_PING_PONG_N_REV * DT_PROP(DT_ALIAS(stepper), micro_step_res);
31
32 static K_SEM_DEFINE(stepper_generic_sem, 0, 1);
33
stepper_callback(const struct device * dev,const enum stepper_event event,void * user_data)34 static void stepper_callback(const struct device *dev, const enum stepper_event event,
35 void *user_data)
36 {
37 switch (event) {
38 case STEPPER_EVENT_STEPS_COMPLETED:
39 k_sem_give(&stepper_generic_sem);
40 break;
41 default:
42 break;
43 }
44 }
45
button_pressed(struct input_event * event,void * user_data)46 static void button_pressed(struct input_event *event, void *user_data)
47 {
48 ARG_UNUSED(user_data);
49
50 if (event->value == 0 && event->type == INPUT_EV_KEY) {
51 return;
52 }
53 enum stepper_mode mode = atomic_get(&stepper_mode);
54
55 if (mode == STEPPER_MODE_DISABLE) {
56 atomic_set(&stepper_mode, STEPPER_MODE_ENABLE);
57 } else {
58 atomic_inc(&stepper_mode);
59 }
60 k_sem_give(&stepper_generic_sem);
61 }
62
63 INPUT_CALLBACK_DEFINE(NULL, button_pressed, NULL);
64
main(void)65 int main(void)
66 {
67 LOG_INF("Starting generic stepper sample\n");
68 if (!device_is_ready(stepper)) {
69 LOG_ERR("Device %s is not ready\n", stepper->name);
70 return -ENODEV;
71 }
72 LOG_DBG("stepper is %p, name is %s\n", stepper, stepper->name);
73
74 stepper_set_event_callback(stepper, stepper_callback, NULL);
75 stepper_set_reference_position(stepper, 0);
76 stepper_set_microstep_interval(stepper, CONFIG_STEP_INTERVAL_NS);
77
78 for (;;) {
79 k_sem_take(&stepper_generic_sem, K_FOREVER);
80 switch (atomic_get(&stepper_mode)) {
81 case STEPPER_MODE_ENABLE:
82 stepper_enable(stepper, true);
83 LOG_INF("mode: enable\n");
84 break;
85 case STEPPER_MODE_STOP:
86 stepper_stop(stepper);
87 LOG_INF("mode: stop\n");
88 break;
89 case STEPPER_MODE_ROTATE_CW:
90 stepper_run(stepper, STEPPER_DIRECTION_POSITIVE);
91 LOG_INF("mode: rotate cw\n");
92 break;
93 case STEPPER_MODE_ROTATE_CCW:
94 stepper_run(stepper, STEPPER_DIRECTION_NEGATIVE);
95 LOG_INF("mode: rotate ccw\n");
96 break;
97 case STEPPER_MODE_PING_PONG_RELATIVE:
98 ping_pong_target_position *= -1;
99 stepper_move_by(stepper, ping_pong_target_position);
100 LOG_INF("mode: ping pong relative\n");
101 break;
102 case STEPPER_MODE_PING_PONG_ABSOLUTE:
103 ping_pong_target_position *= -1;
104 stepper_move_to(stepper, ping_pong_target_position);
105 LOG_INF("mode: ping pong absolute\n");
106 break;
107 case STEPPER_MODE_DISABLE:
108 stepper_enable(stepper, false);
109 LOG_INF("mode: disable\n");
110 break;
111 }
112 }
113 return 0;
114 }
115
monitor_thread(void)116 static void monitor_thread(void)
117 {
118 for (;;) {
119 int32_t actual_position;
120
121 stepper_get_actual_position(stepper, &actual_position);
122 LOG_DBG("Actual position: %d\n", actual_position);
123 k_sleep(K_MSEC(CONFIG_MONITOR_THREAD_TIMEOUT_MS));
124 }
125 }
126
127 K_THREAD_DEFINE(monitor_tid, CONFIG_MONITOR_THREAD_STACK_SIZE, monitor_thread, NULL, NULL, NULL, 5,
128 0, 0);
129