直流电机不能直连 GPIO,要靠 H 桥驱动板隔一层:方向由两根信号线定,速度由 PWM 占空比定,而电机的电必须来自自己的电池——只共地,不共电。
7-3/7-4 学的是【GPIO 输出电平】和【PWM 调亮度】,当时驱动的是 LED 这种毫瓦级负载;本节把同样的两件工具用在安培级负载上,于是必须插入一块驱动板来放大和隔离。所有【Pi 5 上 RPi.GPIO 失效】的结论(7-2)在这里继续有效:电机控制同样用 gpiozero + lgpio。
一、为什么必须经驱动板
电机和 LED 的根本区别有三条,每条都足以烧掉树莓派:
- 电流量级不同:GPIO 单针安全电流约 10~16mA,TT 电机空转就近百毫安、堵转可达 0.6~0.8A——差两个数量级;
- 电机会【倒灌】:电机是电感,断电瞬间线圈要维持电流,会从转动的方向往回送一个远高于供电的反电动势尖峰。LED 没有这个问题,电机每次开关都有;
- 电机要正反转:GPIO 只会给高或低,没法把电压极性倒过来。
H 桥电路一次解决这三件事:用四个开关(现代用 MOSFET)搭成一个【桥】,电机挂在桥中间,改变对角开关的通断组合,就能改变电机两端电压的极性——这就是正转与反转的物理本质。
二、方向真值表:两根线定方向
以 L298N 的 Motor A 为例(IN1/IN2 两根方向线):
| IN1 | IN2 | 结果 |
|---|---|---|
| 低 | 低 | 停止(滑行) |
| 高 | 低 | 正转 |
| 低 | 高 | 反转 |
| 高 | 高 | 刹车(两端短接,急停) |
Motor B 用 IN3/IN4,规则完全相同。记住【一高一低=转,同高同低=不转】,接线时就不会晕。
三、两块驱动板怎么选
| L298N | TB6612FNG | |
|---|---|---|
| 内部结构 | 双极型晶体管(老工艺) | MOSFET(新工艺) |
| 电压降 | 约 1.5~2V(发热形式浪费掉) | 约 0.5V |
| 发热 | 明显,要散热片 | 很小,通常不用散热片 |
| 单通道电流 | 2A | 1.2A 连续/3.2A 峰值 |
| 逻辑电平 | 5V 兼容,3.3V 也认 | 3.3V 原生友好 |
| 额外引脚 | — | STBY 必须拉高才工作 |
| 适合 | 初学、12V 电机 | 电池车、追求效率 |
关键认识:L298N 那 1.5~2V 的压降不是小数目——6V 电机上等于白白损失三分之一的电压,车会明显没劲。做电池驱动的车,TB6612FNG 是更优解;手上的 L298N 也完全能跑,知道它的短板在哪就行。
四、gpiozero 的 Motor 类:把真值表封装掉
不需要自己写四路电平,Motor 类把方向+速度合成一个对象:
from gpiozero import Motor
# 左电机:IN1=GPIO17、IN2=GPIO27、ENA=GPIO12(PWM)
left = Motor(forward=17, backward=27, enable=12, pwm=True)
# 右电机:IN3=GPIO22、IN4=GPIO23、ENB=GPIO13(PWM)
right = Motor(forward=22, backward=23, enable=13, pwm=True)
left.forward(0.6) # 正转,速度 60%
right.forward(0.6)
三个要点:
- speed 取值 0.0~1.0:
forward(0.6)就是 60% 占空比。低速不转是正常的——真实电机要克服静摩擦,通常 0.2 以下就带不动轮子; pwm=True不能省:不加这个参数,speed 只能当开关用(0 或 1),没有中间速度;enable=引脚决定了速度能不能调:L298N 模块上那个 ENA/ENB 跳线帽必须拔掉——留着的话 ENA 被硬拉到高电平,PWM 信号根本进不去,只能控方向不能控速度。这是接 L298N 时最常见的【代码明明对、速度就是不变】的原因。
PWM 引脚选择:GPIO12/13/18/19 是硬件 PWM 引脚,用它俩(12、13)抖动量最小;用其他引脚会走软件 PWM,有一定抖动——但电机惯性大、能吸收抖动,所以电机控速对 PWM 抖动不敏感(这点和舵机完全不同,舵机必须硬件 PWM)。
五、电源铁律:只共地,不共电
这是整章最容易翻车的地方,五条背下来:
- 电机电源独立:电池正负极接驱动板的电机电源输入(L298N 的 +12V/VIN,TB6612 的 VM);
- 只共地:树莓派的 GND 与驱动板的 GND 必须相连——PWM 信号需要一个共同的电压参考,不共地信号就是噪声;
- 绝不从驱动板反哺树莓派:L298N 板上的 5V 输出不要接到树莓派,电机启停的电压波动会顺着这条线灌进树莓派;
- 不接电机线到 GPIO:任何情况下电机两端都不碰 GPIO;
- 加一颗大电容(可选但推荐):在电机电源输入端并一个几百微法的电解电容,吸收尖峰。
诊断口诀:如果电机一转树莓派就重启(或屏幕出现闪电图标),九成是第 1、3 条没做好——先查电源,再怀疑代码。
六、动手 Demo:两层验证法
照坑 49 的老规矩,先验软件链路、再接硬件。
第一层:不接电机,只验代码与 pin 配置
from gpiozero import Motor
from gpiozero import Device
print("pin factory =", Device.pin_factory) # 应看到 LGPIOFactory 之类,不是 MockFactory
m = Motor(forward=17, backward=27, enable=12, pwm=True)
m.forward(0.5)
print("value =", m.value) # 期望 0.5,证明对象活着
m.stop()
看到什么算成功:打印出真实 pin factory(不是 MockFactory),且 value 能读回 0.5。这一步不接电机也能跑——它证明库、引脚号、PWM 对象都正常。
第二层:接上电机,跑四向测试
from gpiozero import Motor
from time import sleep
left = Motor(forward=17, backward=27, enable=12, pwm=True)
right = Motor(forward=22, backward=23, enable=13, pwm=True)
def stop():
left.stop(); right.stop()
try:
print("前进"); left.forward(0.7); right.forward(0.7); sleep(2)
print("后退"); left.backward(0.7); right.backward(0.7); sleep(2)
print("左转"); left.backward(0.5); right.forward(0.5); sleep(1.5)
print("右转"); left.forward(0.5); right.backward(0.5); sleep(1.5)
finally:
stop()
print("已停车")
看到什么算成功:车依次前进 → 后退 → 原地左转 → 原地右转 → 停下。原地转向的原理:左右轮一个正转一个反转,车体绕中心自转。
读结果:如果某个方向反了,有两种修法——① 把那台电机的两根输出线(OUT1/OUT2)对调;② 代码里把 forward 与 backward 的引脚号互换。改线更直观,改代码更省事,选一样即可,不要两边都改(改两次等于没改)。
30 秒实验
把 forward 的速度依次改成 0.1、0.2、0.3 各跑 2 秒,观察:
for s in (0.1, 0.2, 0.3):
print("speed =", s)
left.forward(s); right.forward(s)
sleep(2)
left.stop(); right.stop(); sleep(0.5)
你会看到某个值以下轮子纹丝不动或只嗡嗡响——那就是这台电机+这套电池组合的起步阈值。这个实测值很有用:15-4 的前端滑杆下限就照它设,否则用户会觉得【按了没反应】。
七、常见误区
- ENA/ENB 跳线帽不用管 —— 必须拔!留着它 PWM 进不去,速度永远满速,你会以为代码写错了。
- 树莓派和电机用同一个电源、图省事 —— 电机启停会把噪声和电压跌落甩到同一个电轨上,轻则重启、重则坏 SD 卡;共地即可,不要共电。
- speed 给 0.05 就该微动 —— 真实电机有静摩擦和启动电压,低速不转是物理规律;先做上面的起步阈值实验,再定前端滑杆范围。
- 把 L298N 的 5V 输出接到树莓派 5V 脚上省一个充电宝 —— 这是本章最危险的做法:该 5V 由板载 78M05 从电池降压得到,电机负载一变它就波动,会直接冲击树莓派供电;务必让树莓派走自己的电源。
自测三问(点开对答案)
1. 为什么必须共地、却必须分开供电? 共地是给 PWM 信号提供统一电压参考;分开供电是防止电机启停的噪声与电压跌落污染树莓派的电源。 2. ENA 跳线帽为什么必须拔掉? 它把使能脚硬拉到高电平,PWM 信号进不去,导致只能控方向、不能控速度。 3. 电机最低能转到什么速度,是代码决定的吗? 不是。取决于电机静摩擦、启动电压、负载与电池电压——用起步阈值实验实测,再拿去设前端滑杆下限。- ☐ 下一节(15-3 再谈 Python 的 Flask 框架)
相关笔记
- 模拟输出 —— PWM 与占空比的原理出处,本节把它用在电机上
- Python 的 GPIO 模块 —— gpiozero 与 pin factory 的来龙去脉
- 认识树莓派智能车 —— 四层结构图里的执行层,本节展开
- 🍓 树莓派 · 索引 —— 全课路线图