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 & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • 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
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • 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 2344 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 over 1 year ago in reply to shabaz

    > Small typo

    fixed

    > If 4 motors were to be controlled, would you create three more motor_t instances using the other unused sm values between 0-3

    Yes. And if you want to use 5, then you 'd need to start using the other PIO too. It doesn't make a difference for the motors - there's no inter-dependency between the state machines.

    There's a PIO requirement that the 2 pins have to be consecutive for a particular motor. If DIR pin is GPIO4, then STEP pin has to be GPIO5. But for the next motor you could use (say) pins 9 and 10.

    example:

    motor_t motor1(pio1, 0, 4);
    motor_t motor2(pio1, 1, 9);

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 1 year ago

    Advanced use of CMake : ) I didn't know it could fetch the library. That simplifies things greatly!

    Small typo, regarding the text:

    • can be used with any stepper motor driver that supports PIN and DIR operation

    you meant this I think:

    • can be used with any stepper motor driver that supports STEP and DIR operation

    If 4 motors were to be controlled, would you create three more motor_t instances using the other unused sm values between 0-3, and then which pins would control the step output for the additional motors? 

    • 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 © 2026 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