
做一台能在房间里自己转悠、主动绕开障碍物还能在发现目标的第一时间停下来、扫描确认、再把信号传回手机的小车可能是Arduino玩家进阶路上最有成就感的一个项目。基于Arduino UNO的自动搜救小车就是把一辆普通遥控车的壳子拆掉装上一整套感知-决策-执行-回传闭环的典型练习。这篇东西我不想只给你一份零件清单和几段代码而是把自己从选型、接线、写状态机到现场调参、排查误报的完整过程都摊开讲。打算入机器人坑的同学、正在做课程设计的读者可以直接照着这个思路搭一台自己的搜救小车。1. 从会动的小车到会搜救的小车中间差的是整套闭环1.1 搜救场景对小车提出了什么硬性要求很多朋友第一次做小车装个超声波避障就觉得差不多了。但避障和搜救是两码事。避障只是别撞上搜救要求的是小车要在未知环境里自主移动、尽量覆盖大部分区域、在行程中发现目标、停下来确认、然后把结果告诉外面的人。这个链条里任何一个环节断了它都只是一台会动的玩具。现实中的搜救场景比如灾害后的室内环境、狭小管道、人进不去的塌陷区核心诉求其实就几条体积小、能钻能绕、能持续巡检、发现生命迹象或危险源后能准确上报。我没有能力做一台真正能在废墟里翻越障碍的履带机器人但我可以把这套逻辑在小尺寸的轮式平台上完整跑通。做出来之后你会发现换传感器、换底盘都是小事最难的是让它自主地走完整个流程。1.2 感知-决策-执行-回传机器人运作的基本盘搜救小车的自主性本质上来自一个闭环传感器负责看和摸主控负责想电机负责动通信模块负责说。用生活里的例子类比就像一个人进了一间陌生屋子找东西——眼睛看路、手摸桌角、大脑判断往哪走、找到东西之后张嘴喊人。小车只是把这些动作全部电子化、代码化。具体到我的方案里感知层超声波测距模块负责前方障碍物探测红外避障传感器负责低处盲区补漏火焰传感器或人体热释电模块负责搜救目标探测舵机云台带着超声波左右扫描。决策层Arduino UNO读取传感器数据运行一个状态机决定当前是直行、转向、停止还是发报警。执行层直流减速电机配合驱动板完成前进、后退、左右转弯。回传层蓝牙模块把小车当前状态、检测距离、探测结果实时发到手机。这个分层思路是通用的以后你换主控、加摄像头、上ROS底层逻辑还是这一套。1.3 为什么在这个项目上选Arduino UNO而不是别的板子做搜救小车可以用的主控很多树莓派、ESP32、STM32甚至 Jetson Nano。但我最终还是选了 Arduino UNO原因很实在UNO是5V逻辑电平跟大量传感器模块、驱动板直接对接不用做电平转换。这个省掉的麻烦新手可能体会不到老手一定懂。生态成熟资料巨多。超声波、舵机、蓝牙、火焰传感器每一个模块的样例代码都能搜到遇到问题排查起来快。8位单片机虽然性能一般但搜救小车这种任务实时性要求并不高测距周期几十毫秒完全够用。把代码组织好了UNO的16MHz主频和2KB SRAM绰绰有余。课程设计、竞赛展示场景里UNO的透明感本身就是优势——评委一看就明白系统架构答辩时不用解释主控为什么这么选。树莓派确实能跑视觉识别但它的启动时间、供电稳定性、硬件成本都更适合做进阶项目。先把UNO这套跑通是性价比最高的路径。2. 硬件选型这套配置里每一块钱都有它的理由2.1 底盘与电机两驱还是四驱别被参数忽悠了底盘我用的是最常见的亚克力两驱车架加两个TT直流减速电机、一个万向轮。四驱底盘我也试过动力确实猛但在室内平地上反而是负担——电机多两个功耗高、转向半径大、控制复杂度也上去。搜救场景讲究钻而不是冲两驱加万向轮的灵活性足够用了。电机驱动选的是L298N模块。虽然它有点老、压降大但胜在皮实、便宜、资料多。接线就两组电机A和电机B各自的IN1、IN2、ENA、IN3、IN4、ENB逻辑就两条——ENA给PWM调速IN1/IN2决定正反转。如果你想让小车跑得细腻一点可以换成TB6612FNG体积更小、效率更高但驱动电流稍小。预算二十块以内L298N足够。这里有个新手必踩的坑L298N板载的5V稳压输出很多人拿来直接给Arduino供电结果小车一动Arduino就重启。因为L298N的稳压芯片在电机启动瞬间压降巨大输出根本稳不住。我的做法是电机电源单独一路Arduino用自己独立的降压模块供电两边的地线连在一起就行。2.2 感知层超声波做主视觉红外做触觉搜救车对感知的要求是少盲区所以我配了三类传感器各管一段HC-SR04超声波模块装在舵机云台上负责前方30厘米到4米范围内的测距。它原理是发出40kHz超声波测回声返回时间距离等于时间乘以声速再除以2。注意它有个天生毛病探测面比较窄而且对斜面、细杆这类目标容易丢信号所以不能只靠它一个。两个红外避障传感器装在车头左右两侧低位负责探测超声波够不到的近距盲区。红外传感器本质是一个红外发射管加一个接收管前方有障碍物时反射光增强、输出电平翻转简单粗暴但有效。搜救目标探测我用了两套方案大家可以按需选一套是火焰传感器探测前方红外火焰光谱用来模拟发现火源/危险源场景另一套是热释电人体红外模块HC-SR501探测生命体的热辐射更贴近搜救生命迹象的语义。两个模块都是数字量输出接到Arduino数字引脚就行。舵机云台的作用是让超声波转头。固定安装的超声波只能看正前方装到舵机上之后小车每走一段就左右扫一遍相当于把单点测距变成区域扫描搜救覆盖率完全不一样。2.3 通信与反馈让小车把话说清楚搜救车不是自己闷头跑的它得把状态告诉外面的人。我用HC-05蓝牙模块做无线串口手机装个串口调试助手就能实时看到小车发的消息。HC-05默认是AT命令模式需要先设置波特率和配对密码然后再切到透传模式。具体怎么配网上教程一大堆我只提醒一句AT模式配置的时候模块的EN引脚要拉高否则进不去。除了蓝牙我还加了三个反馈元件一个无源蜂鸣器找到目标时发出提示音两个LED指示灯绿色表示正在巡检红色表示发现目标一块0.96寸OLED屏实时显示当前状态、前方距离和电池电压通过分压电阻采ADC。这些小东西成本加起来不到二十块钱但对调试的帮助是巨大的——你不用每次看手机才能知道小车在想什么屏幕上直接就有。2.4 供电方案最容易翻车的一环认真看搜救小车要长时间跑供电绝不能含糊。我的方案是模块工作电压电流估算供电来源Arduino UNO5VVin 7-12V50-100mA7.4V锂电池经降压模块转5VL298N驱动板7-12V电机堵转可达1-2A7.4V锂电池直接供电舵机SG904.8-6V堵转峰值约700mA5V降压模块单独一路HC-SR045V约15mAArduino 5V引脚蓝牙/传感器/OLED3.3/5V合计约50mAArduino 5V引脚注意几点第一舵机启动瞬间电流很大如果跟Arduino共用一个5V稳压模块很容易把MCU电压拉垮导致复位所以我单独给舵机一路供电第二电池用两节18650串联标称7.4V最省钱但电压会从8.4V降到6V左右L298N在低电压下输出功率下降实测小车速度会明显变慢所以要么选带保护板的电池组要么在软件里做低压告警第三所有模块的地线必须共地否则串口通信和传感器读数会乱飘。3. 状态机控制逻辑让小车自主的不是段代码而是一套状态3.1 为什么必须用状态机而不是堆一堆if判断我第一版代码就是从前往后写先避障再检测再报警结果就是一锅粥——小车撞到墙之后可能永远没机会检测目标。后来我把整个行为改成了状态机逻辑瞬间清晰了。状态机的核心思想是小车任何时刻都处于某个明确状态里每个状态只做一件事事件触发才切换到另一个状态。我的搜救小车定义了六个状态IDLE上电初始化自检传感器原地转一圈。SEARCH正常巡检沿墙或按S形路线走超声波云台周期性左右扫描。AVOID发现障碍物距离小于安全阈值进入避障逻辑先停下判断方向再绕行。DETECT搜救传感器触发停车进入检测流程。CONFIRM连续多次采样确认目标防止误报同时云台扫描一圈确认。REPORT确认无误后蜂鸣器响、LED变红、蓝牙发送发现目标位置信息保持5秒然后回到SEARCH继续巡检。用状态机的好处是每个状态内部代码简单状态跳转一目了然出问题的时候通过串口打印当前状态两分钟就能定位到问题环节。这是做机器人项目非常值得养成的好习惯。3.2 避障策略的三种取舍我选了沿墙走避障算法看着简单其实选择很多。三种主流策略遇到障碍就原地转向实现最简单但小车会像无头苍蝇覆盖率差同一个区域反复跑。随机转向加区域记录逻辑稍微复杂一点类似扫地机器人覆盖面广但不可控。沿墙行走wall following保持超声波测距读数在一个目标区间内比如25-35厘米远了就往墙靠近了就往外偏。这个策略在室内走廊、房间场景下覆盖率非常高而且给人感觉像在认真搜索。我最终用了沿墙为主、盲区扫测为辅的策略。在SEARCH状态里小车以恒定速度前进超声波每100毫秒测一次前方距离舵机每2秒左右扫一遍。如果前方距离小于40厘米进入AVOID如果右侧距离读数告诉我墙在右边我就维持右墙距离目标值。这个策略在规则室内环境里表现很稳调试也直观。3.3 搜救检测与确认机制别让小车狼来了搜救目标探测最怕的就是误报。火焰传感器对阳光、白炽灯光都敏感热释电模块对温度变化敏感一次误报就会让整个搜索过程断掉。我的处理方式是三重确认时间维度检测信号必须持续1秒以上软件里连续采样10次避免瞬间干扰。空间维度触发后小车原地停车云台从左到右扫描一遍要求超声波测得的目标区域距离稳定、目标信号持续存在。逻辑维度进入CONFIRM状态后如果信号再次触发才确认如果中途丢失退回SEARCH状态继续跑。这套确认机制直接治好了我的误报焦虑。事实上后来的实测里小车在阳光充足的窗边跑火焰传感器确实误报过几次但三重确认机制把所有误报都拦在REPORT之前了。3.4 核心代码框架可以直接抄的底座状态机部分我用switch实现代码结构如下enum State { IDLE, SEARCH, AVOID, DETECT, CONFIRM, REPORT }; State currentState IDLE; void loop() { updateSensors(); // 更新超声波、红外、搜救传感器、电压 switch (currentState) { case IDLE: selfCheck(); if (selfCheckOK) currentState SEARCH; break; case SEARCH: wallFollow(); if (frontDistance SAFE_DISTANCE) currentState AVOID; if (detectSignal()) currentState DETECT; break; case AVOID: avoidObstacle(); if (frontDistance SAFE_DISTANCE HYSTERESIS) currentState SEARCH; break; case DETECT: stopMotors(); if (confirmDetect()) currentState CONFIRM; else currentState SEARCH; break; case CONFIRM: scanAndVerify(); if (verified) currentState REPORT; else currentState SEARCH; break; case REPORT: reportTarget(); delay(5000); currentState SEARCH; break; } printStatus(); // 串口/OLED输出状态和传感器值 delay(20); }超声波测距建议加滤波我用的是一次去掉最大最小值后的均值滤波每轮取5个读数float readDistance() { const int N 5; float samples[N]; for (int i 0; i N; i) { samples[i] measureOnce(); delay(10); } // 简单冒泡去掉最大最小 sort(samples, N); float sum 0; for (int i 1; i N - 1; i) sum samples[i]; return sum / 3.0; // 单位: cm }电机控制建议封装成函数后续逻辑层只调用forward()、backward()、turnLeft()、turnRight()不要在状态机里直接写PWM否则调参的时候会疯掉。调参参数我放在文件头部const int SPEED_NORMAL 140; // 正常巡检PWM值范围0-255 const int SPEED_TURN 120; // 转向时的PWM值 const int SAFE_DISTANCE 35; // 触发避障的距离阈值(cm) const int HYSTERESIS 10; // 回滞量防止状态反复跳变 const int WALL_TARGET 30; // 沿墙目标距离(cm) const int WALL_TOLERANCE 5; // 沿墙距离容差(cm)回滞量这个概念值得说一下。如果没有它小车在阈值附近来回跳一会儿避障一会儿前进状态机就会抖动。加了回滞量之后进入避障需要距离小于35cm但退出避障需要距离大于45cm中间的10cm缓冲区让行为稳定很多。4. 装配与接线实操按这个顺序做翻车概率最小4.1 先把底盘和电机装利索我踩过的第一个坑就是装反了电机方向。TT电机有左右之分但你从外观上看不出来。建议先不固定电机接上电源分别测试两个电机的旋转方向把转向一致的电机装到同一边然后固定。固定方式用底盘自带的螺丝加扎带加固否则跑起来电机会移位履带或轮子会蹭到车架产生很大的异响和阻力。万向轮的高度要注意装好之后四个支撑点要基本在一个平面上否则小车跑起来像瘸腿一边轮子空转一边轮子吃力续航和直线性都完蛋。我调整的办法是在万向轮和底板之间加垫片直到用手推车能顺畅直线滑行为止。电机驱动板L298N我直接叠放在底盘上层用铜柱垫高一方面散热一方面避免电机电刷火花产生的电磁干扰串到传感器线路上。铜柱高度建议10mm以上让底板下层走电机线、上层走信号线物理隔离。4.2 传感器布局决定搜救覆盖率不是随便粘上去的布局是整个装配里最有讲究的部分我总结三条经验超声波装在车头正中央的舵机云台上传感器面朝正前方高度保持在25-30厘米。这个高度对应的探测范围正好覆盖桌面、椅腿、墙体等室内常见障碍太低容易漏掉高处的障碍太高测不到地面的小台阶。红外避障传感器装在前轮轴线前方、左右各一个探头稍微斜向下。斜向下的原因超声波对小而低的物体比如地毯边缘、门槛不敏感而红外的反射式探测恰恰擅长这个两者互补。火焰传感器或热释电模块装在车头最前方、靠近地面因为火源和人体热辐射在地面附近信号最强。注意热释电模块有感应延迟特性装好后需要静止20-30秒让传感器稳定否则刚上电它自己会乱触发。走线方面所有线束沿着车架边缘用扎带固定绝不能让线在轮子附近晃。我第一版就因为一根杜邦线被轮子卷进去直接让电机堵转驱动板发热到烫手。线束固定完之后用手转动每个轮子检查一遍确保没有摩擦。4.3 共地与信号线处理电机的脏电是元凶接线上最核心的原则是分开供电、统一共地。我理一下电机电源7.4V电池正极接L298N的12V输入负极接L298N的GND。Arduino电源电池正极经一个5V降压模块接到UNO的Vin或5V引脚。我用的是5V引脚直连因为降压模块输出已经是稳定5V。舵机电源电池正极经另一个5V降压模块接到舵机红线舵机棕线接公共地。所有模块的地线L298N的GND、Arduino的GND、舵机地、传感器地全部并到同一个公共地节点。地线为什么要共地因为Arduino判断传感器信号要靠电压差如果两边地电位不一致读数就乱跳。电机PWM时产生的尖峰噪声如果没有共同地形成低阻抗回流路径会通过地线窜进信号线导致超声波测距出现幽灵障碍。另外电机线最好用绞线或者粗一点的红黑线并且跟信号线保持距离。我实测过电机线贴着杜邦信号线走的时候超声波测距的最大抖动从±2cm飙升到±15cm这就是电磁耦合。后来我把电机线改成双绞线间距拉开问题立刻缓解。5. 实测调参全记录从原地打转到稳定巡检的血泪史5.1 第一轮测试车根本跑不直问题出在电机上所有硬件装完的那天晚上我把小车放到地板上满怀期待地按下电源。结果小车以肉眼可见的弧度向右偏走了两米就撞上了椅子腿。我一开始以为是转向逻辑的问题后来用一块胶带在地上画了条直线发现小车即使在无障碍的直道上也跑不直。原因很简单两个TT电机的转速一致性差左边比右边快。这是直流有刷电机的通病不是故障。解决办法有两个层次硬件上我试着在慢的电机轴上加一个轻质垫圈增加摩擦治标不治本软件上才是正解——在forward()函数里对左右电机给定不对称PWM比如左140、右150用一个校正系数motorCalibration统一管理通过实测不断调整直到小车在2米内偏移小于10cm。同时也发现开机瞬间电压跌落严重。后来查了下7.4V锂电池在电机启动瞬间压降很大Arduino的5V供电模块也会跟着波动。我在代码里加了一个软启动for (pwm 0; pwm target; pwm)让电机在200毫秒内逐步提速既保护电池也避免起步被拽一下。5.2 第二轮测试避障忽远忽近机器人像是喝醉了直线问题解决后我让小车开始自主巡检。结果超声波测距显示前方障碍时远时近小车经常在离墙还有半米的时候就紧急转向有时又几乎贴上墙才反应过来。排查过程我分了三步第一步检查传感器本身。把超声波模块拆下来对着墙面固定测距串口输出还是波动。确认问题在读数环节而不在机械。我加了前面提到的均值滤波之后静态波动从±3cm降到±1cm好多了但动态场景还是不稳。第二步怀疑供电。舵机扫描时超声波和舵机共用一路5V舵机一转电流大超声波模块的VCC立刻被拉低导致测距异常。解决办法就是前面说的给舵机单独供电再在超声波VCC和GND之间加一个100uF电解电容做储能缓冲。这一步做完超声波读数彻底稳定了。第三步是动态跟手问题。超声波从发出到接收本身有延迟小车速度太快的时候看到障碍到执行转向之间车已经往前冲了好几厘米。我把正常巡检速度从PWM 180降到140避障响应立刻从容了。这里记住一个原则搜索车的首要指标不是速度而是稳定和覆盖。跑太快再好的传感器也救不回来。5.3 第三轮测试误报频出三重确认成了救命稻草搜救功能联调的时候我把一个点燃的蜡烛放在房间角落模拟目标小车第一次跑过去确认、报警、蓝牙发消息一气呵成。我正高兴第二天白天再测小车走到窗边突然报发现目标——现场的阳光干扰了火焰传感器。这是火焰传感器最典型的误报场景红外光谱里阳光成分复杂传感器无法区分。这时候三重确认机制的威力就体现出来了阳光干扰通常持续时间短、位置不稳定小车进入DETECT状态后原地停车扫描信号一丢就回到SEARCH不再触发REPORT。我又加了一招在火焰传感器的模拟输出引脚AOUT上做阈值判断把采样得到的模拟值动态中值滤波并把检测阈值设成明显高于环境基线才认为触发相当于给传感器加了个自适应门槛。热释电模块版本也有它的讲究它在人静止的时候反而可能不触发因为热释电只响应变化的红外辐射。所以如果用它搜人小车必须是移动状态而且确认阶段最好让小车小幅前后移动来制造相对运动。这个细节很多教程不会写实际测试中非常关键。5.4 一次完整的现场实测记录最后放一段我调试稳定后的完整实测流程供你对照自己的测试预期上电OLED显示IDLE小车原地360度慢速转一圈超声波扫描环境LED为绿色。2秒后进入SEARCH小车以20cm/s左右的速度沿右侧墙面巡检每2秒用舵机扫描一次前方扇形区域OLED实时刷新当前距离。遇到第一处障碍一个纸箱前方距离小于35cm进入AVOID小车停下、右转、向前试探绕过后回到沿墙。走了大概3米火焰传感器触发进入DETECT小车停车蜂鸣器短响一声提示有信号。云台左右扫描一圈信号连续稳定进入CONFIRMLED变红蓝牙模块发送TARGET_FOUND_AT_STATE3。5秒后自动回到SEARCH继续巡检直到手机端发出停止指令。整个流程从启动到首次发现目标用时约40秒期间误报零次。小车在一次完整巡检里的有效覆盖率我用网格法大概估算是75%左右剩下的盲区主要是墙角回旋处——这个问题留给下一版用螺旋搜索算法解决。6. 如果继续往下做这几条路最值得走6.1 从蓝牙回传到远程图传目前的回传只有文字和状态信息看不到现场画面。升级方向很明确把蓝牙换成ESP32-CAM或者用Arduino加一个串口摄像头模块把实时图像通过WiFi传回手机。这样小车就真正具备现场勘查能力了。代价是功耗上去了供电方案要重新设计建议用带更大容量电芯的电池组。6.2 给小车装上记忆极简区域记录现在的小车跑过的地方不会留下任何记忆容易重复搜索同一片区域。可以用UNO的EEPROM记录大致的时间戳和转向历史或者外挂一个SD卡模块把每次转向的传感器数据写到文本文件里。数据量不大但对后续分析路径覆盖、优化搜索策略非常有用。更进一步是接一个数字罗盘模块如HMC5883L让小车知道自己的朝向配合陀螺仪做闭环转向转弯角度会精确很多。6.3 机械结构上的两个实用升级一是把轮子换成履带模块越障能力明显提升能让小车从室内平地巡检升级到模拟废墟翻越。二是在车顶加一个小型云台摄像头加补光灯在光线不足的搜救场景里非常实用——搜救场景十有八九是暗的这也是实际项目里最容易被忽略的需求。我个人的建议是先别急着追新硬件把现有这套状态机逻辑、避障策略、确认机制吃透再根据自己的实际场景改传感器。机器人的价值从来不在某一个零件多贵而在整套系统能不能稳定地闭环跑起来。你能把一台基于Arduino UNO的小车调教到放下去就能自己搜后面换任何平台都是水到渠成的事。最后分享一个小技巧调试搜救小车时别只在光线下充足的房间里测。找个傍晚拉上窗帘开一盏台灯模拟低照度环境你会发现很多白天发现不了的问题——传感器盲区、红外干扰、LED指示亮度不够看不清全都现出原形。把它当成一次实战演习比在完美条件下跑一百遍都有用。