---
title: "Advanced Stepper Motor Control for Raspberry Pi Pico: A Complete Guide to Non‑Blocking Implementatio"
url: "https://maker.wiznet.io/ruilixin6/projects/advanced-stepper-motor-control-for-raspberry-pi-pico-a-complete-guide-to-nonblocking-implementatio/"
markdown_url: "https://maker.wiznet.io/ruilixin6/projects/advanced-stepper-motor-control-for-raspberry-pi-pico-a-complete-guide-to-nonblocking-implementatio/md"
type: "UCC: User Created Content"
author: "FreakStudio"
author_url: "https://maker.wiznet.io/ruilixin6/"
original_author: "Freakstudio"
original_url: "https://openwrite.cn/articles/63384/edit"
published: "2026-08-14"
language: "en"
tags: ["pio‑hardware"]
likes: 0
views: 102
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# Advanced Stepper Motor Control for Raspberry Pi Pico: A Complete Guide to Non‑Blocking Implementatio

> This tutorial presents PIO-based stepper motor control on the Feng No.1 board. Different from blocking GPIO software delay driving, the independent PIO

Original author: Freakstudio (source: https://openwrite.cn/articles/63384/edit)

## Article

## **PROJECT DESCRIPTION【Preliminary Note】The original hardware example in this article was written based on the RP2040. The actual hardware used in this hands-on demonstration features the W55RP20 as the main controller chip. The circuit logic and UF2 flashing operation principles are universally applicable, with only the main controller model differing. The original chip model mentioned in the circuit descriptions below is provided for reference purposes only.**

## **![](https://maker.wiznet.io/upload/ckeditor5/820159645%5F1786726503%2Ejpg)PIO Stepper Motor Control**

Here, we use `PIO` to implement single-phase drive control of a stepper motor. In short, single-phase drive control controls the energizing sequence and frequency of the stepper motor's 4 winding pairs, thereby achieving precise control of the motor's rotation angle and speed. For details, refer to the stepper motor introduction in `Section 4 GPIO General Purpose Input/Output`; we will not repeat it here.

As you can see, when driving a stepper motor with `GPIO` before, it was usually necessary to control the pin states in the main program through loops and delays. This approach blocks the main program, preventing the `CPU` from handling other tasks at the same time. `PIO`, in contrast, is an independent hardware peripheral that can run in parallel, so the main program can continue executing other tasks (such as processing sensor data, communication, etc.) while the `PIO` precisely controls the stepper motor.

Moreover, `GPIO` timing control relies on software delays (such as `time.sleep_ms()`), whose accuracy is limited by the operating system's scheduling and `CPU` load. `PIO`, however, can run at a fixed clock frequency, providing more precise timing control.

Here, we use the long-pin headers on the `**Fengya One Board - Universal Compatible Expansion Board**` to connect to the logic input interface on the `**Fengya One Board - Stepper Motor Driver Board**`. The pins used are shown in the following table:

![ScreenShot_2026-06-09_193753_127.png](http://openwrite.cn/uploads/21597/63384/21bf50b9-4424-43f6-b0f2-a88ba525b817.png)

Then connect the logic output interface on the stepper motor driver board to the stepper motor:

![1280X1280 (4).PNG](http://openwrite.cn/uploads/21597/63384/b47679fb-ab3f-4032-b676-315aba4544b2.png)

At the same time, turn on the DIP switches on the `**Fengya One Board - Stepper Motor Driver Board**`:

![1280X1280.PNG](http://openwrite.cn/uploads/21597/63384/7d0cfb38-6e92-4b9a-92ef-865db18e9ca1.png)

The overall connection is shown in the following figure:

![1280X1280 (1).PNG](http://openwrite.cn/uploads/21597/63384/62a2d0aa-3efe-450f-8446-444e96fd3ba2.png)

The following code can be found in the `elegance-devkit v1\Demo\34 PIO_StepMotor` folder in our resource package.

The sample code is as follows:

```
# Python env   : MicroPython v1.23.0
# -*- coding: utf-8 -*-        
# @Time    : 2024/7/27 1:07 PM   
# @Author  : Li Qingshui            
# @File    : main.py       
# @Description : PIO experiment: control a stepper motor through PIO
​
# ======================================== Import related modules ========================================
​
# Import hardware-related modules
from machine import Pin
# Import PIO-related modules
import rp2
# Import time-related modules
import time
​
# ======================================== Global variables ============================================
​
# ======================================== Function definitions ============================================
​
# The @rp2.asm_pio decorator is used to define a PIO program
# Here, it sets the initial state of the 4 GPIO pins to low level; these four pins are the set pins
@rp2.asm_pio(set_init=(rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW,
                       rp2.PIO.OUT_LOW, rp2.PIO.OUT_LOW))
def step_motor() -> None:
    """
    Define the PIO program for stepper motor control.
​
    Args:
        None
​
    Returns:
        None
​
    Description:
        This PIO program controls the rotation of the stepper motor by setting the states of the 4 GPIO pins.
        Each pin is set to high level in turn while the other pins are set to low level, forming the single-phase control sequence of the stepper motor.
    """
    # Mark the jump destination of the program
    wrap_target()
    # Set the first pin to high level and the other pins to low level; the trailing [7] means a delay of 7 clock cycles after this instruction
    # Considering that the set instruction itself takes 1 cycle, the interval between each step of the stepper motor is 1 + 7 = 8 clock cycles
    set(pins, 0b0001)   [7]
    # Set the states of the other 3 pins in turn to form the complete single-phase control sequence of the stepper motor
    set(pins, 0b0010)   [7]
    set(pins, 0b0100)   [7]
    set(pins, 0b1000)   [7]
    # Jump the program execution back to wrap_target()
    wrap()
​
# ======================================== Custom classes ============================================
​
# ======================================== Initialization configuration ==========================================
​
# Delay 3s at power-up
time.sleep(3)
# Print debug information
print("FreakStudio: Using PIO to control step motor")
​
# Initialize the state machine instance: use state machine 0 to run the step_motor() function; the PIO execution frequency equals the system clock frequency / 2000
# Set the base pin (the first pin in the series) to GPIO 2
sm = rp2.StateMachine(0, step_motor, freq=2000, set_base=Pin(2))
sm.active(1)
​
# ======================================== Main program ===========================================
​
while True:
    pass
```

Here, in the PIO program, we use the `set` instruction to write 4-bit binary data to control the energizing of the stepper motor's 4 winding pairs (setting a pin to high level energizes 1 winding pair):

![ScreenShot_2026-06-09_193833_440.png](http://openwrite.cn/uploads/21597/63384/331b96bc-c198-47d0-a85b-3fbef58a0b8b.png)

We can also use the `set` instruction to write decimal 1, 2, 4, 8 or hexadecimal 0x1, 0x2, ..., with the same effect.

After flashing the code, you can see the stepper motor rotating. Through the use of the PIO peripheral, we have achieved non-blocking driving of the stepper motor:

![9f458cbf-e5dc-48e5-9346-5e93cbe98c91.png](http://openwrite.cn/uploads/21597/63384/474e47d9-510a-4804-8845-f12ac8c0431c.png)

![4a2f2f2b-9ac4-4c10-a913-e16398a38003.jfif](http://openwrite.cn/uploads/21597/63384/64d5f1e5-b49f-466a-8ccd-3cfc98e16e76.jfif)

---

Source: https://maker.wiznet.io/ruilixin6/projects/advanced-stepper-motor-control-for-raspberry-pi-pico-a-complete-guide-to-nonblocking-implementatio/
