element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Raspberry Pi
  • Products
  • More
Raspberry Pi
Blog Raspberry PIO stepper library documentation - 1: intro, set up project and simple example
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Raspberry Pi to participate - click to join for free!
Featured Articles
Announcing Pi
Technical Specifications
Raspberry Pi FAQs
Win a Pi
GPIO Pinout
Raspberry Pi Wishlist
Comparison Chart
Quiz
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 18 Apr 2025 1:01 PM Date Created
  • Views 1403 views
  • Likes 5 likes
  • Comments 12 comments
Related
Recommended
  • raspberry
  • pico_pio_stepper_lib
  • pico
  • PIO
  • stepper-motor
  • c++

Raspberry PIO stepper library documentation - 1: intro, set up project and simple example

Jan Cumps
Jan Cumps
18 Apr 2025

Raspberry PIO stepper library (pio_stepper_lib) is a C++ library that runs stepper motors in PIO state machines. It's intended to be easy to integrate and use in Pico projects.

  • 4 motors can be controlled per PIO
  • can be used with any stepper motor driver that supports STEP and DIR operation
  • can handle as many commands as PIO FIFO accepts without waiting (default 8).
  • each command can autonomously handle 2147483647 steps, and the spin direction
  • can notify the calling program when a command has finished
  • can report how many commands it processed

Add the library to your Pico project

The library has its own CMake script. You add it to your own project by fetching it in your CMakeFiles.txt. It is then available to your code as a library.

Fetch and make available

# your CMakeFiles.txt
# ...

include(FetchContent)
FetchContent_Declare(stepper
  GIT_REPOSITORY "https://github.com/jancumps/pio_stepper_lib.git"
  GIT_TAG "origin/main"
)
FetchContent_MakeAvailable(stepper)

# ...

Link with your firmware executable

# add stepper as a library to your executable
add_executable(your_stepper_project)
# ...
target_link_libraries(your_stepper_project
  pico_stdlib
  hardware_gpio
  stepper
)

That's it. When building your project, CMake will fetch the stepper code from GitHub, and build the stepper library.
The look and feel is identical to adding, say, hardware_spi. Something you will be familiar with.
No includes need to be defined, or sources individually added. It's all handled in the few lines in the make script above.
This will work if you use and IDE such as VSCode, CLion, Eclipse. And if you build from the Linux or Windows command line.

First project: simple stepper

This Pico firmware example will define a stepper motor, and will make it take 400 steps clockwise.

Resources used

pins

dir: gpio4
step: gpio5

PIO

pio 1
state machine 2
divide pio clock by 16

stepper lib 1 instance of class stepper_controller
other your stepper motor driver IC may require other resources, such as gpio for  enable, reset, ...

Use the library  and create the motor

#include "pico/stdlib.h"

// the PIOs are declared here
// and we select one (or more) of those
// to run the motor state machine(s) on
#include "hardware/pio.h"

import stepper; // PIO stepper lib

// pins
const uint dir = 4U; // implies that step is gpio 5

// config what PIO, SM to use
const auto piostep = pio1;
const uint sm = 2U;

const float clock_divider = 16.0; // works well with full steps

using motor_t = stepper::stepper_controller;
motor_t motor1(piostep, sm);

We now have motor1, that we 'll use in our firmware.

PIO and stepper setup

All PIO activities are handled by the library. You invoke them by taking these steps:

We 'll first tell the motor class to load its firmware into the selected PIO. This is an activity that needs to be done one time for each PIO used.
In this example, we only use PIO1. It can host 4 motors. If you want more motors, you can also use PIO0.
And if you have a Pico 2, there's an additional PIO that enables you to control maximum 12 motors.

Then, we configure each motor. That takes care that the class sets up its PIO state machine and enables it.

void init_pio() {
    // program the pio used for the motors
    // do this only once per used pio
    motor_t::pio_program(piostep);

    // initialise and enable the motor state machine
    motor1.pio_init(dir, clock_divider);
    motor1.enable(true);
}

You call this function at the start of your program. From then on, all is ready to use.

the main function

int main() {
    init_pio();
    motor1.set_delay(4500); // this is fast
    
    motor1.take_steps({400, false}); // 400 steps clockwise
    sleep_ms(2000); // wait for the motor to complete
   
    return 0;
}

motor speed: The delay takes care that we slow down the steps that are sent to the motor driver.
At the start of the program we already slowed down the PIO clock. I set the clock to a frequency that's not crazy, but fast enough to give us good speed finetune resolution.
In main(), I set a particular delay for the next commands. The higher the delay, the slower the motor will run.
With my motor, when I use full steps, I set the divider to 16. When using 8 microsteps per step, I set it to 3.
In both cases, a delay of 4500 is then about the fastest the motor can step, with little load.

classes used

image

where to find the code

The pio_stepper_lib is hosted on GitHub. You don't need to clone or build it, to use the library in your project. CMake does that for you.

A working project, using the Texas Instruments DRV8711 as stepper driver, is also in GitHub.
I took care to clearly define where driver specific code is used, in case your hardware uses another one.
If you like to read up on the example's history, and for wiring information, start here: Stepper Motor Control with Raspberry Pico PIO and DRV8711 driver- Part 1: Hardware Provisioning..
If you get a build error, check the toolchain requirements.

next chapter: get notification when the motor has executed a command

view all posts

  • Sign in to reply
  • Jan Cumps
    Jan Cumps 2 months ago in reply to Jan Cumps

    I got around the RISC limitation. They released a fairly recent toolchain:  RISCV_ZCB_RPI_2_1_1_3. Available via the plugin

    It supports C++ modules, but has some bugs, that are since fixed in GCC proper: https://gcc.gnu.org/pipermail/gcc-patches/2024-October/665109.html#:~:text=This%20patch%20leaves%20a%20couple,):%20...this.%20(

    I worked around that for the moment, by defining this contraption:

    // this is to work around RISC compiler bug solved in 14.2
    // https://gcc.gnu.org/pipermail/gcc-patches/2024-October/665109.html#:~:text=This%20patch%20leaves%20a%20couple,):%20...this.%20(
    // TODO once fixed, replace TRANSLATION_BUG_INLINE with inline
    #define TRANSLATION_BUG_INLINE
    And replacing inlines that suffer from this issue, by TRANSLATION_BUG_INLINE

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps 2 months ago

    For the Pico2 fans that want to use the 3rd PIO engine that's available on that chip: I created a (probably temporary) branch on GitHub to test how well my PIO design behaves on that 3rd co-controller: https://github.com/jancumps/pio_drv8711_stepper/tree/pico2-risk

    I've configured it for ARM architecture. It would work equally good on RISC, but Raspberry's custom GCC toolchain for Pico-RISK hasn't caught up with GCC proper at this time.
    For ARM, they don't need a proprietary toolchain. GCC mainstream ARM version does the job. For the RISK cores, they seem to require a custom-built-by-them GCC at the moment.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps 5 months ago in reply to shabaz

    a few posts that will help:

    • the multiple motor firmware design explained:  Raspberry PIO stepper library documentation - 3: control multiple motors with 1 or more PIOs 
    • clock divider, delay, and stepper frequency explained:  Raspberry PIO stepper library documentation - 4: understand the step frequency 
    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps 5 months ago in reply to Jan Cumps

    ... and 2 motors running in parallel at different speeds:

    image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • DAB
    DAB 5 months ago

    Nice update Jan.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube