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