四线步进电机(28BYJ-48,A+ A- B+ B-)驱动思路
四线步进电机(28BYJ-48,A+ A- B+ B-)驱动思路
四线 = 两相四线步进电机,两相绕组:A相(A+,A-)、B相(B+,😎,没有公共端,典型就是28BYJ-48。 驱动芯片:ULN2003 最常用,也可以用三极管/MOS管搭H桥。 驱动方式:4拍(单拍) / 8拍(半步,细分,更顺滑)
一、绕组逻辑
- A相:A+、A- 一组线圈;B相:B+、B- 另一组线圈
- 线圈通电原理:电流方向决定磁极。A+高A-低 与 A-高A+低,磁极相反。
- 两相四线没有中心抽头,不能像五线28BYJ那样用公共端,必须H桥,每相正反换向。
两种驱动节拍表
1)4拍(全步,单绕组通电,扭矩一般,震动大)
顺序:A → B → /A → /B
| 拍号 | A+ | A- | B+ | B- |
|---|---|---|---|---|
| 0 | 1 | 0 | 0 | 0 |
| 1 | 0 | 0 | 1 | 0 |
| 2 | 0 | 1 | 0 | 0 |
| 3 | 0 | 0 | 0 | 1 |
| 循环 0→1→2→3 正转;反向 3→2→1→0 反转 |
2)8拍(半步模式,力矩平稳、抖动小,角度精度高)
单拍+双拍混合,就是半步驱动
拍号 A+ A- B+ B- 0 1 0 0 0 1 1 0 1 0 2 0 0 1 0 3 0 1 1 0 4 0 1 0 0 5 0 1 0 1 6 0 0 0 1 7 1 0 0 1 0~7 正转;7→0 反向循环
28BYJ-48 减速后:8拍模式一圈需要4096拍
二、硬件引脚定义
A+ → GPIO2
A- → GPIO3
B+ → GPIO4
B- → GPIO5
ULN2003:单片机IO输出高电平,ULN输出低电平,节拍表电平要反过来!这点非常容易踩坑! 简单记:
-
如果你直接MOS管H桥:代码用上面节拍表
-
ULN2003驱动28BYJ:IO输出取反,表格1写成0,0写成1
三、设计思路
- 建立节拍数组,存放8拍的A+ A- B+ B-电平
- 维护一个全局变量
step_index,记录当前在哪一拍 - 每一次步进:修改4个IO口电平 →
step_index++,超过7归零;反转就step_index-- - 延时控制转速:延时越大越慢;不要太短,否则丢步
- 原点限位逻辑:
- 上电:电机持续向零点方向走,检测到限位信号,停止,重置角度计数器=0
- 之后每旋转目标角度,计算需要多少拍,循环输出节拍
四、ESP32 示例代码(两相四线,8拍,A+A-B+B-)
# MicroPython 版本,ESP32
from machine import Pin
import time
# 定义引脚 A+ A- B+ B-
A_plus = Pin(2, Pin.OUT)
A_minus = Pin(3, Pin.OUT)
B_plus = Pin(4, Pin.OUT)
B_minus = Pin(5, Pin.OUT)
# 8拍半步节拍表 H桥驱动(MOS管方案,高电平导通线圈)
# [A+, A-, B+, B-]
step_table = [
[1,0,0,0],
[1,0,1,0],
[0,0,1,0],
[0,1,1,0],
[0,1,0,0],
[0,1,0,1],
[0,0,0,1],
[1,0,0,1],
]
step_idx = 0
def set_step(idx):
"""输出对应节拍电平"""
A_plus.value(step_table[idx][0])
A_minus.value(step_table[idx][1])
B_plus.value(step_table[idx][2])
B_minus.value(step_table[idx][3])
def step_motor(step_num, delay_ms=3):
"""
转动电机
step_num >0 正转,<0反转
delay_ms: 每拍间隔,越小越快,过小丢步
"""
global step_idx
dir = 1
if step_num < 0:
dir = -1
step_num = -step_num
for _ in range(step_num):
set_step(step_idx)
time.sleep_ms(delay_ms)
step_idx += dir
if step_idx >= 8:
step_idx = 0
elif step_idx <0:
step_idx =7
# 可选:转动完成,全部线圈断电,省电减少发热
A_plus.off()
A_minus.off()
B_plus.off()
B_minus.off()
# ========== 测试 ==========
# 转一圈 4096步(8拍模式)
step_motor(4096, 3)
time.sleep(1)
# 反转半圈
step_motor(-2048,3)
五、ULN2003注意事项
ULN2003是灌电流驱动,IO输出高,ULN输出低,线圈通电。 节拍表电平全部取反:1→0,0→1
step_table_uln = [
[0,1,1,1],
[0,1,0,1],
[1,1,0,1],
[1,0,0,1],
[1,0,1,1],
[1,0,1,0],
[1,1,1,0],
[0,1,1,0],
]
六、限位原点集成思路
# 霍尔限位接GPIO14
hall = Pin(14, Pin.IN, Pin.PULL_UP)
def home():
"""上电回零函数"""
global step_idx
print("寻找原点...")
while hall.value() == 1: # 没检测到磁铁
set_step(step_idx)
time.sleep_ms(4)
step_idx +=1
if step_idx >=8:
step_idx=0
# 碰到原点,停止,清零步数计数
A_plus.off()
A_minus.off()
B_plus.off()
B_minus.off()
print("原点找到!")
七、设计要点总结
- 四线两相,A+/A- 控制A相磁场方向;B+/B-控制B相
- 优先8拍半步,云台更顺滑
- 开环靠脉冲计数,必须上电回零(霍尔/限位)消除丢步误差
- 每拍之间必须延时,不能无限快
- 运动结束可以关闭所有绕组,降低发热
八、正反转控制逻辑
step_table = [
[1,0,0,0], # 0
[1,0,1,0], # 1
[0,0,1,0], # 2
[0,1,1,0], # 3
[0,1,0,0], # 4
[0,1,0,1], # 5
[0,0,0,1], # 6
[1,0,0,1], # 7
]
- 正转:
0 →1 →2 →3 →4 →5 →6 →7 →0(数组下标递增) - 反转:
0 →7 →6 →5 →4 →3 →2 →1 →0(数组下标递减)
dir = 1 # +1 下标递增
dir = -1 # -1 下标递减
step_idx = step_idx + dir
step_idx 越界后做边界处理
九、角度与速度控制
step_num 作用
step_num = 需要执行多少个节拍。
step_num = 2048:电机一共走2048拍,然后停下step_num = -2048:走2048拍,反向转动
28BYJ-48 8拍模式:4096拍 = 完整一圈360° 所以
step_num=1024→ 转90°,step_num=2048→ 180°
step_motor(step_num, delay_ms=3)
# step_num:总步数(角度)
# delay_ms:每一拍的间隔时间(速度)
速度由谁控制?
delay_ms:每一拍之间等待多久
delay_ms = 5:每拍等5ms → 慢delay_ms = 2:每拍等2ms → 更快- 太小(比如<1ms):来不及建立磁场,直接丢步,电机不转
转速公式: 每秒拍数 = 1000 / delay_ms 例:delay_ms=3 → 1000/3 ≈ 333拍/秒
示例代码
def step_motor(step_num, delay_ms=3):
dir = 1 if step_num>0 else -1
step_num = abs(step_num)
for _ in range(step_num): # 循环执行 step_num 次
set_step(step_idx)
time.sleep_ms(delay_ms) # 控制速度
step_idx += dir
for _ in range(step_num):循环多少次,就走多少步。
step_motor(1024, 5) # 走1024拍,慢速度
step_motor(1024, 2) # 同样1024拍(同样角度),速度更快
step_motor(4096, 3) # 走更多步数(一圈),中等速度
浙公网安备 33010602011771号