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