电机驱动板怎么选怎么接:L298N / TB6612 / DRV8833 / ESC 实战
- 说清楚为什么不能把直流电机直接接到 MCU 的 GPIO 上
- 用 H 桥原理理解正反转和调速到底是怎么实现的
- 在 L298N / TB6612 / DRV8833 / ESC 之间按电流、电压、效率做出选择
- 用 ESP32 + TB6612 跑通两路电机的前进、后退、转向和调速
我第一次做小车,把一个 TT 减速电机的两根线直接焊到了 ESP32 的两个 GPIO 上,心想:不就是给个高低电平嘛。结果上电那一刻,电机抽搐了一下就不动了,板子重启,串口刷屏。换了块新板子,这次电机倒是转了半秒——然后 GPIO 那一脚再也输不出高电平了。两块板子,学费交得明明白白。
这篇就是把当年那个坑讲清楚:电机驱动板到底解决什么问题,H 桥怎么让电机正反转,市面上 L298N、TB6612、DRV8833 这三款有刷驱动和无刷专用的 ESC 电调各自适合什么场景,最后给一段 ESP32 控两路电机的完整代码,你照着接就能让小车跑起来。
读这篇之前,最好先搞清楚电机本身怎么选——那是另一篇 机器人电机怎么选 的事,有刷、减速比、堵转扭矩都在那讲。这篇只管「选好电机之后,拿什么去驱动它」。另外 PWM 调速的底层原理建议先扫一眼 PWM 是什么 和 用 PWM 控制亮度,下面调速那段会直接用到。
为什么 MCU 不能直接驱动电机
直接接 GPIO 烧板子,不是玄学,是三个硬道理。
第一,电流不够。 ESP32 单个 GPIO 的最大输出电流通常只有 20mA 左右,绝对上限也就 40mA。而一个普通的 TT 减速电机,空载电流就有 100~200mA,堵转(卡住转不动)瞬间能飙到 1A 以上。你让一个只能掏出 20mA 的引脚去喂一个要 1A 的负载,结果就是引脚过流烧毁。这就是我第二块板子那一脚报废的原因。
第二,要能正反转。 直流电机的转向取决于电流方向——正接正转,反接反转。GPIO 只能给你「高电平 3.3V」或「低电平 0V」,没法主动制造反向电流。想让小车既能前进又能后退,光靠一个引脚的高低电平做不到,你需要一套能切换电流方向的电路。
第三,要隔离感性冲击。 电机是个电感。电感的特性是「电流不能突变」。当你突然断电,线圈里那股电流会瞬间产生一个反向的高压尖峰(反电动势),几十伏的尖峰直接打回你 3.3V 的逻辑电路,主控轻则重启、重则击穿。这就是为什么我第一块板子一上电就疯狂重启。
驱动板(也叫电机驱动模块、H 桥模块)就是专门挡在 MCU 和电机中间的那一层:它用大功率的开关管去扛电机的大电流,用续流二极管去吸收反电动势尖峰,再把电机电源和逻辑电源隔开。MCU 只负责发「往哪个方向转、转多快」的弱电信号,脏活累活全交给驱动板。
H 桥原理:四个开关怎么控正反转
驱动板的核心电路叫 H 桥(H-Bridge)。名字来自它的拓扑长得像字母 H:上面两个开关、下面两个开关,电机横在中间那一横上。
VM(电机电源)
│
┌─┴─┐ ┌───┐
│S1 │ │S2 │
└─┬─┘ └─┬─┘
│ ┌─────┐ │
├───┤ 电机 ├───┤
│ └─────┘ │
┌─┴─┐ ┌─┴─┐
│S3 │ │S4 │
└─┬─┘ └─┬─┘
│ │
GND ──────────GND
四个开关(实际是晶体管/MOS 管)两两配合,决定电流从哪头流进电机:
- 正转:闭合 S1 和 S4,断开 S2 和 S3。电流从左上进、右下出,电机正转。
- 反转:闭合 S2 和 S3,断开 S1 和 S4。电流反过来走,电机反转。
- 刹车:闭合 S3 和 S4(下面两个都通),电机两端短路,靠自身发电产生阻力,急停。
- 滑行:四个全断开,电机两端悬空,靠惯性自己慢慢停。
有一条铁律:同一侧的上下两个开关(S1+S3 或 S2+S4)绝对不能同时闭合。一旦同时通,VM 经过两个开关直接短路到 GND,瞬间大电流烧驱动芯片,这叫「直通」(shoot-through)。好在你买的成品驱动模块内部都做了逻辑保护或死区延时,你只要别给出矛盾的方向信号就行。
那「调速」呢?调速不靠改电压,靠 PWM——给方向信号叠加一路高频开关。让 H 桥以几千上万赫兹的频率快速通断,占空比 70% 电机就拿到约 70% 的等效功率,转得快;占空比 20% 就转得慢。原理和 PWM 控制 LED 亮度 一模一样,只是负载从灯换成了电机。
四款驱动横向对比
明白了 H 桥,选驱动板就是在「H 桥用什么开关管、能扛多大电流、压降多少」之间做权衡。
① L298N — 老牌、便宜、但发热大
最经典的入门驱动,淘宝十几块带散热片。内部用的是双极性晶体管(BJT),双路 H 桥,每路持续约 2A。最大的毛病是压降高:导通时每路要吃掉约 23V。你给 7.4V 的电池,电机实际只拿到 45V,剩下的全变成热量从散热片散掉。效率低、发烫、还得占用电池电量。我的评价:只适合做实验、学原理、不在乎效率的场合。能用,但 2024 年了没必要再买它做正式项目。
② TB6612FNG — MOS 管、效率高、推荐替代 L298N
东芝的双路驱动,SparkFun 把它做成了经典的红色小模块(产品页)。内部换成了 MOS 管,导通压降只有约 0.5V 不到,效率比 L298N 高一大截,发热小、不用大散热片。每路持续 1.2A、峰值 3.2A,双路,覆盖绝大多数小车和两轮平衡车。控制接口也清爽:每路两个方向脚(IN1/IN2)+ 一个 PWM 脚。做有刷小车,我的默认选择就是它。 下面的代码也用它。
③ DRV8833 — 小巧、低压、适合电池小机器人
TI 的双 H 桥驱动(官方产品页)。最大特点是工作电压低,2.7V 起步就能干活,特别适合直接用一节锂电池(3.7V)或两节 AAA 供电的小型机器人、桌面玩具、微型双足。每路持续约 1.5A、峰值 2A,封装比 TB6612 还小。如果你的项目是「锂电池供电、空间紧张、电机不大」,选它。锂电池供电的安全注意事项见 锂电池安全。
④ ESC 电调 — 给无刷电机用,信号像舵机
前三款都是给有刷直流电机用的 H 桥。如果你用的是无刷电机(BLDC)——比如航模、穿越机、高速轮毂——那就完全不是 H 桥的活了,得用专门的 ESC(电子调速器/电调)。无刷电机有三相绕组,ESC 内部是三相六管桥+换相逻辑,结构复杂得多。
对你来说好消息是:ESC 的控制信号跟舵机一模一样——一路 50Hz 的 PWM,1ms 脉宽是停、2ms 是满油门。所以你会控舵机就会控 ESC。坏消息是无刷电机起步前要「解锁」(先给最低油门),堵转和高速都更危险。新手做轮式小车不用碰它,做航模/穿越机才需要。
下面是选型表,按你的实际情况对号入座:
| 驱动 | 类型 | 每路电流 | 压降/效率 | 适用电机 | 推荐场景 |
|---|---|---|---|---|---|
| L298N | BJT 双 H 桥 | 持续 2A | 压降 ~2.5V,效率低、发热大 | 有刷直流 | 纯学习、不在乎效率 |
| TB6612FNG | MOS 双 H 桥 | 持续 1.2A / 峰值 3.2A | 压降 ~0.5V,效率高 | 有刷直流 | 多数有刷小车(首选) |
| DRV8833 | MOS 双 H 桥 | 持续 1.5A / 峰值 2A | 低压 2.7V 起、效率高 | 有刷直流 | 锂电池供电的小型机器人 |
| ESC 电调 | 三相六管 | 看型号 10~60A 不等 | 效率高 | 无刷 BLDC | 航模、穿越机、高速轮毂 |
ESP32 + TB6612 控两路电机:完整可跑代码
下面这段代码用 ESP32 的 LEDC 硬件 PWM 外设,控两路电机的方向和速度。LEDC 是 ESP32 自带的硬件 PWM,比软件模拟稳得多,用法见 Arduino-ESP32 LEDC 文档。
引脚定义是示意,以你的实际接线为准。TB6612 每路要三根控制线:两个方向脚(IN1/IN2)决定转向,一个 PWM 脚(PWMA/PWMB)决定速度。
// ESP32 + TB6612FNG 双路电机驱动
// 引脚为示意,以你的实际接线为准
// ---- 左电机(接 TB6612 的 A 路)----
const int AIN1 = 16; // 方向脚 1
const int AIN2 = 17; // 方向脚 2
const int PWMA = 18; // 速度(PWM)
// ---- 右电机(接 TB6612 的 B 路)----
const int BIN1 = 21;
const int BIN2 = 22;
const int PWMB = 23;
// ---- 待机脚,拉高才工作(TB6612 的 STBY)----
const int STBY = 19;
// PWM 参数
const int PWM_FREQ = 1000; // 1kHz,电机驱动常用 1~20kHz
const int PWM_BITS = 8; // 8 位分辨率,速度范围 0~255
void setup() {
pinMode(AIN1, OUTPUT); pinMode(AIN2, OUTPUT);
pinMode(BIN1, OUTPUT); pinMode(BIN2, OUTPUT);
pinMode(STBY, OUTPUT);
// 新版 Arduino-ESP32 (3.x) 的 LEDC 用法:直接绑定引脚
ledcAttach(PWMA, PWM_FREQ, PWM_BITS);
ledcAttach(PWMB, PWM_FREQ, PWM_BITS);
digitalWrite(STBY, HIGH); // 解除待机,驱动开始工作
}
// 左电机:speed 取 -255~255,正前进、负后退、0 停
void leftMotor(int speed) {
bool forward = speed >= 0;
digitalWrite(AIN1, forward ? HIGH : LOW);
digitalWrite(AIN2, forward ? LOW : HIGH);
ledcWrite(PWMA, abs(speed));
}
void rightMotor(int speed) {
bool forward = speed >= 0;
digitalWrite(BIN1, forward ? HIGH : LOW);
digitalWrite(BIN2, forward ? LOW : HIGH);
ledcWrite(PWMB, abs(speed));
}
// ---- 高层动作函数 ----
void forward(int spd) { leftMotor(spd); rightMotor(spd); } // 前进
void backward(int spd) { leftMotor(-spd); rightMotor(-spd); } // 后退
void turnLeft(int spd) { leftMotor(-spd); rightMotor(spd); } // 原地左转
void turnRight(int spd){ leftMotor(spd); rightMotor(-spd); } // 原地右转
void stopAll() { leftMotor(0); rightMotor(0); } // 停
void loop() {
forward(180); delay(1500); // 前进 1.5 秒(约 70% 速度)
stopAll(); delay(500);
backward(180); delay(1500); // 后退
stopAll(); delay(500);
turnLeft(150); delay(800); // 左转
stopAll(); delay(500);
turnRight(150);delay(800); // 右转
stopAll(); delay(1000);
}
几个要点解释一下:
- 方向靠两个脚的高低组合:
IN1=H, IN2=L正转,IN1=L, IN2=H反转,两个都 L 是滑行停。这就是上面 H 桥四个开关在芯片内部的体现。 - 速度靠 PWM 占空比:
ledcWrite写 0255,180 大约是 70% 速度。太小(比如低于 50)电机可能因为扭矩不够「嗡嗡响但不转」,这是正常的,小车一般工作在 120255 区间。 - STBY 必须拉高:TB6612 有个待机脚,忘了拉高电机一动不动,这是最常见的「接对了却不转」的原因。
- 转向靠左右轮反着转:原地转就是一边正转一边反转,这种两轮差速的运动学下一篇 差速驱动 专门讲。
接线要点:电源分开、必须共地、加电容
软件之外,接线是另一个翻车重灾区。三条铁律:
1. 电机电源 VM 和逻辑电源 VCC 分开。 TB6612 上有两个电源脚:VM 接电机电源(比如 7.4V 锂电池),VCC 接逻辑电源(3.3V,跟 ESP32 同一个)。别把电机的 7.4V 接到 VCC 上去,会烧逻辑电路。电池为什么不能直接当逻辑供电、怎么稳压降到 3.3V,见 稳压电源原理。
2. 所有地必须共地(GND 接到一起)。 ESP32 的 GND、驱动板的 GND、电池的负极,三者必须连成一个点。这是新手最容易漏的一步。不共地的话,PWM 信号没有共同的参考电平,表现为电机乱转、时转时不转、甚至完全无反应。共地是排查「玄学故障」第一个要检查的地方。
3. 电机电源端加去耦电容。 在 VM 和 GND 之间并一个 100nF 陶瓷电容(高频)加一个 100~470μF 电解电容(低频),靠近驱动板放。电机换向时会产生电气噪声,这些电容能把尖峰滤掉,防止主控被干扰重启。电容为什么能滤波、怎么选容值,见 电容是什么。
电机驱动三大安全红线,每一条我都踩过:
- 电源别接错:电机电源(VM)和逻辑电源(VCC)一旦接反或接错,逻辑芯片瞬间烧毁,ESP32 可能一起报废。接线后先用万用表量一遍再上电。
- 当心堵转电流:电机被卡住(堵转)时电流是正常运行的 5~10 倍,TT 电机能到 1A 以上,大电机更夸张。长时间堵转会烧驱动芯片,也会让电池过放发热。代码里别让电机长时间顶着障碍物硬推。
- 务必共地:MCU、驱动板、电池三方 GND 必须连通。不共地不只是「不工作」,还可能因为电位漂移损坏 IO 口。先连 GND,再连信号线,是焊接的固定顺序。
你应该看到什么
接线和烧录都对的话,上电后小车会按 loop() 的脚本走一遍:
- 前进约 1.5 秒(两轮同向、中等速度往前滚)
- 停半秒,然后后退 1.5 秒(两轮反向)
- 停半秒,原地左转约 0.8 秒(左轮倒、右轮进,车头向左甩)
- 停半秒,原地右转
- 停 1 秒后整个循环重来
如果车走直线时明显往一边歪,那是两个电机的实际转速有差异(电机个体差异很正常),后面接编码器做闭环就能修正,先别纠结。
故障排查表
| 现象 | 最可能的原因 | 怎么查 |
|---|---|---|
| 电机完全不转 | STBY 没拉高,或 VM 没接电机电源 | 量 STBY 是否 3.3V;量 VM 是否有电池电压 |
| 只有一个方向能转 | 某个方向脚(IN1/IN2)没接好或虚焊 | 万用表通断挡量两个方向脚到芯片 |
| 电机发烫、效率低 | 用的 L298N(压降大),或 PWM 频率太低 | 换 TB6612;PWM 频率提到 1kHz 以上 |
| 一给电机加速主控就重启 | 没共地,或缺去耦电容,反电动势打回主控 | 检查三方 GND;VM 端补 100μF 电解电容 |
| 电机抖动/嗡嗡响不转 | PWM 占空比太低,扭矩不够 | 速度值提到 120 以上试试 |
| 转向反了(左变右) | 电机两根线接反了 | 对调那个电机的两根输出线,或在代码里取负 |
进阶变体
变体一:接编码器做闭环。 上面的代码是「开环」——你让它走 180 的速度,它实际多快你不知道,电池电量低了就变慢。给电机装上编码器(码盘),就能实时读到真实转速,反馈给控制器去自动补偿。这是从「能动」到「精确」的关键一步。
变体二:PID 闭环控速。 有了编码器的反馈,下一步就是用 PID 算法让两个轮子精确匹配设定速度,走直线不再歪,定点停车更准。这套闭环控制是 机器人 PID 入门 的主题,编码器和这篇的驱动代码是它的前置。
动手挑战
把 loop() 改掉,让小车走一个正方形:前进一段 → 右转 90 度 → 再前进同样一段 → 再右转,重复四次回到起点。
提示:右转 90 度对应的 turnRight 时长需要你自己试出来(跟电池电压、地面摩擦、电机速度都有关,没有标准答案,从 delay(400) 开始调)。这正好让你体会到「开环控制」的痛点——同样的代码,电池满电和快没电时转的角度不一样。等你被这个问题折磨够了,自然就理解为什么需要编码器和闭环了。
小结·下一步
驱动板的本质是 H 桥:四个开关控正反转,PWM 占空比控速度。有刷电机首选 TB6612(L298N 太费电、DRV8833 适合低压小机器人),无刷电机才用 ESC。接线记牢三条——电源分开、必须共地、加去耦电容。
现在你能让小车前进后退转弯了,但「左轮倒右轮进就是原地转」这套运动学背后其实有一整套规律:怎么算转弯半径、怎么走弧线、怎么让两轮配合出任意轨迹。下一篇 两轮差速驱动 把这套运动学讲透,让你的小车从「能动」走向「会走」。想看更多机器人主题,回到 机器人专栏。