news 2026/9/20 13:03:18

树莓派4B循迹智能小车实战:ST188传感器与L298N电机驱动全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
树莓派4B循迹智能小车实战:ST188传感器与L298N电机驱动全解析

第一次把树莓派4B和ST188红外传感器接到智能小车底盘上那晚,我在客厅地板上贴了一圈黑色电工胶带,满心期待小车能顺着轨道自己跑起来,结果它纹丝不动。折腾了两个小时,最后发现只是传感器信号线在杜邦头上虚接了。后来我在这个项目上又断断续续调了几天,把循迹逻辑从两路改到四路,用Python重写了两版控制代码,这辆小车总算能在黑色胶带轨道上稳定跑完一圈又一圈。

这篇博客就完整记录我用树莓派4B做循迹智能小车的整个过程:硬件怎么选、ST188红外传感器到底怎么工作、L298N电机驱动怎么接线、Python代码怎么一步步写出来,以及我踩过的几个坑。适合刚入手树莓派、想从“点亮LED”进阶到“做一个能动的东西”的朋友,也适合学生创客比赛前临时抱佛脚。代码我会完整贴出来,你照着接线、照着改参数,大概率能直接跑通。

1. 项目拆解:一台循迹小车需要哪些零件,为什么是这套方案

1.1 整车硬件清单与大致预算

先把我实测用到的配置列出来,你在淘宝照搜就行:

配件型号/规格大致参考价
主控树莓派4B(2GB/4GB均可)300-600,看渠道
存储卡TF卡 32GB Class1030-50
小车底盘四轮TT马达底盘,带轮子和电机50-80
电机驱动L298N模块10-20
红外传感器ST188循迹模块 ×4单个几块到十几块
电机供电两节18650电池盒(7.4V左右)20-40
主控供电5V 3A充电宝或DC降压模块50-100
连接件杜邦线公对母/公对公、扎带、铜柱10-20

这套配置含底盘下来大概500-900元,主要浮动在树莓派价格上。如果你手里已经有树莓派,实际额外开销也就一百多。

树莓派放在小车上跑,散热片和风扇基本是必须的,树莓派4B全速跑起来发热挺明显,建议装一个带风扇的散热壳。底盘选四轮还是两轮驱动?我个人建议四轮TT马达底盘,便宜耐造,TT马达用普通的直流减速电机,控制逻辑和两轮完全一样。两轮+万向轮的底盘转向更灵活,但平衡和重心容易出问题,新手调试起来更费劲。

1.2 为什么主控选树莓派4B而不是STM32或Arduino

说实话,纯做循迹,用STM32或者Arduino在性能和成本上都比树莓派合适。STM32F103ZET6这种板子响应快、价格低,很多竞赛队都在用;Arduino语法简单,库一大把。但你要是第一次接触硬件,我建议直接上树莓派。

原因有三点。

第一,树莓派跑完整Linux系统,调试非常方便。程序崩了、引脚冲突、传感器读数不对,都能直接在系统里看日志、打印变量、甚至远程SSH进来改代码。单片机那边出问题往往要烧录器、串口线、JTAG全副武装才能定位。

第二,Python的GPIO开发对新手来说门槛最低。GPIO.input()读一次电平、GPIO.PWM()输出调速,都是几个函数的事,不需要处理寄存器、中断、定时器这些底层细节。你可以把精力集中在“循迹逻辑”本身。

第三,扩展性强。循迹只是第一步,后续加摄像头做OpenCV视觉巡线、加机械臂、做无线图传,树莓派都能继续胜任。我看到很多人项目做到一半就想升级,平台选好了能省一大笔换平台的成本。

当然,如果你已经有STM32或Arduino基础,这篇文章里的传感器原理、差速转向逻辑、PID思路也完全可以平移过去,代码思路是通用的。

1.3 ST188红外传感器选型,以及“几路循迹”怎么选

ST188是这次项目最关键的传感器之一。它的本质是一体化红外反射式光电传感器,内部封装了一个红外发射管和一个光电晶体管,结构小、成本低、用起来简单。循迹小车上常说的“灰度传感器”“循迹模块”,很多就是基于ST188或者同类方案做的。

网上搜索时还会看到“五路循迹传感器”这种说法,指的是板子上集成五路ST188。五路传感器的优势在于:中间一路能更精细地判断车身是否完全居中,转弯时也不容易丢线,十字路口、起跑线这些场景处理起来更稳定。但五路对我来说有一个问题——价格更高、接线更多,代码判断组合也多不少。

我的方案是四路,左右两侧各两路。四路能覆盖“左外、左内、右内、右外”的情况,既能判断轻微偏移,也能判断大弯道,属于性价比最高的中间档。两路循迹确实也能跑,但只有“偏左/偏右”两个信息,弯道稍微急一点就容易冲出线。

2. ST188红外传感器的工作逻辑:黑线为什么能被识别

2.1 光电反射原理:白色和黑色对红外线的反射率差异

循迹小车能认黑线,核心不是“看见”,而是“测量反射光”。

ST188模块上的红外发射管会一直向外发射红外光。光照射到物体表面后产生反射,光电晶体管负责接收反射回来的红外光。白色或者浅色表面反射率高,大部分红外光会回到接收管;黑色胶带表面吸收光线能力很强,反射回来的光非常少。接收管收到光越多,内部阻值变化越明显,模块把这种变化转化成电平信号输出。

用一个生活化的类比:晚上用手电筒照路,白色墙面会刺眼,黑色柏油路几乎不反光,瞳孔就能直观感受到区别。ST188就是一直在打手电筒并且盯着反射光的那个“眼睛”。

这里有个容易被忽略的点:传感器关心的不是“颜色”,而是“反射率”。如果你用的黑线是哑光黑,反射率很低,效果很好;如果你找一种反光的黑色材料,它的反射率可能比哑光白纸还高,这时候小车就会“看不见”黑线。所以我建议做轨迹时首选黑色电工胶带或赛道专用麦克线,不要用透明胶带或者光面塑料。

2.2 模块上的比较器在做什么,电位器又该拧到什么位置

市面上的ST188循迹模块通常有四个引脚:VCC、GND、OUT,部分模块还会多一个AOUT模拟量输出。如果你买的是带比较器版本(板子上有一颗小芯片,常见的是LM393),那就是数字量输出,直接读高/低电平就行。

比较器做的事情很简单:把光电晶体管产生的电压和电位器设定的阈值电压做比较,信号高于阈值输出一种电平,低于阈值输出另一种电平。所以白色高反射=电平翻转一下,黑色低反射=电平翻转回来。具体是“白低黑高”还是“白高黑低”,不同模块可能相反,我后面会说怎么实测确认。

电位器是拿来调灵敏度的。标准做法是:把传感器放到你要用的黑线上方正常工作高度,用小螺丝刀慢慢拧电位器,观察模块上的LED指示灯刚好在黑线/白底之间翻转的那个位置。注意不要拧得太“灵敏”,否则地面有一点色差、距离稍微变一点就会误触发。我一开始图省事把阈值调得很临界,结果小车在浅色木地板上跑着跑着就开始鬼畜。

还有一点,模块供电接3.3V还是5V?ST188模块标称3.3-5V都能工作,我建议接3.3V。原因很简单,树莓派的GPIO输入并不是所有引脚都做5V容忍,直接接5V输出存在烧坏引脚的风险,3.3V供电虽然检测距离会稍微短一点,但在这个高度完全够用,更稳妥。

2.3 装车高度、传感器间距的实测标定方法

传感器装车是第一个容易翻车的地方。

安装高度方面,ST188模块距离被测地面大约0.8cm到1.5cm比较合适。太近了,底盘稍微一颠簸,传感器会直接蹭到地面;太远了,白底和黑线的反射差异都会被稀释,模块输出不稳定。

传感器间距方面,四路传感器最好能覆盖在黑线两侧。拿2cm宽的黑线举例,传感器之间的间隔在1.5cm左右,让中间两路正好压在黑线两侧边缘,外侧两路位于白底上。你可以先把传感器固定到一块洞洞板或者用热熔胶粘在底盘前缘,不要一上来就锁死,跑几圈再微调。

标定时最直观的方法是先别写循迹逻辑,单独给树莓派跑一个读传感器的脚本,把四路传感器的实时输出打印到终端,然后用手把小车推到黑线上方、黑线外侧,观察每个值的变化。我强烈建议你在这个环节多花十分钟,确认每个传感器“看到黑线”和“看到白底”时分别读到什么,再开始往下写代码。

3. 树莓派侧环境准备:系统、SSH、GPIO库

3.1 烧录系统时就把SSH和WiFi配好

树莓派不一定要接显示器、键盘才能用,尤其是装在车上以后,接显示器完全不现实。我这边是全程无头模式,也就是只用SSH远程操作。

烧录系统用树莓派官方Imager工具就行,TF卡插电脑上,选择Raspberry Pi OS并写入。Imager有一个容易被忽略的齿轮设置按钮,烧录前点开,可以把SSH打开、设置WiFi账号密码、设置登录用户名和密码,一次全配好。如果你用的是旧镜像版本,烧完之后也可以手动在SD卡boot根目录放一个无扩展名的ssh空文件来开启SSH,再放一个wpa_supplicant.conf文件来配置WiFi。

这里顺带说一句,有人喜欢给树莓派4B装Ubuntu 20.04/22.04 Server,我也试过。能做,但树莓派官方系统对GPIO、PWM这些底层外设的支持最及时,新手不建议折腾,直接用官方Raspberry Pi OS最省事。

3.2 BCM编号和物理引脚:接线别再数错

树莓派上的GPIO有两种编号方式,很多人就是在这里被绕晕的。

  • BOARD编号:按物理引脚位置编号,1到40
  • BCM编号:按芯片内部的GPIO编号,比如GPIO17、GPIO18

在Python代码里你首先要写一行GPIO.setmode(GPIO.BCM),之后所有引脚都按BCM编号来。我的接线表是这样:

功能树莓派BCM编号
左外传感器 OUTGPIO 5
左内传感器 OUTGPIO 6
右内传感器 OUTGPIO 13
右外传感器 OUTGPIO 19
左电机 IN1GPIO 23
左电机 IN2GPIO 24
左电机 PWM ENAGPIO 25
右电机 IN3GPIO 17
右电机 IN4GPIO 18
右电机 PWM ENBGPIO 22

建议把这张表格抄下来贴在手边,接线前先对着表标一遍。我身边所有做树莓派小车的朋友,至少有一半的时间都花在校对引线上。

3.3 RPi.GPIO和gpiozero怎么选,库怎么装

树莓派上Python控制GPIO的库主要有两个:RPi.GPIOgpiozero

RPi.GPIO是经典老库,教程最多,出问题后网上随便一搜就能找到答案。它要求你手动初始化引脚、手动清理资源,代码稍微“原始”一点,但正因为原始,每一步都看得明白,很适合学原理。

gpiozero是官方推荐的现代库,API面向对象,几行代码就能让LED闪烁、电机转动,上手非常快。但对循迹小车这种需要细粒度控制、实时读多个传感器状态的场景,gpiozero封装层级多,排查问题时反而要多绕一圈。

我的建议是用RPi.GPIO,原因就是要排查顺滑。安装命令如下:

sudo apt update sudo apt install -y python3-pip pip3 install RPi.GPIO

如果你发现自己电脑上开发Python要配环境卡了一天,这里给你一个取巧方案:直接在树莓派上装Thonny或者VS Code,代码写完在树莓派本地跑,不用搞什么远程开发映射。等后面项目复杂了再去配VS Code Remote SSH也不迟,前期别给自己制造障碍。

4. 电机驱动与PWM调速:让L298N老老实实听话

4.1 L298N接线图和方向真值表

L298N是智能小车圈子里最常见的电机驱动模块,双路H桥,能控制两个直流电机的方向和速度。我习惯叫它“大板子”,因为它的散热片和接线端子很有辨识度。

接线有几个关键点。

第一,动力电接模块的“12V”输入端子,我这边用两节18650串联,实际电压在7.4V左右,L298N完全能工作。第二,模块上的“5V输出”可以给ST188传感器模块供电,但绝对不要拿来给树莓派供电,这个问题后面踩坑部分细说。第三,L298N的GND必须和树莓派的GND连在一起。逻辑信号需要一个公共参考地,不然IN1、IN2的电平对电机驱动芯片来说就是悬空的,表现就是电机乱转、不转或者时转时不转。

方向和使能的关系看这张表:

ENA/ENBIN1/IN3IN2/IN4电机状态
PWM(占空比控制)10正转,速度随占空比
PWM01反转,速度随占空比
PWM00停止,无制动
PWM11刹车

我需要特别强调“共地”这件事。桥式驱动电路如果没有共地,输入信号就没有参考基准,树莓派说“这是高电平”,电机驱动芯片根本不认,这是新手做小车第一个隐藏坑。

4.2 用Python输出PWM控制转速

树莓派本身GPIO只能输出高/低电平,要给电机调速就需要PWM脉冲宽度调制。原理不复杂:通过以极高的频率让引脚在高低电平之间切换,控制高电平持续时间的比例,也就是占空比。占空比100%电机全速跑,占空比50%电机大概半速。

RPi.GPIO里,创建一个PWM对象并启动:

pwm_left = GPIO.PWM(ENA, 2000) # ENA引脚,频率2000Hz pwm_left.start(0) # 初始占空比0 pwm_left.ChangeDutyCycle(60) # 改成60%

频率选多少合适?我实测1000Hz到5000Hz都能用,中间2000Hz比较舒服。频率太低,比如50Hz,电机会一顿一顿地转,声音听起来像风扇转动那种低频嗡鸣,还会造成车辆抖动。频率太高,软件PWM的切换开销变大,L298N的开关损耗也会上升,没必要。

RPi.GPIO的PWM属于软件PWM,任何GPIO引脚都能用,但对高频率大循环不太友好,容易占用CPU。树莓派4B性能足够,2000Hz没压力。如果你追求更高精度,可以考虑用树莓派的硬件PWM引脚12、13、18、19,不过L298N本身开关速度有限,软件PWM已经能跑出不错的控制效果。

4.3 动起来之前先写一个电机自检脚本

很多教程一上来就贴完整循迹代码,跑不动了回头怀疑传感器。我强烈建议你先写一个电机自检脚本,只验证一件事:电机转不转、方向对不对。

自检脚本很简单:让左轮前进1秒,停1秒,后退1秒;然后右轮同样来一遍。代码结构如下:

import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) IN1, IN2, ENA = 23, 24, 25 IN3, IN4, ENB = 17, 18, 22 for pin in [IN1, IN2, IN3, IN4, ENA, ENB]: GPIO.setup(pin, GPIO.OUT) pwm_left = GPIO.PWM(ENA, 2000) pwm_right = GPIO.PWM(ENB, 2000) pwm_left.start(0) pwm_right.start(0) def set_motor(in_a, in_b, pwm, speed): if speed > 0: GPIO.output(in_a, GPIO.HIGH) GPIO.output(in_b, GPIO.LOW) pwm.ChangeDutyCycle(speed) elif speed < 0: GPIO.output(in_a, GPIO.LOW) GPIO.output(in_b, GPIO.HIGH) pwm.ChangeDutyCycle(-speed) else: GPIO.output(in_a, GPIO.LOW) GPIO.output(in_b, GPIO.LOW) pwm.ChangeDutyCycle(0) try: print("左轮前进") set_motor(IN1, IN2, pwm_left, 50) time.sleep(2) set_motor(IN1, IN2, pwm_left, 0) time.sleep(1) print("右轮前进") set_motor(IN3, IN4, pwm_right, 50) time.sleep(2) set_motor(IN3, IN4, pwm_right, 0) finally: pwm_left.stop() pwm_right.stop() GPIO.cleanup()

如果小车装上的是两组轮子,有一个电机正负极接反,就会出现“一个前进一个后退”,车身原地打转,这一步就能抓出来。如果一侧电机不转,优先检查L298N对应的OUT端子、IN引脚以及ENA是否给了PWM信号,八成是松线。

5. 循迹代码逐行解析:从传感器读到三轮差速控制

5.1 先读传感器,确认“黑线读到1还是0”

很多初学者直接跑完整代码,发现小车完全不动或者反向乱跑,其实问题出在电平约定上。不同厂家的ST188模块,黑线和白底对应的输出电平可能正好相反。

所以第一步永远是打印读数。你可以用这样一个简单的脚本:

import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) SENSOR_PINS = [5, 6, 13, 19] for pin in SENSOR_PINS: GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) try: while True: values = [GPIO.input(pin) for pin in SENSOR_PINS] print(values) time.sleep(0.1) except KeyboardInterrupt: GPIO.cleanup()

然后把传感器分别放到黑线上和白底上,看终端输出。我的模块是“黑线上读到1,白底读到0”,下面所有逻辑都基于这个约定。如果你的模块正好相反,把所有判断里等于1和等于0的情况对调就行。

这里的pull_up_down=GPIO.PUD_UP设置的是内部上拉。因为有些ST188模块的输出是开漏结构,如果不加上拉,引脚会处于悬空状态,读到的电平会随机飘。加上内部上拉之后,默认电平被拉到高电平,输出低电平时也能被正确识别。如果模块本身带强上拉或推挽输出,这个设置不会造成副作用,可以放心加。

5.2 四路传感器状态与转向动作的映射关系

四路传感器从左到右排列为:左外、左内、右内、右外。每个状态组合都代表车身相对黑线的一个位置关系,我整理成了下表,仍以“黑=1”为例:

传感器状态含义动作
(0,0,0,0)完全脱线,四路都在白底低速直行,尝试找回黑线
(0,1,1,0)中间两路压线,车身很正左右轮等速直行
(1,0,0,0)左外压线,说明线在车身最左边大幅左转
(0,1,0,0)左内压线,车身轻微右偏轻微左转
(0,0,1,0)右内压线,车身轻微左偏轻微右转
(0,0,0,1)右外压线,线在车身最右边大幅右转
(1,1,0,0)左边两路压线,进入左转弯左轮反转/减速,右轮加速
(0,0,1,1)右边两路压线,进入右转弯右轮反转/减速,左轮加速
(1,1,1,1)十字路口或者超粗黑线直行通过

这里有个核心概念叫差速转向。左转不是方向盘打过去,而是右侧轮子转得比左侧轮子快,甚至左侧轮子反转,车身就会向左偏。转弯力度不是拍脑袋定的,你要看传感器的“压线位置”有多靠外。压线在左内,说明偏移不大,内轮稍微减速就能纠正;压线在左外,说明偏移很大,必须让左轮轻微反转,才能快速拉回来。

5.3 完整可跑通的main.py

下面是完整代码,我加了中文注释,你可以直接复制修改:

import RPi.GPIO as GPIO import time # ---------- 接线参数(BCM编号) ---------- # 四路ST188传感器,从左到右:左外、左内、右内、右外 SENSOR_PINS = [5, 6, 13, 19] # L298N电机驱动 IN1, IN2, ENA = 23, 24, 25 # 左电机 IN3, IN4, ENB = 17, 18, 22 # 右电机 # ---------- 初始化 ---------- GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) for pin in SENSOR_PINS: GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) for pin in [IN1, IN2, IN3, IN4, ENA, ENB]: GPIO.setup(pin, GPIO.OUT) pwm_left = GPIO.PWM(ENA, 2000) pwm_right = GPIO.PWM(ENB, 2000) pwm_left.start(0) pwm_right.start(0) # ---------- 电机控制函数 ---------- def set_motor(in_a, in_b, pwm, speed): """ speed: -100 到 100 正数前进,负数后退,0停止 """ if speed > 0: GPIO.output(in_a, GPIO.HIGH) GPIO.output(in_b, GPIO.LOW) pwm.ChangeDutyCycle(speed) elif speed < 0: GPIO.output(in_a, GPIO.LOW) GPIO.output(in_b, GPIO.HIGH) pwm.ChangeDutyCycle(-speed) else: GPIO.output(in_a, GPIO.LOW) GPIO.output(in_b, GPIO.LOW) pwm.ChangeDutyCycle(0) def run(left_speed, right_speed): set_motor(IN1, IN2, pwm_left, left_speed) set_motor(IN3, IN4, pwm_right, right_speed) # ---------- 传感器读取 ---------- def read_sensors(): return tuple(GPIO.input(pin) for pin in SENSOR_PINS) # ---------- 主循环 ---------- if __name__ == '__main__': BASE_SPEED = 55 # 直行基础速度 TURN_SPEED = 45 # 转弯时保持轮速度 REVERSE_SPEED = 45 # 转弯时反转轮速度 LOOP_INTERVAL = 0.02 # 控制周期20ms try: while True: s = read_sensors() # 调试时保留打印,观察四路状态 print(s) # 直行 if s == (0, 1, 1, 0): run(BASE_SPEED, BASE_SPEED) # 全黑,可能是十字路口,直行通过 elif s == (1, 1, 1, 1): run(BASE_SPEED, BASE_SPEED) # 全白,脱线了,低速直行找回 elif s == (0, 0, 0, 0): run(30, 30) # 明显偏右,强左转 elif s == (1, 0, 0, 0): run(-REVERSE_SPEED, TURN_SPEED) # 轻微偏右,弱左转 elif s == (0, 1, 0, 0): run(20, BASE_SPEED) # 轻微偏左,弱右转 elif s == (0, 0, 1, 0): run(BASE_SPEED, 20) # 明显偏左,强右转 elif s == (0, 0, 0, 1): run(TURN_SPEED, -REVERSE_SPEED) # 左边两路都压线,大左弯 elif s in [(1, 1, 0, 0), (1, 1, 1, 0)]: run(-REVERSE_SPEED, TURN_SPEED) # 右边两路都压线,大右弯 elif s in [(0, 0, 1, 1), (0, 1, 1, 1)]: run(TURN_SPEED, -REVERSE_SPEED) # 其他怪状态,按直行兜底 else: run(BASE_SPEED, BASE_SPEED) time.sleep(LOOP_INTERVAL) except KeyboardInterrupt: pass finally: pwm_left.stop() pwm_right.stop() GPIO.cleanup()

代码中最容易忽略的两点我必须单独讲一下。

第一,finally里的GPIO.cleanup()很关键。如果程序被Ctrl+C中断而没有清理引脚,下次运行时会提示GPIO已经被占用,有时还需要重启树莓派才能恢复。养成每次写完都带清理逻辑的习惯,能省下很多莫名其妙的时间。

第二,read_sensors()返回的是元组,打印出来形如(0, 1, 0, 1),这个值在跑车时一定要实时看。我把print(s)放在循环里,虽然会往终端刷屏,但对定位“哪个传感器不灵”特别有用。等调试稳了,可以把打印去掉或者改成有条件打印。

5.4 车速和控制周期的调参思路

代码能跑通之后,你会面临一个真正影响体验的问题:参数怎么调。

先说基础速度。我初始给了55,适合我手上这套TT马达。如果你发现小车直行时明显抖动或一冲一冲的,先把速度降到30-35,跑顺了再往上加。循迹小车不是越快越厉害,是“稳定圈速”才厉害,先稳再快。

再说转弯力度。大幅转弯用-REVERSE_SPEED让内侧轮反转,纠偏力度很大,但如果地面摩擦力太大或者速度太快,反转会造成甩尾。遇到这种情况,把内侧轮反转改成减速到0,即run(0, TURN_SPEED),牺牲一点响应速度换取姿态稳定。

控制周期LOOP_INTERVAL我设的是20ms,也就是每秒执行50次状态判断。这个频率对常见黑线轨道完全够用。如果轨道弯道特别急、车速偏快,可以把间隔缩短到10ms,但也要注意树莓派上Python的循环本身有系统调度开销,不是越短越好。太短反而可能因为GPIO读取抖动造成误判。10ms到30ms之间都是合理区间,别把它设成100ms这种明显过长的值。

6. 实测踩坑记录:黑线失控、车身抽搐、跑着跑着重启

6.1 传感器全输出高电平,最全的排查链路

我开头提到的那次“小车纹丝不动”,就是典型的传感器故障。排查过程很值得分享。

当时的症状是:打印四路传感器读数,全是(1, 1, 1, 1),无论我把小车推到黑线上还是白地上,数值一动不动。我的排查链路是这样的:

第一步,单独验证传感器模块本身。把其中一个ST188模块从底盘上拆下来,直接用杜邦线接到树莓派3.3V、GND和一个GPIO口,然后拿黑色物体在模块前方来回移动,看LED灯和打印值是否翻转。这个模块正常翻转,说明模块本身没坏。

第二步,怀疑是插到树莓派那一端的问题。换了一根杜邦线重新接,数值开始正常。继续检查,发现原来的信号线在杜邦头内部的金属弹片有一点松动,插上去时偶尔接触不良,GPIO在内部上拉作用下就一直读到高电平。

这个问题很隐蔽,因为它不是完全不导通,而是时断时续。排查经验就一条:如果所有传感器数值恒定不变,优先怀疑“信号线是否真的把信号传到了GPIO”,不要先怀疑代码逻辑。用万用表蜂鸣档测杜邦线两端通断,或者干脆换新线,比盯着代码猜快得多。

6.2 小车走S形、原地画龙,先别急着怀疑PID

很多人遇到小车左右摇摆、轨迹像波浪一样,第一反应是“我需要PID”。但实际上一大半情况是机械或供电问题,不是控制算法问题。

我遇到过一次小车持续画龙,排查后发现是传感器安装高度太高。模块离地约2cm,白色底面的反射光也不强,阈值翻转很不稳定,传感器隔几秒就误判一次,车身就会来回纠正。把传感器降到1cm附近,问题立刻消失。

其他常见原因按频率排序:左右轮实际速度不一致,直行时本身就往一侧偏,循迹逻辑一直在纠正,看起来就是S形;黑线和白底的反差不足,模块临界状态抖动;车身重心太靠后,前轮传感器在颠簸时离地高度变化太大;还有电池电量不足,电机转速随电压下降而波动。

排查顺序建议是:先直行测试看会不会偏,再晃动底盘看传感器读数稳不稳,最后才回来调速度和控制周期。

6.3 电机一启动树莓派就重启,这是电源问题

这个坑几乎每个玩树莓派小车的人都会踩,我必须多说几句。

现象是:代码一跑,电机还没转几圈,树莓派就直接重启,或者SSH断开,系统日志里出现“low voltage”之类的提示。本质是电源电压被电机启动瞬间的大电流拉垮了。

最容易犯的错误是:让L298N模块上的“5V输出”给树莓派供电。L298N板载的稳压芯片确实能输出5V,但它的能力很弱,只能带带传感器、逻辑电路这种小负载。电机一启动,电流需求暴涨,5V输出立刻跌落,树莓派4B这种对供电质量敏感的设备瞬间黑屏重启。

正确方案是树莓派和电机完全独立供电,两套电源之间只把GND连在一起。电机侧用两节18650串联给L298N;树莓派侧用一个能稳定输出5V 3A的电源。如果你用充电宝,也要小心一个问题:很多充电宝有“低电流自动断电”保护,树莓派4B待机电流通常大于充电宝最低检测阈值,但电机一启动电流大幅波动,有些充电宝会误判为过流或短路而切断输出。实测下来,带PD协议或专门为树莓派设计的电源更省心。

6.4 白地板、强光和不同黑线带来的干扰

我之前在地下车库测试时发现小车在明亮区域的弯道频繁误判,到了阴影下又恢复正常。原因是车库顶部灯光直射给传感器带来了额外的红外干扰。循迹小车最好在室内普通灯光环境下测试,避免太阳光直射,环境光线越稳定,阈值越可靠。

如果地面本身是深色木地板或者灰色地砖,白底和黑线的反射差异会变小,模块翻转变得不干脆。我建议用纯黑色PVC电工胶带贴轨道,和常见的浅色地板反差足够。如果场地已经固定没法换,那就把电位器调得稍微“不灵敏”一点,让黑线触发更可靠,宁可白底偶尔漏判也不要黑线误判成白。

还有一个小技巧:轨道连接处不要留明显缝隙,传感器经过接口时可能出现瞬时的“全白”误判。我用黑色胶带接头时都会重叠一小段,保证轨迹连续。

7. 小车稳定运行后,你还可以继续改什么

7.1 给循迹加上PID让转向更平滑

状态判断法的缺点大家应该能感觉到:动作是离散的,要么直行、要么一个固定力度转弯,所以车身会有轻微顿挫。如果想要更平滑的过弯,可以在状态判断之上加一层PID。

具体做法是把四路传感器的压线位置映射成一个偏差量,比如中间两路压线偏差为0,左内压线偏差为-1,左外压线偏差为-2,右边对称。然后用比例项计算左右轮速度差,偏差越大转向越猛;再引入微分项抑制震荡,最后才是积分项消除稳态误差。注意PID不是灵丹妙药,参数调不好会比纯状态判断更乱。我的建议是先把状态判断版本跑到熟练,再尝试把速度输出从“查表”改成“公式计算”。

7.2 升级摄像头巡线和无线遥控

树莓派做循迹的真正优势在升级空间。红外循迹只能在贴好轨道的场景跑,而摄像头巡线可以识别任意路径,还能实时分析弯道形状。流程不外乎:用picamera采集图像,OpenCV转灰度、二值化,找黑线的轮廓质心作为偏差量,然后沿用差不多的差速控制逻辑。

想玩遥控也不难,接一个无线手柄接收模块,或者用手机App通过网络控制树莓派,把注意力放到机器人控制上。很多人就是从这辆循迹小车开始,一步步走到了自己的第一个完整机器人项目。

7.3 最后分享一个调试小习惯

回到一开始说的那次杜邦线虚接。我后来把所有设备的接线都整理成了表格,打印出来贴在底盘底下,每次调试车翻过来就能直接核对,省掉了大量重复记忆和猜测时间。另外我在main.py里保留了状态打印,跑车时通过SSH实时看到四路传感器的状态变化,出问题先看输出数据,再判断是硬件还是逻辑,效率高很多。

如果你也准备动手做这辆小车,我的一点点建议是:先把电机自检跑通,再让传感器有稳定读数,最后才写完整循迹逻辑,每一步都确认没问题再往前推进。按这个节奏,你大概率不会像我第一次那样,在地上蹲到腿麻,结果只是坏在一根杜邦线上。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 13:02:48

GD32F103C8T6标准库RS485通讯实战:方向切换与TC标志避坑指南

简介&#xff1a;基于GD32F103C8T6单片机的RS485通讯标准库工程代码&#xff0c;面向嵌入式开发者和入门学习者&#xff0c;解决GD32平台上485总线通信的底层配置与数据收发问题。压缩包共73个文件、约326KB&#xff0c;以31个h头文件与27个c源文件为主&#xff0c;配合uvprojx…

作者头像 李华
网站建设 2026/9/20 12:58:30

baoyu-diagram 流程图(Flowchart)SVG 绘制规范与实战指南

baoyu-diagram 流程图&#xff08;Flowchart&#xff09;SVG 绘制规范与实战指南 【免费下载链接】baoyu-skills 项目地址: https://gitcode.com/gh_mirrors/ba/baoyu-skills 本文是基于 baoyu-skills 仓库中 baoyu-diagram 技能的 Flowchart 布局参考文档&#xff08;…

作者头像 李华
网站建设 2026/9/20 12:57:46

10分钟做出可用的OpenCore EFI:OpCore Simplify快速上手指南

10分钟做出可用的OpenCore EFI&#xff1a;OpCore Simplify快速上手指南 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 手动配黑苹果 EFI&#xff0c…

作者头像 李华
网站建设 2026/9/20 12:54:08

效率直接起飞!盘点2026年实力封神的的AI论文软件

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文软件正在席卷学术圈&#xff0c;覆盖选题构思、文献整理、内容生成、降重润色等核心场景&#xff0c;真正帮你高效搞定论文写作。 一、全流程王者&#xff1a;一站式搞定论文全链路&#xff08…

作者头像 李华