1 /**
2 * @file drivers/stepper.h
3 *
4 * @brief Public API for Stepper Driver
5 *
6 */
7
8 /*
9 * SPDX-FileCopyrightText: Copyright (c) 2024 Carl Zeiss Meditec AG
10 * SPDX-FileCopyrightText: Copyright (c) 2024 Jilay Sandeep Pandya
11 * SPDX-License-Identifier: Apache-2.0
12 */
13
14 #ifndef ZEPHYR_INCLUDE_DRIVERS_STEPPER_H_
15 #define ZEPHYR_INCLUDE_DRIVERS_STEPPER_H_
16
17 /**
18 * @brief Stepper Controller Interface
19 * @defgroup stepper_interface Stepper Controller Interface
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 #define MICRO_STEP_RES_INDEX(res) LOG2(res)
33
34 /**
35 * @brief Stepper Motor micro step resolution options
36 */
37 enum stepper_micro_step_resolution {
38 /** Full step resolution */
39 STEPPER_MICRO_STEP_1 = 1,
40 /** 2 micro steps per full step */
41 STEPPER_MICRO_STEP_2 = 2,
42 /** 4 micro steps per full step */
43 STEPPER_MICRO_STEP_4 = 4,
44 /** 8 micro steps per full step */
45 STEPPER_MICRO_STEP_8 = 8,
46 /** 16 micro steps per full step */
47 STEPPER_MICRO_STEP_16 = 16,
48 /** 32 micro steps per full step */
49 STEPPER_MICRO_STEP_32 = 32,
50 /** 64 micro steps per full step */
51 STEPPER_MICRO_STEP_64 = 64,
52 /** 128 micro steps per full step */
53 STEPPER_MICRO_STEP_128 = 128,
54 /** 256 micro steps per full step */
55 STEPPER_MICRO_STEP_256 = 256,
56 };
57
58 /**
59 * @brief Stepper Motor direction options
60 */
61 enum stepper_direction {
62 /** Negative direction */
63 STEPPER_DIRECTION_NEGATIVE = 0,
64 /** Positive direction */
65 STEPPER_DIRECTION_POSITIVE = 1,
66 };
67
68 /**
69 * @brief Stepper Motor run mode options
70 */
71 enum stepper_run_mode {
72 /** Hold Mode */
73 STEPPER_RUN_MODE_HOLD = 0,
74 /** Position Mode*/
75 STEPPER_RUN_MODE_POSITION = 1,
76 /** Velocity Mode */
77 STEPPER_RUN_MODE_VELOCITY = 2,
78 };
79
80 /**
81 * @brief Stepper Events
82 */
83 enum stepper_event {
84 /** Steps set using move or set_target_position have been executed */
85 STEPPER_EVENT_STEPS_COMPLETED = 0,
86 /** Stall detected */
87 STEPPER_EVENT_STALL_DETECTED = 1,
88 /** Left end switch status changes to pressed */
89 STEPPER_EVENT_LEFT_END_STOP_DETECTED = 2,
90 /** Right end switch status changes to pressed */
91 STEPPER_EVENT_RIGHT_END_STOP_DETECTED = 3,
92 };
93
94 /**
95 * @cond INTERNAL_HIDDEN
96 *
97 * Stepper motor controller driver API definition and system call entry points.
98 *
99 */
100
101 /**
102 * @brief enable or disable the stepper motor controller.
103 *
104 * @see stepper_enable() for details.
105 */
106 typedef int (*stepper_enable_t)(const struct device *dev, const bool enable);
107
108 /**
109 * @brief Move the stepper motor relatively by a given number of micro_steps.
110 *
111 * @see stepper_move_by() for details.
112 */
113 typedef int (*stepper_move_by_t)(const struct device *dev, const int32_t micro_steps);
114
115 /**
116 * @brief Set the max velocity in micro_steps per seconds.
117 *
118 * @see stepper_set_max_velocity() for details.
119 */
120 typedef int (*stepper_set_max_velocity_t)(const struct device *dev,
121 const uint32_t micro_steps_per_second);
122
123 /**
124 * @brief Set the micro-step resolution
125 *
126 * @see stepper_set_micro_step_res() for details.
127 */
128 typedef int (*stepper_set_micro_step_res_t)(const struct device *dev,
129 const enum stepper_micro_step_resolution resolution);
130
131 /**
132 * @brief Get the micro-step resolution
133 *
134 * @see stepper_get_micro_step_res() for details.
135 */
136 typedef int (*stepper_get_micro_step_res_t)(const struct device *dev,
137 enum stepper_micro_step_resolution *resolution);
138 /**
139 * @brief Set the reference position of the stepper
140 *
141 * @see stepper_set_actual_position() for details.
142 */
143 typedef int (*stepper_set_reference_position_t)(const struct device *dev, const int32_t value);
144
145 /**
146 * @brief Get the actual a.k.a reference position of the stepper
147 *
148 * @see stepper_get_actual_position() for details.
149 */
150 typedef int (*stepper_get_actual_position_t)(const struct device *dev, int32_t *value);
151
152 /**
153 * @brief Move the stepper motor absolutely by a given number of micro_steps.
154 *
155 * @see stepper_move_to() for details.
156 */
157 typedef int (*stepper_move_to_t)(const struct device *dev, const int32_t micro_steps);
158
159 /**
160 * @brief Is the target position fo the stepper reached
161 *
162 * @see stepper_is_moving() for details.
163 */
164 typedef int (*stepper_is_moving_t)(const struct device *dev, bool *is_moving);
165
166 /**
167 * @brief Run the stepper with a given velocity in a given direction
168 *
169 * @see stepper_run() for details.
170 */
171 typedef int (*stepper_run_t)(const struct device *dev, const enum stepper_direction direction,
172 const uint32_t value);
173
174 /**
175 * @brief Callback function for stepper events
176 */
177 typedef void (*stepper_event_callback_t)(const struct device *dev, const enum stepper_event event,
178 void *user_data);
179
180 /**
181 * @brief Set the callback function to be called when a stepper event occurs
182 *
183 * @see stepper_set_event_callback() for details.
184 */
185 typedef int (*stepper_set_event_callback_t)(const struct device *dev,
186 stepper_event_callback_t callback, void *user_data);
187
188 /**
189 * @brief Stepper Motor Controller API
190 */
191 __subsystem struct stepper_driver_api {
192 stepper_enable_t enable;
193 stepper_move_by_t move_by;
194 stepper_set_max_velocity_t set_max_velocity;
195 stepper_set_micro_step_res_t set_micro_step_res;
196 stepper_get_micro_step_res_t get_micro_step_res;
197 stepper_set_reference_position_t set_reference_position;
198 stepper_get_actual_position_t get_actual_position;
199 stepper_move_to_t move_to;
200 stepper_is_moving_t is_moving;
201 stepper_run_t run;
202 stepper_set_event_callback_t set_event_callback;
203 };
204
205 /**
206 * @endcond
207 */
208
209 /**
210 * @brief Enable or Disable Motor Controller
211 *
212 * @param dev pointer to the stepper motor controller instance
213 * @param enable Input enable or disable motor controller
214 *
215 * @retval -EIO Error during Enabling
216 * @retval 0 Success
217 */
218 __syscall int stepper_enable(const struct device *dev, const bool enable);
219
z_impl_stepper_enable(const struct device * dev,const bool enable)220 static inline int z_impl_stepper_enable(const struct device *dev, const bool enable)
221 {
222 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
223
224 return api->enable(dev, enable);
225 }
226
227 /**
228 * @brief Set the micro_steps to be moved from the current position i.e. relative movement
229 *
230 * @details The motor will move by the given number of micro_steps from the current position.
231 * This function is non-blocking.
232 *
233 * @param dev pointer to the stepper motor controller instance
234 * @param micro_steps target micro_steps to be moved from the current position
235 *
236 * @retval -ECANCELED If the stepper is disabled
237 * @retval -EIO General input / output error
238 * @retval 0 Success
239 */
240 __syscall int stepper_move_by(const struct device *dev, int32_t micro_steps);
241
z_impl_stepper_move_by(const struct device * dev,const int32_t micro_steps)242 static inline int z_impl_stepper_move_by(const struct device *dev, const int32_t micro_steps)
243 {
244 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
245
246 return api->move_by(dev, micro_steps);
247 }
248
249 /**
250 * @brief Set the target velocity to be reached by the motor
251 *
252 * @details For controllers such as DRV8825 where you
253 * toggle the STEP Pin, the pulse_length would have to be calculated based on this parameter in the
254 * driver. For controllers where velocity can be set, this parameter corresponds to max_velocity
255 * @note Setting max velocity does not set the motor into motion, a combination of set_max_velocity
256 * and move is required to set the motor into motion.
257 *
258 * @param dev pointer to the stepper motor controller instance
259 * @param micro_steps_per_second speed in micro_steps per second
260 *
261 * @retval -EIO General input / output error
262 * @retval -EINVAL If the requested velocity is not supported
263 * @retval 0 Success
264 */
265 __syscall int stepper_set_max_velocity(const struct device *dev, uint32_t micro_steps_per_second);
266
z_impl_stepper_set_max_velocity(const struct device * dev,const uint32_t micro_steps_per_second)267 static inline int z_impl_stepper_set_max_velocity(const struct device *dev,
268 const uint32_t micro_steps_per_second)
269 {
270 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
271
272 return api->set_max_velocity(dev, micro_steps_per_second);
273 }
274
275 /**
276 * @brief Set the microstep resolution in stepper motor controller
277 *
278 * @param dev pointer to the stepper motor controller instance
279 * @param resolution microstep resolution
280 *
281 * @retval -EIO General input / output error
282 * @retval -ENOSYS If not implemented by device driver
283 * @retval -ENOTSUP If the requested resolution is not supported
284 * @retval 0 Success
285 */
286 __syscall int stepper_set_micro_step_res(const struct device *dev,
287 enum stepper_micro_step_resolution resolution);
288
z_impl_stepper_set_micro_step_res(const struct device * dev,enum stepper_micro_step_resolution resolution)289 static inline int z_impl_stepper_set_micro_step_res(const struct device *dev,
290 enum stepper_micro_step_resolution resolution)
291 {
292 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
293
294 if (api->set_micro_step_res == NULL) {
295 return -ENOSYS;
296 }
297 return api->set_micro_step_res(dev, resolution);
298 }
299
300 /**
301 * @brief Get the microstep resolution in stepper motor controller
302 *
303 * @param dev pointer to the stepper motor controller instance
304 * @param resolution microstep resolution
305 *
306 * @retval -EIO General input / output error
307 * @retval -ENOSYS If not implemented by device driver
308 * @retval 0 Success
309 */
310 __syscall int stepper_get_micro_step_res(const struct device *dev,
311 enum stepper_micro_step_resolution *resolution);
312
z_impl_stepper_get_micro_step_res(const struct device * dev,enum stepper_micro_step_resolution * resolution)313 static inline int z_impl_stepper_get_micro_step_res(const struct device *dev,
314 enum stepper_micro_step_resolution *resolution)
315 {
316 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
317
318 if (api->get_micro_step_res == NULL) {
319 return -ENOSYS;
320 }
321 return api->get_micro_step_res(dev, resolution);
322 }
323
324 /**
325 * @brief Set the reference position of the stepper
326 *
327 * @param dev Pointer to the stepper motor controller instance.
328 * @param value The reference position to set in micro-steps.
329 *
330 * @retval -EIO General input / output error
331 * @retval -ENOSYS If not implemented by device driver
332 * @retval 0 Success
333 */
334 __syscall int stepper_set_reference_position(const struct device *dev, int32_t value);
335
z_impl_stepper_set_reference_position(const struct device * dev,const int32_t value)336 static inline int z_impl_stepper_set_reference_position(const struct device *dev,
337 const int32_t value)
338 {
339 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
340
341 if (api->set_reference_position == NULL) {
342 return -ENOSYS;
343 }
344 return api->set_reference_position(dev, value);
345 }
346
347 /**
348 * @brief Get the actual a.k.a reference position of the stepper
349 *
350 * @param dev pointer to the stepper motor controller instance
351 * @param value The actual position to get in micro_steps
352 *
353 * @retval -EIO General input / output error
354 * @retval -ENOSYS If not implemented by device driver
355 * @retval 0 Success
356 */
357 __syscall int stepper_get_actual_position(const struct device *dev, int32_t *value);
358
z_impl_stepper_get_actual_position(const struct device * dev,int32_t * value)359 static inline int z_impl_stepper_get_actual_position(const struct device *dev, int32_t *value)
360 {
361 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
362
363 if (api->get_actual_position == NULL) {
364 return -ENOSYS;
365 }
366 return api->get_actual_position(dev, value);
367 }
368
369 /**
370 * @brief Set the absolute target position of the stepper
371 *
372 * @details The motor will move to the given micro_steps position from the reference position.
373 * This function is non-blocking.
374 *
375 * @param dev pointer to the stepper motor controller instance
376 * @param micro_steps target position to set in micro_steps
377 *
378 * @retval -ECANCELED If the stepper is disabled
379 * @retval -EIO General input / output error
380 * @retval -ENOSYS If not implemented by device driver
381 * @retval 0 Success
382 */
383 __syscall int stepper_move_to(const struct device *dev, int32_t micro_steps);
384
z_impl_stepper_move_to(const struct device * dev,const int32_t micro_steps)385 static inline int z_impl_stepper_move_to(const struct device *dev, const int32_t micro_steps)
386 {
387 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
388
389 if (api->move_to == NULL) {
390 return -ENOSYS;
391 }
392 return api->move_to(dev, micro_steps);
393 }
394
395 /**
396 * @brief Check if the stepper motor is currently moving
397 *
398 * @param dev pointer to the stepper motor controller instance
399 * @param is_moving Pointer to a boolean to store the moving status of the stepper motor
400 *
401 * @retval -EIO General input / output error
402 * @retval -ENOSYS If not implemented by device driver
403 * @retval 0 Success
404 */
405 __syscall int stepper_is_moving(const struct device *dev, bool *is_moving);
406
z_impl_stepper_is_moving(const struct device * dev,bool * is_moving)407 static inline int z_impl_stepper_is_moving(const struct device *dev, bool *is_moving)
408 {
409 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
410
411 if (api->is_moving == NULL) {
412 return -ENOSYS;
413 }
414 return api->is_moving(dev, is_moving);
415 }
416
417 /**
418 * @brief Run the stepper with a given velocity in a given direction
419 *
420 * @details If velocity > 0, motor shall be set into motion and run incessantly until and unless
421 * stalled or stopped using some other command, for instance, motor_enable(false).
422 * This function is non-blocking.
423 *
424 * @param dev pointer to the stepper motor controller instance
425 * @param direction The direction to set
426 * @param velocity The velocity to set in microsteps per second
427 * - > 0: Run the stepper with the given velocity in a given direction
428 * - 0: Stop the stepper
429 *
430 * @retval -ECANCELED If the stepper is disabled
431 * @retval -EIO General input / output error
432 * @retval -ENOSYS If not implemented by device driver
433 * @retval 0 Success
434 */
435 __syscall int stepper_run(const struct device *dev, enum stepper_direction direction,
436 uint32_t velocity);
437
z_impl_stepper_run(const struct device * dev,const enum stepper_direction direction,const uint32_t velocity)438 static inline int z_impl_stepper_run(const struct device *dev,
439 const enum stepper_direction direction,
440 const uint32_t velocity)
441 {
442 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
443
444 if (api->run == NULL) {
445 return -ENOSYS;
446 }
447 return api->run(dev, direction, velocity);
448 }
449
450 /**
451 * @brief Set the callback function to be called when a stepper event occurs
452 *
453 * @param dev pointer to the stepper motor controller instance
454 * @param callback Callback function to be called when a stepper event occurs
455 * passing NULL will disable the callback
456 * @param user_data User data to be passed to the callback function
457 *
458 * @retval -ENOSYS If not implemented by device driver
459 * @retval 0 Success
460 */
461 __syscall int stepper_set_event_callback(const struct device *dev,
462 stepper_event_callback_t callback, void *user_data);
463
z_impl_stepper_set_event_callback(const struct device * dev,stepper_event_callback_t callback,void * user_data)464 static inline int z_impl_stepper_set_event_callback(const struct device *dev,
465 stepper_event_callback_t callback,
466 void *user_data)
467 {
468 const struct stepper_driver_api *api = (const struct stepper_driver_api *)dev->api;
469
470 if (api->set_event_callback == NULL) {
471 return -ENOSYS;
472 }
473 return api->set_event_callback(dev, callback, user_data);
474 }
475
476 /**
477 * @}
478 */
479
480 #ifdef __cplusplus
481 }
482 #endif
483
484 #include <zephyr/syscalls/stepper.h>
485
486 #endif /* ZEPHYR_INCLUDE_DRIVERS_STEPPER_H_ */
487