Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/stepper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
add_subdirectory_ifdef(CONFIG_STEPPER_ADI_TMC adi_tmc)
add_subdirectory_ifdef(CONFIG_STEPPER_TI ti)
add_subdirectory_ifdef(CONFIG_STEP_DIR_STEPPER step_dir)
add_subdirectory_ifdef(CONFIG_STEPPER_ALLEGRO allegro)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pancakem perhaps we can move this to an alphabetical order to avoid the warnings?

# zephyr-keep-sorted-stop

Check failure on line 11 in drivers/stepper/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

KeepSorted

drivers/stepper/CMakeLists.txt:11 sorted block has out-of-order line at 10

zephyr_library()
zephyr_library_property(ALLOW_EMPTY TRUE)
Expand Down
1 change: 1 addition & 0 deletions drivers/stepper/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
rsource "Kconfig.gpio"
rsource "adi_tmc/Kconfig"
rsource "ti/Kconfig"
rsource "allegro/Kconfig"
# zephyr-keep-sorted-stop

Check failure on line 39 in drivers/stepper/Kconfig

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

KeepSorted

drivers/stepper/Kconfig:39 sorted block has out-of-order line at 38

endif
7 changes: 7 additions & 0 deletions drivers/stepper/allegro/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Marvin Ouma
# SPDX-License-Identifier: Apache-2.0

zephyr_library()
zephyr_library_property(ALLOW_EMPTY TRUE)

zephyr_library_sources_ifdef(CONFIG_A4988 a4988.c)
8 changes: 8 additions & 0 deletions drivers/stepper/allegro/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Marvin Ouma
# SPDX-License-Identifier: Apache-2.0

config STEPPER_ALLEGRO
bool
depends on STEPPER

rsource "Kconfig.a4988"
12 changes: 12 additions & 0 deletions drivers/stepper/allegro/Kconfig.a4988
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Marvin Ouma
# SPDX-License-Identifier: Apache-2.0

config A4988
bool "A4988 DMOS Microstepping Driver"

Check warning on line 5 in drivers/stepper/allegro/Kconfig.a4988

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/stepper/allegro/Kconfig.a4988:5 please, no spaces at the start of a line
default y

Check warning on line 6 in drivers/stepper/allegro/Kconfig.a4988

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/stepper/allegro/Kconfig.a4988:6 please, no spaces at the start of a line
depends on DT_HAS_ALLEGRO_A4988_ENABLED

Check warning on line 7 in drivers/stepper/allegro/Kconfig.a4988

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/stepper/allegro/Kconfig.a4988:7 please, no spaces at the start of a line
select STEPPER_ALLEGRO

Check warning on line 8 in drivers/stepper/allegro/Kconfig.a4988

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/stepper/allegro/Kconfig.a4988:8 please, no spaces at the start of a line
select STEP_DIR_STEPPER

Check warning on line 9 in drivers/stepper/allegro/Kconfig.a4988

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/stepper/allegro/Kconfig.a4988:9 please, no spaces at the start of a line
select STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS

Check warning on line 10 in drivers/stepper/allegro/Kconfig.a4988

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/stepper/allegro/Kconfig.a4988:10 please, no spaces at the start of a line
help

Check warning on line 11 in drivers/stepper/allegro/Kconfig.a4988

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/stepper/allegro/Kconfig.a4988:11 please, no spaces at the start of a line
Enable A4988 DMOS Microstepping Driver.

Check warning on line 12 in drivers/stepper/allegro/Kconfig.a4988

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

drivers/stepper/allegro/Kconfig.a4988:12 please, no spaces at the start of a line
220 changes: 220 additions & 0 deletions drivers/stepper/allegro/a4988.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 Marvin Ouma
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT allegro_a4988

#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/stepper.h>
#include "../step_dir/step_dir_stepper_common.h"

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(a4988, CONFIG_STEPPER_LOG_LEVEL);

#define MSX_PIN_COUNT 3
#define MSX_PIN_STATE_COUNT 5

static enum stepper_micro_step_resolution a4988_msx_resolutions[MSX_PIN_STATE_COUNT] = {
STEPPER_MICRO_STEP_1, STEPPER_MICRO_STEP_2, STEPPER_MICRO_STEP_4,
STEPPER_MICRO_STEP_8, STEPPER_MICRO_STEP_16,
};

struct a4988_config {
struct step_dir_stepper_common_config common;
struct gpio_dt_spec sleep_pin;
struct gpio_dt_spec enable_pin;
struct gpio_dt_spec reset;
struct gpio_dt_spec *msx_pins;
enum stepper_micro_step_resolution *msx_resolutions;
};

struct a4988_data {
struct step_dir_stepper_common_data common;
enum stepper_micro_step_resolution resolution;
};

STEP_DIR_STEPPER_STRUCT_CHECK(struct a4988_config, struct a4988_data);

static int a4988_stepper_enable(const struct device *dev, const bool enable)
{
/* enable and sleep pins need to be set logic low to be on */
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Pancakem the data sheet seems not to agree on this see page 10 on here https://www.pololu.com/file/download/A4988.pdf?file_id=0J450

const struct a4988_config *config = dev->config;
int ret;

if (config->sleep_pin.port != NULL) {
ret = gpio_pin_set_dt(&config->sleep_pin, enable);
if (ret < 0) {
LOG_WRN("Failed to set sleep pin %d", ret);
}
}

LOG_DBG("Stepper motor controller %s %s", dev->name, enable ? "enabled" : "disabled");
return gpio_pin_set_dt(&config->enable_pin, !enable);
}

/* Set microstepping mode
*
*/
static int a4988_stepper_set_micro_step_res(const struct device *dev,
enum stepper_micro_step_resolution micro_step_res)
{
struct a4988_data *data = dev->data;
const struct a4988_config *config = dev->config;
int ret;

if (!config->msx_pins) {
LOG_ERR("Microstep resolution pins are not configured");
return 0; // NOT CONNECTED

Check failure on line 70 in drivers/stepper/allegro/a4988.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

drivers/stepper/allegro/a4988.c:70 do not use C99 // comments
}

for (uint8_t i = 0; i < MSX_PIN_STATE_COUNT; ++i) {
if (micro_step_res != config->msx_resolutions[i]) {
continue;
}

ret = gpio_pin_set_dt(&config->msx_pins[0], i & 0x01);
if (ret < 0) {
LOG_ERR("Failed to set MS1 pin: %d", ret);
return ret;
}

ret = gpio_pin_set_dt(&config->msx_pins[1], (i & 0x02) >> 1);
if (ret < 0) {
LOG_ERR("Failed to set MS2 pin: %d", ret);
return ret;
}

ret = gpio_pin_set_dt(&config->msx_pins[2], (i & 0x04) >> 1);
if (ret < 0) {
LOG_ERR("Failed to set MS3 pin: %d", ret);
return ret;
}

data->resolution = micro_step_res;
return 0;
}

LOG_ERR("Unsupported microstep resolution: %d", micro_step_res);
return -EINVAL;
}

static int a4988_stepper_configure_msx_pins(const struct device *dev)
{
const struct a4988_config *config = dev->config;
int ret;

for (uint8_t i = 0; i < MSX_PIN_COUNT; i++) {
if (!gpio_is_ready_dt(&config->msx_pins[i])) {
LOG_ERR("MSX pin %u is not ready", i);
return -ENODEV;
}

ret = gpio_pin_configure_dt(&config->msx_pins[i], GPIO_OUTPUT);
if (ret < 0) {
LOG_ERR("Failed to configure msx pin %u", i);
return ret;
}
}
return 0;
}

static int a4988_stepper_get_micro_step_res(const struct device *dev,
enum stepper_micro_step_resolution *micro_step_res)
{

struct a4988_data *data = dev->data;
*micro_step_res = data->resolution;
return 0;
}

static int a4988_stepper_init(const struct device *dev)
{
const struct a4988_config *config = dev->config;
const struct a4988_data *data = dev->data;
int ret;

if (config->sleep_pin.port != NULL) {
ret = gpio_pin_configure_dt(&config->sleep_pin, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
LOG_ERR("Failed to configure sleep pin: %d", ret);
return -ENODEV;
}
}

if (!gpio_is_ready_dt(&config->enable_pin)) {
LOG_ERR("GPIO pins are not ready");
return -ENODEV;
}

ret = gpio_pin_configure_dt(&config->enable_pin, GPIO_OUTPUT);
if (ret < 0) {
LOG_ERR("Failed to configure enable pin: %d", ret);
return ret;
}

if (config->msx_pins) {
ret = a4988_stepper_configure_msx_pins(dev);
if (ret < 0) {
LOG_ERR("Failed to configure MSX pins: %d", ret);
return ret;
}

ret = a4988_stepper_set_micro_step_res(dev, data->resolution);
if (ret < 0) {
LOG_ERR("Failed to set microstep resolution: %d", ret);
return ret;
}
}

ret = step_dir_stepper_common_init(dev);
if (ret < 0) {
LOG_ERR("Failed to init step dir common stepper: %d", ret);
return ret;
}
return 0;
}

static DEVICE_API(stepper, a4988_stepper_api) = {
.enable = a4988_stepper_enable,
.move_by = step_dir_stepper_common_move_by,
.is_moving = step_dir_stepper_common_is_moving,
.set_reference_position = step_dir_stepper_common_set_reference_position,
.get_actual_position = step_dir_stepper_common_get_actual_position,
.move_to = step_dir_stepper_common_move_to,
.set_microstep_interval = step_dir_stepper_common_set_microstep_interval,
.run = step_dir_stepper_common_run,
.set_event_callback = step_dir_stepper_common_set_event_callback,
.set_micro_step_res = a4988_stepper_set_micro_step_res,
.get_micro_step_res = a4988_stepper_get_micro_step_res,
};

#define A4988_STEPPER_DEFINE(inst, msx_table) \

Check warning on line 194 in drivers/stepper/allegro/a4988.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/stepper/allegro/a4988.c:194 line length of 102 exceeds 100 columns
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, msx_gpios), ( \
static const struct gpio_dt_spec a4988_stepper_msx_pins_##inst[] = { \
DT_INST_FOREACH_PROP_ELEM_SEP( \
inst, msx_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,) \
), \
}; \
BUILD_ASSERT( \
ARRAY_SIZE(a4988_stepper_msx_pins_##inst) == MSX_PIN_COUNT, \
"Three microstep config pins needed"); \

Check warning on line 203 in drivers/stepper/allegro/a4988.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/stepper/allegro/a4988.c:203 line length of 102 exceeds 100 columns
)) \
\
static const struct a4988_config a4988_config_##inst = { \
.common = STEP_DIR_STEPPER_DT_INST_COMMON_CONFIG_INIT(inst), \
.enable_pin = GPIO_DT_SPEC_INST_GET(inst, en_gpios), \
.msx_resolutions = msx_table, \
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, msx_gpios), \
(.msx_pins = (struct gpio_dt_spec *)a4988_stepper_msx_pins_##inst)) }; \
static struct a4988_data a4988_data_##inst = { \
.common = STEP_DIR_STEPPER_DT_INST_COMMON_DATA_INIT(inst), \
.resolution = DT_INST_PROP(inst, micro_step_res), \
}; \
DEVICE_DT_INST_DEFINE(inst, a4988_stepper_init, NULL, &a4988_data_##inst, \
&a4988_config_##inst, POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \
&a4988_stepper_api);

DT_INST_FOREACH_STATUS_OKAY_VARGS(A4988_STEPPER_DEFINE, a4988_msx_resolutions)
47 changes: 47 additions & 0 deletions dts/bindings/stepper/allegro/allegro,a4988.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Marvin Ouma
# SPDX-License-Identifier: Apache-2.0

description: |
Allegro A4988 stepper motor driver.

Example:
a4988: a4988 {
status = "okay";
compatible = "allegro,a4988";

step-gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
dir-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
en-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
msx-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>,
<&gpio0 17 GPIO_ACTIVE_HIGH>,
<&gpio0 5 GPIO_ACTIVE_HIGH>;
};

compatible: "allegro,a4988"

include:
- name: stepper-controller.yaml
property-allowlist:
- micro-step-res
- step-gpios
- dir-gpios
- en-gpios


properties:
msx-gpios:
type: phandle-array
description: |
An array of GPIO pins for configuring the microstep resolution of the driver.
The pins should be listed in the following order:
- MS1
- MS2
- MS3

sleep-gpios:
type: phandle-array
description: Sleep pin

reset-gpios:
type: phandle-array
description: Reset pin
10 changes: 10 additions & 0 deletions samples/drivers/stepper/a4988/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Marvin Ouma
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(a4988)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
11 changes: 11 additions & 0 deletions samples/drivers/stepper/a4988/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Marvin Ouma
# SPDX-License-Identifier: Apache-2.0

mainmenu "A4988 sample application"

config STEPS_PER_REV
int "Steps per revolution"
default 200


source "Kconfig.zephyr"
23 changes: 23 additions & 0 deletions samples/drivers/stepper/a4988/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.. zephyr:code-sample:: stepper/a4988
:name: A4988 Stepper Driver
:relevant-api: stepper_interface

Rotate a A4988 stepper motor.

Overview
********

This sample applications rotates the A4988 stepper motor at a constant speed.


Building and Running
********************

The sample applications spins the stepper and outputs the events to the console. It requires
an A4988 stepper driver. It should work with any platform with enough gpios to spare.
It does not work on QEMU.

.. zephyr-app-commands::
:zephyr-app: samples/drivers/stepper/a4988
:board: stm32_min_dev
:goals: build flash
32 changes: 32 additions & 0 deletions samples/drivers/stepper/a4988/boards/stm32_min_dev.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/ {

chosen {
zephyr,console=&cdc_acm_uart0;
};

aliases {
stepper = &a4988;
};

a4988: a4988 {
compatible = "allegro,a4988";
status = "okay";

step-gpios = <&gpiob 45 GPIO_ACTIVE_HIGH>;
dir-gpios = <&gpiob 46 GPIO_ACTIVE_HIGH>;
en-gpios = <&gpioa 38 GPIO_ACTIVE_LOW>;
sleep-gpios = <&gpiob 43 GPIO_ACTIVE_LOW>;
reset-gpios = <&gpiob 42 GPIO_ACTIVE_HIGH>;
msx-gpios = <&gpiob 39 GPIO_ACTIVE_HIGH>,
<&gpiob 40 GPIO_ACTIVE_HIGH>,

Check failure on line 21 in samples/drivers/stepper/a4988/boards/stm32_min_dev.overlay

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

CODE_INDENT

samples/drivers/stepper/a4988/boards/stm32_min_dev.overlay:21 code indent should use tabs where possible
<&gpiob 41 GPIO_ACTIVE_HIGH>;

Check failure on line 22 in samples/drivers/stepper/a4988/boards/stm32_min_dev.overlay

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

CODE_INDENT

samples/drivers/stepper/a4988/boards/stm32_min_dev.overlay:22 code indent should use tabs where possible
micro-step-res = <16>;
};
};

&zephyr_udc0 {
cdc_acm_uart0: cdc_acm_uart0 {
compatible = "zephyr,cdc-acm-uart";

Check failure on line 29 in samples/drivers/stepper/a4988/boards/stm32_min_dev.overlay

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

CODE_INDENT

samples/drivers/stepper/a4988/boards/stm32_min_dev.overlay:29 code indent should use tabs where possible
label = "CDC_ACM_0";
};
};
Loading
Loading