Line data Source code
1 1 : /*
2 : * SPDX-FileCopyrightText: Copyright (c) 2024 Carl Zeiss Meditec AG
3 : * SPDX-FileCopyrightText: Copyright (c) 2024 Jilay Sandeep Pandya
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : /**
8 : * @file drivers/stepper.h
9 : * @brief Public API for Stepper Driver
10 : */
11 :
12 : #ifndef ZEPHYR_INCLUDE_DRIVERS_STEPPER_H_
13 : #define ZEPHYR_INCLUDE_DRIVERS_STEPPER_H_
14 :
15 : /**
16 : * @brief Stepper Driver Interface
17 : * @defgroup stepper_interface Stepper Driver Interface
18 : * @since 4.0
19 : * @version 0.1.0
20 : * @ingroup io_interfaces
21 : * @{
22 : */
23 :
24 : #include <zephyr/kernel.h>
25 : #include <zephyr/device.h>
26 : #include <errno.h>
27 :
28 : #ifdef __cplusplus
29 : extern "C" {
30 : #endif
31 :
32 : /**
33 : * @brief Stepper Motor micro-step resolution options
34 : */
35 1 : enum stepper_micro_step_resolution {
36 : /** Full step resolution */
37 : STEPPER_MICRO_STEP_1 = 1,
38 : /** 2 micro-steps per full step */
39 : STEPPER_MICRO_STEP_2 = 2,
40 : /** 4 micro-steps per full step */
41 : STEPPER_MICRO_STEP_4 = 4,
42 : /** 8 micro-steps per full step */
43 : STEPPER_MICRO_STEP_8 = 8,
44 : /** 16 micro-steps per full step */
45 : STEPPER_MICRO_STEP_16 = 16,
46 : /** 32 micro-steps per full step */
47 : STEPPER_MICRO_STEP_32 = 32,
48 : /** 64 micro-steps per full step */
49 : STEPPER_MICRO_STEP_64 = 64,
50 : /** 128 micro-steps per full step */
51 : STEPPER_MICRO_STEP_128 = 128,
52 : /** 256 micro-steps per full step */
53 : STEPPER_MICRO_STEP_256 = 256,
54 : };
55 :
56 : /**
57 : * @brief Macro to calculate the index of the microstep resolution
58 : * @param res Microstep resolution
59 : */
60 1 : #define MICRO_STEP_RES_INDEX(res) LOG2(res)
61 :
62 0 : #define VALID_MICRO_STEP_RES(res) \
63 : ((res) == STEPPER_MICRO_STEP_1 || (res) == STEPPER_MICRO_STEP_2 || \
64 : (res) == STEPPER_MICRO_STEP_4 || (res) == STEPPER_MICRO_STEP_8 || \
65 : (res) == STEPPER_MICRO_STEP_16 || (res) == STEPPER_MICRO_STEP_32 || \
66 : (res) == STEPPER_MICRO_STEP_64 || (res) == STEPPER_MICRO_STEP_128 || \
67 : (res) == STEPPER_MICRO_STEP_256)
68 :
69 : /**
70 : * @brief Stepper Motor direction options
71 : */
72 1 : enum stepper_direction {
73 : /** Negative direction */
74 : STEPPER_DIRECTION_NEGATIVE = 0,
75 : /** Positive direction */
76 : STEPPER_DIRECTION_POSITIVE = 1,
77 : };
78 :
79 : /**
80 : * @brief Stepper Motor run mode options
81 : */
82 1 : enum stepper_run_mode {
83 : /** Hold Mode */
84 : STEPPER_RUN_MODE_HOLD = 0,
85 : /** Position Mode*/
86 : STEPPER_RUN_MODE_POSITION = 1,
87 : /** Velocity Mode */
88 : STEPPER_RUN_MODE_VELOCITY = 2,
89 : };
90 :
91 : /**
92 : * @brief Stepper Events
93 : */
94 1 : enum stepper_event {
95 : /** Steps set using move_by or move_to have been executed */
96 : STEPPER_EVENT_STEPS_COMPLETED = 0,
97 : /** Stall detected */
98 : STEPPER_EVENT_STALL_DETECTED = 1,
99 : /** Left end switch status changes to pressed */
100 : STEPPER_EVENT_LEFT_END_STOP_DETECTED = 2,
101 : /** Right end switch status changes to pressed */
102 : STEPPER_EVENT_RIGHT_END_STOP_DETECTED = 3,
103 : /** Stepper has stopped */
104 : STEPPER_EVENT_STOPPED = 4,
105 : /** Fault with the stepper controller detected */
106 : STEPPER_EVENT_FAULT_DETECTED = 5,
107 : };
108 :
109 : /**
110 : * @cond INTERNAL_HIDDEN
111 : *
112 : * Stepper driver API definition and system call entry points.
113 : *
114 : */
115 :
116 : /**
117 : * @brief Enable the stepper driver.
118 : *
119 : * @see stepper_enable() for details.
120 : */
121 : typedef int (*stepper_enable_t)(const struct device *dev);
122 :
123 : /**
124 : * @brief Disable the stepper driver.
125 : *
126 : * @see stepper_disable() for details.
127 : */
128 : typedef int (*stepper_disable_t)(const struct device *dev);
129 :
130 : /**
131 : * @brief Set the micro-step resolution
132 : *
133 : * @see stepper_set_micro_step_res() for details.
134 : */
135 : typedef int (*stepper_set_micro_step_res_t)(const struct device *dev,
136 : const enum stepper_micro_step_resolution resolution);
137 :
138 : /**
139 : * @brief Get the micro-step resolution
140 : *
141 : * @see stepper_get_micro_step_res() for details.
142 : */
143 : typedef int (*stepper_get_micro_step_res_t)(const struct device *dev,
144 : enum stepper_micro_step_resolution *resolution);
145 : /**
146 : * @brief Set the reference position of the stepper
147 : *
148 : * @see stepper_set_actual_position() for details.
149 : */
150 : typedef int (*stepper_set_reference_position_t)(const struct device *dev, const int32_t value);
151 :
152 : /**
153 : * @brief Get the actual a.k.a reference position of the stepper
154 : *
155 : * @see stepper_get_actual_position() for details.
156 : */
157 : typedef int (*stepper_get_actual_position_t)(const struct device *dev, int32_t *value);
158 :
159 : /**
160 : * @brief Callback function for stepper events
161 : */
162 : typedef void (*stepper_event_callback_t)(const struct device *dev, const enum stepper_event event,
163 : void *user_data);
164 :
165 : /**
166 : * @brief Set the callback function to be called when a stepper event occurs
167 : *
168 : * @see stepper_set_event_callback() for details.
169 : */
170 : typedef int (*stepper_set_event_callback_t)(const struct device *dev,
171 : stepper_event_callback_t callback, void *user_data);
172 : /**
173 : * @brief Set the time interval between steps in nanoseconds.
174 : *
175 : * @see stepper_set_microstep_interval() for details.
176 : */
177 : typedef int (*stepper_set_microstep_interval_t)(const struct device *dev,
178 : const uint64_t microstep_interval_ns);
179 : /**
180 : * @brief Move the stepper relatively by a given number of micro-steps.
181 : *
182 : * @see stepper_move_by() for details.
183 : */
184 : typedef int (*stepper_move_by_t)(const struct device *dev, const int32_t micro_steps);
185 :
186 : /**
187 : * @brief Move the stepper to an absolute position in micro-steps.
188 : *
189 : * @see stepper_move_to() for details.
190 : */
191 : typedef int (*stepper_move_to_t)(const struct device *dev, const int32_t micro_steps);
192 :
193 : /**
194 : * @brief Run the stepper with a given step interval in a given direction
195 : *
196 : * @see stepper_run() for details.
197 : */
198 : typedef int (*stepper_run_t)(const struct device *dev, const enum stepper_direction direction);
199 :
200 : /**
201 : * @brief Stop the stepper
202 : *
203 : * @see stepper_stop() for details.
204 : */
205 : typedef int (*stepper_stop_t)(const struct device *dev);
206 :
207 : /**
208 : * @brief Is the target position fo the stepper reached
209 : *
210 : * @see stepper_is_moving() for details.
211 : */
212 : typedef int (*stepper_is_moving_t)(const struct device *dev, bool *is_moving);
213 :
214 : /**
215 : * @brief Stepper Driver API
216 : */
217 : __subsystem struct stepper_driver_api {
218 : stepper_enable_t enable;
219 : stepper_disable_t disable;
220 : stepper_set_micro_step_res_t set_micro_step_res;
221 : stepper_get_micro_step_res_t get_micro_step_res;
222 : stepper_set_reference_position_t set_reference_position;
223 : stepper_get_actual_position_t get_actual_position;
224 : stepper_set_event_callback_t set_event_callback;
225 : stepper_set_microstep_interval_t set_microstep_interval;
226 : stepper_move_by_t move_by;
227 : stepper_move_to_t move_to;
228 : stepper_run_t run;
229 : stepper_stop_t stop;
230 : stepper_is_moving_t is_moving;
231 : };
232 :
233 : /**
234 : * @endcond
235 : */
236 :
237 : /**
238 : * @brief Enable stepper driver
239 : *
240 : * @details Enabling the driver shall switch on the power stage and energize the coils.
241 : *
242 : * @param dev pointer to the stepper driver instance
243 : *
244 : * @retval -EIO Error during Enabling
245 : * @retval 0 Success
246 : */
247 1 : __syscall int stepper_enable(const struct device *dev);
248 :
249 : static inline int z_impl_stepper_enable(const struct device *dev)
250 : {
251 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
252 :
253 : return api->enable(dev);
254 : }
255 :
256 : /**
257 : * @brief Disable stepper driver
258 : *
259 : * @details Disabling the driver shall switch off the power stage and de-energize the coils.
260 : * Disabling the stepper does not implicitly stop the stepper. If the motor shall not move after
261 : * re-enabling the stepper than consider calling stepper_stop() before.
262 : *
263 : * @param dev pointer to the stepper driver instance
264 : *
265 : * @retval -ENOTSUP Disabling of driver is not supported.
266 : * @retval -EIO Error during Disabling
267 : * @retval 0 Success
268 : */
269 1 : __syscall int stepper_disable(const struct device *dev);
270 :
271 : static inline int z_impl_stepper_disable(const struct device *dev)
272 : {
273 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
274 :
275 : return api->disable(dev);
276 : }
277 :
278 : /**
279 : * @brief Set the micro-step resolution in stepper driver
280 : *
281 : * @param dev pointer to the stepper driver instance
282 : * @param resolution micro-step resolution
283 : *
284 : * @retval -EIO General input / output error
285 : * @retval -ENOSYS If not implemented by device driver
286 : * @retval -EINVAL If the requested resolution is invalid
287 : * @retval -ENOTSUP If the requested resolution is not supported
288 : * @retval 0 Success
289 : */
290 1 : __syscall int stepper_set_micro_step_res(const struct device *dev,
291 : enum stepper_micro_step_resolution resolution);
292 :
293 : static inline int z_impl_stepper_set_micro_step_res(const struct device *dev,
294 : enum stepper_micro_step_resolution resolution)
295 : {
296 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
297 :
298 : if (api->set_micro_step_res == NULL) {
299 : return -ENOSYS;
300 : }
301 :
302 : if (!VALID_MICRO_STEP_RES(resolution)) {
303 : return -EINVAL;
304 : }
305 : return api->set_micro_step_res(dev, resolution);
306 : }
307 :
308 : /**
309 : * @brief Get the micro-step resolution in stepper driver
310 : *
311 : * @param dev pointer to the stepper driver instance
312 : * @param resolution micro-step resolution
313 : *
314 : * @retval -EIO General input / output error
315 : * @retval -ENOSYS If not implemented by device driver
316 : * @retval 0 Success
317 : */
318 1 : __syscall int stepper_get_micro_step_res(const struct device *dev,
319 : enum stepper_micro_step_resolution *resolution);
320 :
321 : static inline int z_impl_stepper_get_micro_step_res(const struct device *dev,
322 : enum stepper_micro_step_resolution *resolution)
323 : {
324 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
325 :
326 : if (api->get_micro_step_res == NULL) {
327 : return -ENOSYS;
328 : }
329 : return api->get_micro_step_res(dev, resolution);
330 : }
331 :
332 : /**
333 : * @brief Set the reference position of the stepper
334 : *
335 : * @param dev Pointer to the stepper driver instance.
336 : * @param value The reference position to set in micro-steps.
337 : *
338 : * @retval -EIO General input / output error
339 : * @retval -ENOSYS If not implemented by device driver
340 : * @retval 0 Success
341 : */
342 1 : __syscall int stepper_set_reference_position(const struct device *dev, int32_t value);
343 :
344 : static inline int z_impl_stepper_set_reference_position(const struct device *dev,
345 : const int32_t value)
346 : {
347 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
348 :
349 : if (api->set_reference_position == NULL) {
350 : return -ENOSYS;
351 : }
352 : return api->set_reference_position(dev, value);
353 : }
354 :
355 : /**
356 : * @brief Get the actual a.k.a reference position of the stepper
357 : *
358 : * @param dev pointer to the stepper driver instance
359 : * @param value The actual position to get in micro-steps
360 : *
361 : * @retval -EIO General input / output error
362 : * @retval -ENOSYS If not implemented by device driver
363 : * @retval 0 Success
364 : */
365 1 : __syscall int stepper_get_actual_position(const struct device *dev, int32_t *value);
366 :
367 : static inline int z_impl_stepper_get_actual_position(const struct device *dev, int32_t *value)
368 : {
369 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
370 :
371 : if (api->get_actual_position == NULL) {
372 : return -ENOSYS;
373 : }
374 : return api->get_actual_position(dev, value);
375 : }
376 :
377 : /**
378 : * @brief Set the callback function to be called when a stepper event occurs
379 : *
380 : * @param dev pointer to the stepper driver instance
381 : * @param callback Callback function to be called when a stepper event occurs
382 : * passing NULL will disable the callback
383 : * @param user_data User data to be passed to the callback function
384 : *
385 : * @retval -ENOSYS If not implemented by device driver
386 : * @retval 0 Success
387 : */
388 1 : __syscall int stepper_set_event_callback(const struct device *dev,
389 : stepper_event_callback_t callback, void *user_data);
390 :
391 : static inline int z_impl_stepper_set_event_callback(const struct device *dev,
392 : stepper_event_callback_t callback,
393 : void *user_data)
394 : {
395 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
396 :
397 : if (api->set_event_callback == NULL) {
398 : return -ENOSYS;
399 : }
400 : return api->set_event_callback(dev, callback, user_data);
401 : }
402 :
403 : /**
404 : * @brief Set the time interval between steps in nanoseconds with immediate effect.
405 : *
406 : * @note Setting step interval does not set the stepper into motion, a combination of
407 : * set_microstep_interval and move is required to set the stepper into motion.
408 : *
409 : * @param dev pointer to the stepper driver instance
410 : * @param microstep_interval_ns time interval between steps in nanoseconds
411 : *
412 : * @retval -EIO General input / output error
413 : * @retval -EINVAL If the requested step interval is not supported
414 : * @retval -ENOSYS If not implemented by device driver
415 : * @retval 0 Success
416 : */
417 1 : __syscall int stepper_set_microstep_interval(const struct device *dev,
418 : uint64_t microstep_interval_ns);
419 :
420 : static inline int z_impl_stepper_set_microstep_interval(const struct device *dev,
421 : const uint64_t microstep_interval_ns)
422 : {
423 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
424 :
425 : if (api->set_microstep_interval == NULL) {
426 : return -ENOSYS;
427 : }
428 : return api->set_microstep_interval(dev, microstep_interval_ns);
429 : }
430 :
431 : /**
432 : * @brief Set the micro-steps to be moved from the current position i.e. relative movement
433 : *
434 : * @details The stepper will move by the given number of micro-steps from the current position.
435 : * This function is non-blocking.
436 : *
437 : * @param dev pointer to the stepper driver instance
438 : * @param micro_steps target micro-steps to be moved from the current position
439 : *
440 : * @retval -EIO General input / output error
441 : * @retval 0 Success
442 : */
443 1 : __syscall int stepper_move_by(const struct device *dev, int32_t micro_steps);
444 :
445 : static inline int z_impl_stepper_move_by(const struct device *dev, const int32_t micro_steps)
446 : {
447 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
448 :
449 : return api->move_by(dev, micro_steps);
450 : }
451 :
452 : /**
453 : * @brief Set the absolute target position of the stepper
454 : *
455 : * @details The stepper will move to the given micro-steps position from the reference position.
456 : * This function is non-blocking.
457 : *
458 : * @param dev pointer to the stepper driver instance
459 : * @param micro_steps target position to set in micro-steps
460 : *
461 : * @retval -EIO General input / output error
462 : * @retval -ENOSYS If not implemented by device driver
463 : * @retval 0 Success
464 : */
465 1 : __syscall int stepper_move_to(const struct device *dev, int32_t micro_steps);
466 :
467 : static inline int z_impl_stepper_move_to(const struct device *dev, const int32_t micro_steps)
468 : {
469 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
470 :
471 : if (api->move_to == NULL) {
472 : return -ENOSYS;
473 : }
474 : return api->move_to(dev, micro_steps);
475 : }
476 :
477 : /**
478 : * @brief Run the stepper with a given step interval in a given direction
479 : *
480 : * @details The stepper shall be set into motion and run continuously until
481 : * stalled or stopped using some other command, for instance, stepper_stop(). This
482 : * function is non-blocking.
483 : *
484 : * @param dev pointer to the stepper driver instance
485 : * @param direction The direction to set
486 : *
487 : * @retval -EIO General input / output error
488 : * @retval -ENOSYS If not implemented by device driver
489 : * @retval 0 Success
490 : */
491 1 : __syscall int stepper_run(const struct device *dev, enum stepper_direction direction);
492 :
493 : static inline int z_impl_stepper_run(const struct device *dev,
494 : const enum stepper_direction direction)
495 : {
496 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
497 :
498 : if (api->run == NULL) {
499 : return -ENOSYS;
500 : }
501 : return api->run(dev, direction);
502 : }
503 :
504 : /**
505 : * @brief Stop the stepper
506 : * @details Cancel all active movements.
507 : *
508 : * @param dev pointer to the stepper driver instance
509 : *
510 : * @retval -EIO General input / output error
511 : * @retval -ENOSYS If not implemented by device driver
512 : * @retval 0 Success
513 : */
514 1 : __syscall int stepper_stop(const struct device *dev);
515 :
516 : static inline int z_impl_stepper_stop(const struct device *dev)
517 : {
518 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
519 :
520 : if (api->stop == NULL) {
521 : return -ENOSYS;
522 : }
523 : return api->stop(dev);
524 : }
525 :
526 : /**
527 : * @brief Check if the stepper is currently moving
528 : *
529 : * @param dev pointer to the stepper driver instance
530 : * @param is_moving Pointer to a boolean to store the moving status of the stepper
531 : *
532 : * @retval -EIO General input / output error
533 : * @retval -ENOSYS If not implemented by device driver
534 : * @retval 0 Success
535 : */
536 1 : __syscall int stepper_is_moving(const struct device *dev, bool *is_moving);
537 :
538 : static inline int z_impl_stepper_is_moving(const struct device *dev, bool *is_moving)
539 : {
540 : const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
541 :
542 : if (api->is_moving == NULL) {
543 : return -ENOSYS;
544 : }
545 : return api->is_moving(dev, is_moving);
546 : }
547 :
548 : /**
549 : * @}
550 : */
551 :
552 : #ifdef __cplusplus
553 : }
554 : #endif
555 :
556 : #include <zephyr/syscalls/stepper.h>
557 :
558 : #endif /* ZEPHYR_INCLUDE_DRIVERS_STEPPER_H_ */
|