总线单极性步进电机驱动板
摘要
总线单极性步进电机扩展板采用紧凑型设计,兼容XIAO系列主控板直连或独立使用,支持级联16个模块。板载ULN2003达林顿管驱动芯片(单通道500mA/整片2.5A),可适配28BYJ-48等5线4相步进电机(5-24V宽压供电),提供单步/全步/半步三种驱动模式,配备双固态电容稳压、防反接保护和可视化状态指示灯,兼具堆叠扩展能力与高可靠性。
1.总体介绍




总线单极性步进电机扩展板是一种用于通过串行通信接口 I2C 来控制多个单极性步进电机(例如 28BYJ48、35BYJ46、35BY412L 等五线四相步进电机)的扩展模块,具有以下主要特点:
- 小尺寸设计:可以与 XIAO 系列主控板、Adafruit Qt Py 系列主控直接连接,也可以作为独立模块使用。
- I2C 接口:提供 I2C 总线接口,可堆叠式进行级联,同时 4 个地址位可选择,理论上可级联 16 个步进电机驱动扩展板。
- **板载供电指示灯:**电机供电和 PWM 扩展芯片供电。
- 供电保护设计:支持接线端子和 Type-C 接口供电,防反接设计。
- **可靠供电稳压:**使用 2 颗 220UF 固态电解电容供电稳压,相比于铝电解电容,固态电解电容具有更低的 ESR(等效串联电阻)、更高的工作频率和更长的使用寿命。
- **支持多种单极性步进电机:**可用于驱动不同外径、减速比、供电电压的 5 线 4 相单极性步进电机(例如 28BYJ-48),电压范围支持 5V~24V,ULN2003 达林顿管芯片每个通道的最大输出电流为 500mA,单个芯片的总电流限制为 2.5A
- **不同驱动模式支持:**支持单步驱动、全步驱动和半步驱动方式、带有多个步进电机通道的 LED 指示灯。
总线单极性步进电机扩展板采用紧凑型设计,兼容 XIAO 系列主控板直连或独立使用,支持级联 16 个模块。板载 ULN2003 达林顿管驱动芯片(单通道 500mA/整片 2.5A),可适配 28BYJ-48 等 5 线 4 相步进电机(5-24V 宽压供电),提供单步/全步/半步三种驱动模式,配备双固态电容稳压、防反接保护和可视化状态指示灯,兼具堆叠扩展能力与高可靠性。
我们提供了 MicroPython 的示例代码,具有完善的异常检测机制,支持多电机独立控制。


设计原因如下所示:

设计思路类似 I2C 总线电机驱动板:


设计时考虑的因素:

步进电机的基础知识点包括以下内容:




2.接口说明
2.1 通信接口
我们提供了两个 I2C 通信接口,当作为单独模块使用时,通过 PH2.0 连接线连接主控模块和扩展板,如下图所示:

也可以使用主控板直接插入到扩展板的排母接口上:

多个扩展板也可以堆叠连接,此时使用扩展板下方靠近供电端子部分的 I2C 通信接口与扩展板上方靠近供电端子部分的 I2C 通信接口相互连接,连接时需要注意线序,这里需要使用 PH2.0 双头反向连接线,我们这里使用 M2 塑料柱将两个扩展板进行固定:

2.2 步进电机接口
本扩展板采用 XH2.54-5P 接口连接 5 线 4 相单极性步进电机(如 28BYJ-48),此标准化接口设计可兼容市面上常见的 5 线 4 相步进电机,公共端(红色线)需连接至电机供电,如下图所示:

2.3 供电接口
我们可以使用 Type-C 接口的电源适配器进行供电(需要注意电源适配器最大电流,建议使用 15V 3A 适配器),也可以使用接线端子供电,电源正极连接 V,电源负极连接 G,如下图所示:

3.硬件细节
3.1 供电保护
我们使用 220uF 固态电容作为稳压元件,固态电容具有较低的等效串联电阻和快速的电荷释放能力,对高频信号的阻抗更低,能够更高效地滤除高频噪声,相比传统电解电容在高温下具有更稳定的性能和更长的使用寿命,配合 100nf 小电容给达林顿管芯片进行稳压,快速消除达林顿管(ULN2003)开关瞬间的瞬态干扰,适合步进电机启停频繁的应用场景:

3.2 PWM 输出芯片地址位选择
我们可以通过焊接扩展板背面短路点来设置 PWM 扩展芯片地址位,注意四个地址位必须都焊接,默认地址位浮空:

3.3 指示灯电路
我们对步进电机驱动的四个控制通道都配备了指示灯,通过 4.7K 上拉电阻连接到 VCC,当某个通道导通时,对应 LED 指示灯点亮:

4.提供代码和使用须知
在使用烧录完程序后的主控板通过扩展板控制舵机前,务必确保电机和通信接线正确,供电无误:

示例代码包括以下版本:
- MicroPython 版本 :总线单极性步进电机驱动板
这里,需要注意,MicroPython 相关程序经过我们的优化处理,以便更好地适配硬件,提高易用性,以第三方库形式在 Github 进行发布,并附带知识共享署名-非商业性使用 4.0 国际版 (CC BY-NC 4.0) 许可,侵权必纠,敢线下直接来揪你!
5.获取链接
- 获取链接 :多米诺系列-I2C总线单极性步进电机驱动板
- 硬件开源链接 :多米诺系列-I2C总线单极性步进电机驱动板
6.相关测试和演示视频
我们测试了不同减速比、驱动电压、直径的步进电机:






也对不同驱动模式进行了测试:

相关演示视频可以查看:
【从硬件到代码】I2C总线单极性步进电机驱动板设计全解 | 标准化接口+电机原理+实战测试,看这一篇就够了!
7.代码软件详解

配套示例程序展示了如何使用总线单极性步进电机扩展板控制两个单极性步进电机,该扩展板通过I2C总线控制PCA9685芯片生成8路PWM信号,并通过这些信号控制步进电机转动,最多支持两个步进电机(可通过多个扩展板堆叠式排布扩展增加可以驱动的步进电机数量),支持单相、双相、半步驱动模式:
pca9685.py
: 提供对PCA9685芯片的控制,能够设置和获取PWM频率,并控制PWM波形占空比。bus_step_motor.py
: 用于控制两个直流电机的正反转、调速和不同驱动模式。main.py
:简单测试相关驱动库。
主要特性包括:
- 多电机独立控制:单块PCA9685最多支持2个步进电机(每个电机占用4个PWM通道),每个电机可独立设置方向、速度、驱动模式和运动模式。
- 灵活的运动模式:可以设置其进行连续运动(电机持续旋转,直到手动停止)和定步运动(精确控制电机旋转指定步数后自动停止)。
- 三种驱动方式:单相驱动(Single Phase),低功耗,扭矩较小;双相驱动(Double Phase),高扭矩,适合重负载;半步驱动(Half Step),更高分辨率,运动更平滑。
- 硬件优化 :使用
micropython.native
装饰器提升关键函数执行效率。 - 非阻塞式控制:定时器中断驱动步进脉冲,减少主程序阻塞。
BusStepMotor:
-
用于控制5线4相步进电机(如28BYJ-48)的运动控制,支持三种驱动模式和两种运动方式。
方法:
__init__(pca9685: PCA9685, motor_count: int = 2)
: 构造函数,初始化电机控制类。_next_step(motor_id: int)
: 计算并更新指定电机的步进状态。_start_timer(motor_id: int, speed: int)
: 启动定时器并设置回调函数,以控制电机连续运动。_stop_timer(motor_id: int)
: 停止指定电机的定时器,停止运动。start_continuous_motion(motor_id: int, direction: int, driver_mode: int, speed: int)
: 启动电机进行连续运动。stop_continuous_motion(motor_id: int)
: 停止电机的连续运动。start_step_motion(motor_id: int, direction: int, driver_mode: int, speed: int, steps: int)
: 启动步进电机的定步运动,按照指定步数执行。
属性:
pca9685 (PCA9685)
: 控制PWM信号输出的PCA9685芯片实例。motor_count (int)
: 控制的步进电机数量,最大为4个。timers (list)
: 存储每个电机定时器的列表。steps (list)
: 存储每个电机目标步数的列表。step_counters (list)
: 存储每个电机当前步数的计数器列表。directions (list)
: 存储每个电机的运动方向(正转或反转)。driver_modes (list)
: 存储每个电机的驱动模式(单相、双相或半步驱动)。speeds (list)
: 存储每个电机的转速(控制驱动器输出脉冲的频率)。
类变量:
DRIVER_MODE_SINGLE (int)
: 单相驱动模式的常量值。DRIVER_MODE_DOUBLE (int)
: 双相驱动模式的常量值。DRIVER_MODE_HALF_STEP (int)
: 半步驱动模式的常量值。FORWARD (int)
: 步进电机的正转方向常量值。BACKWARD (int)
: 步进电机的反转方向常量值。PHASES (dict)
: 一个字典,包含不同驱动模式下的相位序列。
以驱动一号步进电机为例,单相驱动模式时序图如下所示:
双相驱动模式时序如下:
半步驱动模式时序如下:
不同驱动模式情况下,通道驱动顺序如下表所示:
步进 | 单相模式 (A+/A-/B+/😎 | 双相模式 (A+/A-/B+/😎 | 半步模式 (A+/A-/B+/😎 | 扭矩特性 |
---|---|---|---|---|
1 | [1, 0, 0, 0] |
[1, 1, 0, 0] |
[1, 0, 0, 0] |
单相:★☆☆ 双相:★★★ 半步:★☆☆ |
2 | [0, 1, 0, 0] |
[0, 1, 1, 0] |
[1, 0, 1, 0] |
单相:★☆☆ 双相:★★☆ 半步:★★★ |
3 | [0, 0, 1, 0] |
[0, 0, 1, 1] |
[0, 0, 1, 0] |
单相:★☆☆ 双相:★★★ 半步:★☆☆ |
4 | [0, 0, 0, 1] |
[1, 0, 0, 1] |
[0, 0, 1, 1] |
单相:★☆☆ 双相:★★☆ 半步:★★★ |
5 | - | - | [0, 0, 0, 1] |
半步:★☆☆ |
6 | - | - | [0, 1, 0, 1] |
半步:★★★ |
7 | - | - | [0, 1, 0, 0] |
半步:★☆☆ |
8 | - | - | [1, 1, 0, 0] |
半步:★★★ |
相位说明:
1
表示激活,0
表示关闭- 扭矩等级:★☆☆(低) ★★☆(中) ★★★(高)
在运行示例程序之前,确保你的环境中安装了machine
和time
等模块。你可以通过MicroPython的包管理器安装依赖。
将两个文件保存到你的主文件夹中,通过以下方式导入:
python
# 导入硬件相关模块
from machine import Pin, I2C
# 导入时间相关模块
import time
# 导入自定义模块
from pca9685 import PCA9685
# 导入直流电机控制模块
from bus_step_motor import BusStepMotor
使用示例如下:
python
# Python env : MicroPython v1.23.0 on Raspberry Pi Pico
# -*- coding: utf-8 -*-
# @Time : 2025/1/19 上午10:57
# @Author : 李清水
# @File : main.py
# @Description : 总线步进电机扩展板示例程序
# ======================================== 导入相关模块 =========================================
# 导入硬件相关模块
from machine import Pin, I2C
# 导入时间相关模块
import time
# 导入自定义模块
from pca9685 import PCA9685
# 导入直流电机控制模块
from bus_step_motor import BusStepMotor
# ======================================== 全局变量 ============================================
# 外置PWM扩展芯片地址
PCA9685_ADDR = 0
# ======================================== 功能函数 ============================================
# ======================================== 自定义类 ============================================
# ======================================== 初始化配置 ==========================================
# 上电延时3s
time.sleep(3)
# 打印调试消息
print("FreakStudio: Using PCA9685 to control step motor")
# 创建硬件I2C的实例,使用I2C1外设,时钟频率为400KHz,SDA引脚为6,SCL引脚为7
i2c = I2C(id=1, sda=Pin(6), scl=Pin(7), freq=400000)
# 开始扫描I2C总线上的设备,返回从机地址的列表
devices_list = i2c.scan()
print('START I2C SCANNER')
# 若devices_list为空,则没有设备连接到I2C总线上
if len(devices_list) == 0:
print("No i2c device !")
# 若非空,则打印从机设备地址
else:
print('i2c devices found:', len(devices_list))
# 遍历从机设备地址列表
for device in devices_list:
# 判断地址是否在0x40到0x4F之间,如果是,则为PCA9685芯片地址
if 0x40 <= device <= 0x4F:
print("PCA9685 I2C hexadecimal address: ", hex(device))
PCA9685_ADDR = device
# 创建PCA9685实例,使用I2C0外设
pca9685 = PCA9685(i2c, PCA9685_ADDR)
# 创建步进电机实例,使用PCA9685实例,电机数量为4
bus_step_motor = BusStepMotor(pca9685, 4)
# ======================================== 主程序 ===========================================
# 开启步进电机连续运动模式:电机编号为1,方向为正转,驱动模式为单相驱动,速度为10
bus_step_motor.start_continuous_motion(1, BusStepMotor.FORWARD, BusStepMotor.DRIVER_MODE_SINGLE, 10)
# 延时10s
time.sleep(10)
# 停止步进电机连续运动模式
bus_step_motor.stop_continuous_motion(1)
# 开启步进电机步进运动模式:电机编号为1,方向为正转,驱动模式为单相驱动,速度为10,步数为10
bus_step_motor.start_step_motion(1, 1, 0, 100, 1000)
