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