1. 树莓派控制四轮小车运动概述
用树莓派控制四轮小车是嵌入式开发和机器人入门的经典项目。我最近用树莓派3B+配合L298N电机驱动模块搭建了一套完整的四轮小车控制系统,实测下来发现这套方案不仅成本低廉(总硬件成本不到300元),而且稳定性和扩展性都相当不错。
这个项目的核心是通过树莓派的GPIO引脚输出PWM信号,经由L298N模块驱动四个直流电机。相比直接用树莓派驱动电机,L298N模块提供了电流放大和保护功能,可以避免烧毁树莓派引脚。整个系统搭建完成后,可以通过Python脚本实现前进、后退、转向等基本运动控制,为后续添加传感器、摄像头等扩展功能打下基础。
注意:树莓派GPIO引脚的最大驱动电流只有16mA,而普通直流电机的启动电流可达数百mA,必须使用电机驱动模块作为中间缓冲。
2. 硬件准备与电路连接
2.1 所需材料清单
- 树莓派3B+(其他型号也适用,但GPIO布局可能不同)
- L298N电机驱动模块(建议选择带光耦隔离的版本)
- 四轮小车底盘套件(含4个直流电机)
- 18650锂电池组(7.4V)及充电器
- 杜邦线若干(建议使用公对公和公对母两种)
- 面包板(可选,用于扩展电路)
2.2 电路连接详解
L298N模块有多个接口需要正确连接:
-
电源部分:
- 12V输入接锂电池正极
- GND接锂电池负极和树莓派GND
- 5V输出可接树莓派5V引脚(可选)
-
电机输出:
- OUT1-OUT4分别接四个电机的正负极
- 注意电机极性,接反会导致转向相反
-
控制信号:
- ENA/ENB接树莓派PWM引脚(GPIO12/13)
- IN1-IN4接普通GPIO引脚(如GPIO5/6/16/17)
python复制# 典型引脚连接示例
ENA = 12 # GPIO12 (PWM0)
IN1 = 5 # GPIO5
IN2 = 6 # GPIO6
ENB = 13 # GPIO13 (PWM1)
IN3 = 16 # GPIO16
IN4 = 17 # GPIO17
重要提示:务必先断开电源再进行接线操作,避免短路烧毁元件。我第一次测试时就因为接线时没断电,烧坏了一个L298N模块。
3. 软件环境配置
3.1 系统与驱动安装
推荐使用Raspberry Pi OS Lite版本(无桌面环境),通过SSH远程控制:
bash复制# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装必要工具
sudo apt install -y python3-pip git
# 安装GPIO库
pip3 install RPi.GPIO
3.2 PWM控制原理
树莓派的硬件PWM只有两个通道(GPIO12和13),我们需要用它们控制两个电机组的转速:
python复制import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM) # 使用BCM编号
GPIO.setup(ENA, GPIO.OUT)
pwm_a = GPIO.PWM(ENA, 1000) # 1kHz频率
pwm_a.start(50) # 50%占空比
对于转向控制,通过IN1-IN4的高低电平组合实现:
- IN1=HIGH, IN2=LOW → 正转
- IN1=LOW, IN2=HIGH → 反转
- IN1=IN2=LOW → 刹车
3.3 完整控制代码示例
python复制import time
import RPi.GPIO as GPIO
# 引脚定义
ENA, IN1, IN2 = 12, 5, 6
ENB, IN3, IN4 = 13, 16, 17
def setup():
GPIO.setmode(GPIO.BCM)
GPIO.setup([ENA, IN1, IN2, ENB, IN3, IN4], GPIO.OUT)
global pwm_a, pwm_b
pwm_a = GPIO.PWM(ENA, 1000)
pwm_b = GPIO.PWM(ENB, 1000)
pwm_a.start(0)
pwm_b.start(0)
def move(speed=50, turn=0, timeout=0):
# speed: 0-100, turn: -100到100
left_speed = max(0, min(100, speed + turn))
right_speed = max(0, min(100, speed - turn))
pwm_a.ChangeDutyCycle(left_speed)
pwm_b.ChangeDutyCycle(right_speed)
# 设置方向
GPIO.output(IN1, left_speed > 0)
GPIO.output(IN2, left_speed < 0)
GPIO.output(IN3, right_speed > 0)
GPIO.output(IN4, right_speed < 0)
if timeout > 0:
time.sleep(timeout)
stop()
def stop():
pwm_a.ChangeDutyCycle(0)
pwm_b.ChangeDutyCycle(0)
GPIO.output([IN1, IN2, IN3, IN4], GPIO.LOW)
if __name__ == '__main__':
try:
setup()
move(50, 0, 2) # 直行2秒
move(30, 30, 1) # 右转1秒
move(30, -30, 1) # 左转1秒
finally:
stop()
GPIO.cleanup()
4. 常见问题与调试技巧
4.1 电机不转的排查步骤
-
检查电源:
- 用万用表测量L298N的12V输入是否正常
- 检查5V输出是否稳定(如有使用)
-
检查信号:
bash复制# 在树莓派上查看GPIO状态 gpio readall -
检查接线:
- 确认ENA/ENB已连接且PWM信号正常
- 用示波器或LED测试PWM输出
4.2 电机抖动或转速不稳
- 提高PWM频率(500Hz-1kHz通常最佳)
- 检查电源容量是否足够(建议2000mAh以上)
- 在电机两端并联0.1μF电容滤除干扰
4.3 控制延迟问题
- 避免使用time.sleep()做精确控制
- 改用多线程或asyncio实现非阻塞控制
- 考虑使用pigpio库替代RPi.GPIO(延迟更低)
python复制# 使用pigpio的示例
import pigpio
pi = pigpio.pi()
pi.set_PWM_frequency(ENA, 1000)
pi.set_PWM_dutycycle(ENA, 128) # 50%占空比
5. 进阶优化方向
5.1 增加PID速度控制
通过编码器反馈实现闭环控制:
python复制class PIDController:
def __init__(self, Kp, Ki, Kd):
self.Kp, self.Ki, self.Kd = Kp, Ki, Kd
self.last_error = 0
self.integral = 0
def update(self, error, dt):
self.integral += error * dt
derivative = (error - self.last_error) / dt
output = self.Kp*error + self.Ki*self.integral + self.Kd*derivative
self.last_error = error
return output
5.2 无线遥控实现
使用PS4手柄或手机APP通过蓝牙控制:
bash复制# 安装PyBluez库
pip3 install pybluez
5.3 电源管理优化
- 添加电压检测电路
- 实现低电量自动返回充电
- 使用MOSFET替代L298N提高效率
我在实际项目中发现,使用TB6612FNG驱动芯片比L298N效率更高(发热量减少约40%),但引脚定义和驱动方式略有不同,需要调整代码。另外,为每个电机添加霍尔编码器后,可以实现精确的里程计算和位置控制,这对构建自动驾驶小车特别有用。
