samples: stepper: add tmc50xx sample

Add a minimal tmc50xx sample with spi interface

Signed-off-by: Jilay Pandya <jilay.pandya@outlook.com>
This commit is contained in:
Jilay Pandya 2025-02-09 19:36:41 +01:00 committed by Benjamin Cabé
parent 2c25211ede
commit 93b53efbe3
8 changed files with 199 additions and 0 deletions

View File

@ -0,0 +1,5 @@
.. zephyr:code-sample-category:: stepper
:name: Stepper
:show-listing:
These samples demonstrate how to use the :ref:`stepper <stepper_api>` driver API.

View File

@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(tmc50xx)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View File

@ -0,0 +1,18 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya
# SPDX-License-Identifier: Apache-2.0
mainmenu "TMC50XX sample application"
config STEPS_PER_REV
int "Steps per revolution"
default 200
config PING_PONG_N_REV
int "Change direction every N revolutions"
default 1
config MAX_VELOCITY_MULTIPLIER
int "Max velocity multiplier"
default 1
source "Kconfig.zephyr"

View File

@ -0,0 +1,49 @@
.. zephyr:code-sample:: tmc50xx
:name: TMC50XX stepper
:relevant-api: stepper_interface
Rotate a TMC50XX stepper motor and change velocity at runtime.
Description
***********
This sample application periodically spins the stepper clockwise and counterclockwise depending on
the :kconfig:option:`CONFIG_PING_PONG_N_REV` configuration.
References
**********
- TMC5041: https://www.analog.com/media/en/technical-documentation/data-sheets/TMC5041_datasheet_rev1.16.pdf
- TMC5072: https://www.analog.com/media/en/technical-documentation/data-sheets/TMC5072_datasheet_rev1.26.pdf
Wiring
*******
This sample uses the TMC5072 BOB controlled using the SPI interface. The board's Devicetree must define
a ``stepper`` alias for the stepper motor node.
Building and Running
********************
This project spins the stepper and outputs the events to the console. It requires an TMC50XX stepper
driver. It should work with any platform featuring a SPI peripheral interface.
It does not work on QEMU.
.. zephyr-app-commands::
:zephyr-app: samples/drivers/stepper/tmc50xx
:board: nucleo_g071rb
:goals: build flash
Sample Output
=============
.. code-block:: console
Starting tmc50xx stepper sample
stepper is 0x8007240, name is tmc_stepper@0
stepper_callback steps completed changing direction
stepper_callback steps completed changing direction
stepper_callback steps completed changing direction
<repeats endlessly>

View File

@ -0,0 +1,52 @@
/ {
aliases {
stepper = &tmc_stepper;
};
};
&spi1 {
pinctrl-0 = <&spi1_sck_pa5 &spi1_miso_pa6 &spi1_mosi_pa7>;
pinctrl-names = "default";
cs-gpios = <&gpiob 0 GPIO_ACTIVE_LOW>;
status = "okay";
tmc50xx: tmc50xx@0 {
compatible = "adi,tmc50xx";
reg = <0>;
spi-max-frequency = <DT_FREQ_M(1)>; /* Maximum SPI bus frequency */
#address-cells = <1>;
#size-cells = <0>;
clock-frequency = <DT_FREQ_M(10)>; /* Internal/External Clock frequency */
tmc_stepper: tmc_stepper@0 {
status = "okay";
reg = <0>;
/* common stepper controller settings */
micro-step-res = <256>;
/* ADI TMC stallguard settings specific to TMC50XX */
activate-stallguard2;
stallguard-velocity-check-interval-ms=<1000>;
stallguard2-threshold=<30>;
stallguard-threshold-velocity=<200000>;
/* ADI TMC ramp generator as well as current settings */
vstart = <1000>;
vstop = <10>;
a1 = <10000>;
v1 = <50000>;
d1 = <14000>;
vmax = <900000>;
amax = <50000>;
dmax = <7000>;
tzerowait = <100>;
vhigh = <900000>;
vcoolthrs = <900000>;
ihold = <1>;
irun = <10>;
iholddelay = <1>;
};
};
};

View File

@ -0,0 +1,2 @@
CONFIG_STEPPER=y
CONFIG_LOG=y

View File

@ -0,0 +1,8 @@
sample:
name: TMC50XX Stepper Sample
tests:
sample.stepper.tmc50xx:
harness: stepper
tags: stepper
platform_allow: nucleo_g071rb
depends_on: spi

View File

@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya.
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/stepper.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/stepper/stepper_trinamic.h>
const struct device *stepper = DEVICE_DT_GET(DT_ALIAS(stepper));
int32_t ping_pong_target_position = CONFIG_STEPS_PER_REV * CONFIG_PING_PONG_N_REV *
DT_PROP(DT_ALIAS(stepper), micro_step_res);
K_SEM_DEFINE(steps_completed_sem, 0, 1);
void stepper_callback(const struct device *dev, const enum stepper_event event, void *user_data)
{
switch (event) {
case STEPPER_EVENT_STEPS_COMPLETED:
k_sem_give(&steps_completed_sem);
break;
default:
break;
}
}
int main(void)
{
printf("Starting tmc50xx stepper sample\n");
if (!device_is_ready(stepper)) {
printf("Device %s is not ready\n", stepper->name);
return -ENODEV;
}
printf("stepper is %p, name is %s\n", stepper, stepper->name);
stepper_set_event_callback(stepper, stepper_callback, NULL);
stepper_enable(stepper, true);
stepper_set_reference_position(stepper, 0);
stepper_move_by(stepper, ping_pong_target_position);
/* Change Max Velocity during runtime */
int32_t tmc_velocity = DT_PROP(DT_ALIAS(stepper), vmax) * CONFIG_MAX_VELOCITY_MULTIPLIER;
(void)tmc50xx_stepper_set_max_velocity(stepper, tmc_velocity);
for (;;) {
if (k_sem_take(&steps_completed_sem, K_FOREVER) == 0) {
ping_pong_target_position *= -1;
stepper_move_by(stepper, ping_pong_target_position);
}
}
return 0;
}