家里窗帘机、空调摆叶、3D打印机料仓里,其实都藏着同一种东西:步进电机。它不像直流电机那样转起来没数,而是一格一格地走,走多少格、往哪边走、走多快,全看你怎么给脉冲,所以凡是需要精确定位的场合都轮得到它。
入门玩步进,28BYJ-48 加 ULN2003 驱动板这套组合几乎是标配:几块钱一套、5V 就能驱动、接 Arduino 四根线搞定。这篇把步进原理、步距角、减速比、接线、两种库的控制写法一次讲透,代码全部取自可核验的英文教程底稿,照抄就能转。
先搞懂步进电机怎么走
步进电机本质是无刷直流电机的一种,靠磁场一步步走。定子上绕着电磁线圈,转子带磁齿;给线圈按顺序通电,每个线圈产生的磁场会吸住最近的转子齿,转子就前进一个固定的角度,这个角度就叫一步。
控制逻辑就三句话:脉冲的顺序决定转向,脉冲的频率决定转速,脉冲的总数决定转角。想把电机转到某个精确位置,数好脉冲个数就行——这也是它比直流电机加编码器方案省事的地方。
28BYJ-48:步距角与 64:1 减速比
28BYJ-48 是 5 线单极性步进电机,5V 供电,机身直径约 28mm,含减速箱整机约 37g,输出轴做成双 D 形方便装轮子和连轴件。
它的五根线里,红线是两组线圈的中心抽头,接正极;剩下四根蓝、粉、黄、橙各对应一个相位。哪根线接低电平,那个相位就励磁。按固定节奏轮流通电,这个节奏就叫步序。
重点说减速比。查数据手册可知,不带减速箱时转子每步走 11.25°,转一圈要 32 步;机内自带 64:1 的减速齿轮组,转子转 64 圈输出轴才转 1 圈,所以输出轴转一圈要 32 × 64 = 2048 步,输出轴步距角 5.625°。减速箱牺牲了转速换来扭矩:标称空载转速约 15 RPM,扭矩约 34.3 mN·m。另外要注意,不同厂家的版本有的减速比是 1:16,一圈只有 512 步,步数对不上先查这个。
功耗方面,单相约 240mA,而且步进电机有个特点:静止时为了锁定位置,线圈里也一直通着保持电流,照样耗电发热。项目要靠电池长跑的话,这一点必须提前算进去。
ULN2003 驱动板与接线
Arduino 引脚扛不住 240mA 的线圈电流,中间必须垫一级驱动。ULN2003 是七路达林顿阵列,板子上引出了 IN1-IN7 七个输入,28BYJ-48 只用到前四个;板侧还有 A、B、C、D 四个 LED,转的时候能直观看到励磁顺序,排查接线特别方便。
接线一共六根,按下面这张图来:
- 电机五线插头直接插驱动板的白色座子,插反插不进,不用担心方向;
- 驱动板 IN1、IN2、IN3、IN4 依次接 Arduino 的 8、9、10、11 号引脚;
- 驱动板 GND 接 Arduino GND,VCC(标 + 的那端)接 Arduino 5V;
- 只测一两分钟可以吃 Arduino 的 5V,长时间跑建议外接 5V 电源,共地即可。

写法一:自带 Stepper 库,正反转与调速
Arduino 自带的 Stepper 库不用装任何东西,代码里实例化的引脚顺序必须写 IN1-IN3-IN2-IN4(8, 10, 9, 11),这是最容易翻车的点——按 8, 9, 10, 11 填,电机只会抖不转。
下面这段取自底稿教程:先 5 RPM 顺时针一整圈,再 10 RPM 逆时针一整圈。改 setSpeed 的数值就是调速,step 前面加负号就是反转:
//Includes the Arduino Stepper Library
#include "Stepper.h"
// Defines the number of steps per rotation
const int stepsPerRevolution = 2048;
// Creates an instance of stepper class
// Pins entered in sequence IN1-IN3-IN2-IN4 for proper step sequence
Stepper myStepper = Stepper(stepsPerRevolution, 8, 10, 9, 11);
void setup() {
// Nothing to do (Stepper Library sets pins as outputs)
}
void loop() {
// Rotate CW slowly at 5 RPM
myStepper.setSpeed(5);
myStepper.step(stepsPerRevolution);
delay(1000);
// Rotate CCW quickly at 10 RPM
myStepper.setSpeed(10);
myStepper.step(-stepsPerRevolution);
delay(1000);
}提示一点:Stepper 库的 step() 是阻塞式的,转完 2048 步才往下走,中间串口、传感器全停。玩着没问题,要接别的活就得换下面的写法。
写法二:AccelStepper 库,非阻塞加减速
AccelStepper 支持加速度规划和非阻塞运行,先在库管理器里搜 AccelStepper 装上(Michael Contreras 版):
接口类型填 4(四线全步),引脚顺序同样写 8, 10, 9, 11。setup 里设最大速度、加速度、初始速度和目标位置 2048 步;loop 里每到目标就反向,run() 每圈循环推进一步,不阻塞主循环:
// Include the AccelStepper Library
#include "AccelStepper.h"
// Define step constant
#define MotorInterfaceType 4
// Creates an instance
// Pins entered in sequence IN1-IN3-IN2-IN4 for proper step sequence
AccelStepper myStepper(MotorInterfaceType, 8, 10, 9, 11);
void setup() {
// set the maximum speed, acceleration factor,
// initial speed and the target position
myStepper.setMaxSpeed(1000.0);
myStepper.setAcceleration(50.0);
myStepper.setSpeed(200);
myStepper.moveTo(2048);
}
void loop() {
// Change direction once the motor reaches target position
if (myStepper.distanceToGo() == 0)
myStepper.moveTo(-myStepper.currentPosition());
// Move the motor one step
myStepper.run();
}想把两个 28BYJ-48 一起跑(比如小车左右轮),AccelStepper 更是唯一解:开两个实例,第二个接 4, 5, 6, 7 号脚,loop 里各调各的 run() 就能同动、各转各的方向。底稿教程里有完整双电机代码,照抄即可。
收个尾
这套组合的定位很清楚:便宜、省事、教学价值高,但 15 RPM 的转速和 34.3 mN·m 的扭矩摆在那,干不了重活快活。做相机滑轨、窗帘、小云台这类慢速定位,它正合适;要速度和力度,直接看 NEMA17 加 A4988 的路子。
最后划三个新手坑:引脚顺序必须 IN1-IN3-IN2-IN4 交错填;减速比不同厂家有 64:1 和 16:1 两种,步数 2048 还是 512 先确认;电机静止也持续发热,长时间通电加散热或断电逻辑。避开这三条,基本一次点亮。(价格层面,这套组合长期在几元到十几元一档,截至2026-11-08电商价大致如此,下单前自己核一眼。)


之前用 Stepper 库按 8,9,10,11 顺手填的,结果电机嗡嗡抖不转,查了一晚上才知道要交错填 8,10,9,11。这篇直接把坑点写明白了,新手能少走好多弯路。
减速比 64:1 和 16:1 那段有用,我手里那块就是 512 步的,一开始照 2048 写一直觉得转速不对劲。
ULN2003 板上那四个 LED 确实好用,肉眼就能看出励磁顺序。
静止也发热这点深有体会,挂了一晚上电池掉得心疼,后来加了不转就断电的逻辑才好。