:红外双目跟随模块原理与调试)
引言智能小车要实现的功能很多——避障、跟随、贴边、灭火、直线行驶每一个模块单独调试起来都有自己的难点。如果一开始就把所有模块塞进一个工程里联调出了问题很难分清到底是传感器硬件的问题、电平极性的问题还是上层控制算法的问题所以这一系列教程的思路是先把每个功能模块单独拎出来配一个不依赖其他硬件的最小测试程序把模块本身调通调透再回头看它在完整项目里是怎么被使用的目录一、引言二、红外对射传感器硬件原理2.1 红外发射光电接收2.2 原理图讲解三、硬件接线说明3.1 红外跟随模块引脚定义3.2 接线方案表3.3 连接示意图四、独立测试程序五、调试流程演示5.1 测试流程5.2 演示视频六、项目跟随功能实现6.1 IRSensor底层感知层6.2 FollowBehavior跟随状态机6.3 系统流程图七、常见问题解答FAQQ1传感器接好了跟随时小车原地转但不追目标是什么问题Q2红外传感器在阳光下失效怎么办一、引言在前两篇教程里我们把循迹传感器和超声波云台都调通了这一篇讲红外双目跟随——用两个固定在车头左右两侧的红外对射传感器让小车识别目标方向像影子一样跟在目标后面走相比超声波云台双目红外跟随的优势在响应速度极快毫秒级无需舵机扫描等待电路简单、成本极低只需读两个GPIO电平劣势是探测距离短2~30cm可调、无法测量具体距离、对高反射率目标白色物体更灵敏。正是因为这个特性在本项目里这两个模块同时承担了两个角色跟随模式G命令用于追踪目标避障模式B命令的辅助IR用于检测45°斜前方近距离障碍这篇教程会把传感器原理、模块电路、跟随算法设计、调试过程和遇到的坑都完整梳理一遍包括项目里这个模块走弯路的调试历程这个系列教程拆成以下几篇篇次内容第一篇已完成五路循迹模块TCRT5000 LM393/LM339第二篇已完成HC-SR04 超声波测距 SG90 舵机云台三模式应用第三篇本文红外双目跟随模块红外避障对管第四篇霍尔编码器测速与直线行驶 PID含 PID 自整定第五篇DHT11 温湿度、火焰传感器、风扇灭火模块第六篇蓝牙/串口双通道通信协议设计终篇整车项目架构总览把前面六篇串起来讲整体设计思路二、红外对射传感器硬件原理红外双目跟随模块使用的是主动式红外避障传感器每个传感器内部集成了一个红外发射管发射红外光和一个红外接收管接收反射回来的红外光2.1 红外发射光电接收红外跟随模块红外发射器与光电三极管集成在一起适用于近接检测和反射传感红外发射管是由红外发光二极管组成发光体用红外辐射效率高的材料常用砷化镓制成 PN 结正向偏压向 PN 结注入电流激发红外光红外接收管则是将红外线光信号变成电信号的半导体器件其核心部件是一个特殊材料的 PN 结随着红外光强度的增加电流也随之增大①核心检测原理① 发射管持续发出 940nm 红外脉冲光 → ② 目标物体反射红外光反射率与目标材质、颜色相关 → ③ 接收管检测反射光强度 → LM393 比较器将模拟信号转为数字电平输出不同表面对红外光的反射特性表面特性红外反射接收管状态输出电平浅色/光滑表面强反射导通LOW检测到物体深色/粗糙表面弱反射/吸收截止HIGH未检测到黑色物体几乎吸收截止HIGH未检测到②输出电平与检测状态当探测到障碍物在检测范围内时模块会输出低电平LOW。该模块检测距离为 2~30cm检测角度 35°距离可通过电位器调节注意不同厂家、不同批次的模块输出电平与检测状态的对应关系可能相反。本项目实测确认检测到物体 → 输出 LOW0无物体 → 输出 HIGH1③LM393 比较器LM393 是一款双差分比较器 IC内部包含两个独立的运算放大器比较器。比较器对两路输入电压进行比较判断哪路更大然后给出输出比较电压工作原理当同相输入端 电压高于反相输入端-电压时比较器输出高电平。当同相输入端电压低于反相输入端-电压时比较器输出低电平比较器内部电路解析晶体管Q1、Q2绿色构成同相输入端的输入级。反相输入端的输入级由晶体管Q3、Q4黄色组成。晶体管Q5、Q6灰色用作电流镜。晶体管Q7、Q8红色为开关级各级晶体管均由恒流源供电、一旦同相输入端的输入电压高于反相输入端-的电压比较器输出端的晶体管Q8就会截止若通过电阻RL为输出端提供5伏电压即可引出高电平脉冲、同相输入端电压等于或低于反相输入端电压输出端晶体管导通比较器输出端向电源负电位侧切换此时可引出低电平脉冲电压变化发生在反相输入端还是同相输入端对开关功能没有影响。唯一关键的因素是两个输入端之间的电压差值。各类开关示例中将不同的电压变化情况蓝色箭头分开展示1同相输入端电压上升同相输入端电压升高会使输出端电压随之升高2同相输入端的电压降低同相输入端产生电压降会使输出端出现电压降3反相输入端电压上升反相输入端电压升高会使输出端电压降低4反相输入端的电压降低同相输入端产生电压压降时输出端也会出现电压压降④电位器调节模块上那颗蓝色方形可调3362电位器本质上是可调分压器——旋转旋钮改变分压比例从而改变送入 LM393 比较器的参考电压阈值调节效果调节方向参考电压变化检测距离变化顺时针旋转阈值降低检测距离增大更灵敏逆时针旋转阈值升高检测距离减小更不灵敏实际调试方法将模块正对目标物体如手掌距离约 10~15cm慢慢旋转电位器观察模块上的状态指示灯找到指示灯刚好点亮或熄灭的临界点再往灵敏方向回调一点点两个模块需要分别调节因为每个模块的电位器是独立的灵敏度和检测距离不会自动一致2.2 原理图讲解①单路 红外跟随电路典型的 IR333 PT333 LM393 红外避障模块单路原理图元件作用100Ω限流电阻R3限制 IR333发射管电流通常 100Ω ~ 200Ω10KΩ上拉电阻R5LM393 集电极开路输出需要上拉到 VCC通常 10kΩ10kΩ电位器R2调节比较器参考阈值电压通常 10kΩ 3362型②探测逻辑两个红外传感器在车头两侧呈八字形安装左传感器检测到目标意味着目标在左侧小车应该左转对准右传感器检测到目标意味着目标在右侧小车应该右转对准左传感器右传感器判断结果执行动作检测到LOW未检测HIGH目标在左侧左转未检测HIGH检测到LOW目标在右侧右转检测到LOW检测到LOW目标在正前方停车目标已近未检测HIGH未检测HIGH目标丢失原地旋转搜索如果方向反了小车会朝着远离目标的方向转永远跟不住三、硬件接线说明3.1 红外跟随模块引脚定义本项目跟随模块的引脚定义与pinsdefine.h一致传感器位置引脚号代码定义左侧IR模块21ServoPWM3右侧IR模块24ServoPWM4注意这两个引脚虽然命名为ServoPWM3/4但在本项目中被复用为红外传感器的信号输入引脚3.2 接线方案表每个红外跟随模块有 3个引脚模块引脚零知派迷你板引脚说明左红外传感器VCC5V电源正极左红外传感器GNDGND电源地左红外传感器OUTD21ServoPWM3信号输出右红外传感器VCC5V电源正极右红外传感器GNDGND电源地右红外传感器OUTD24ServoPWM4信号输出3.3 连接示意图左侧传感器直插小车扩展板——舵机接口 PWM3和右侧传感器直插小车扩展板——舵机接口 PWM4接反后代码里lIR和rIR含义会颠倒导致目标在右侧时车向左转。如果跟随方向错误第一步先用独立测试程序确认左右传感器方向是否正确再排查代码四、独立测试程序下面这个程序只依赖两个红外传感器不需要电机、超声波等其他模块在接入整车工程之前先用这个程序独立验证传感器的方向和灵敏度/************************************************************************************** * 文件: IR_Follow_Standalone_Test.ino * 作者零知实验室深圳市在芯间科技有限公司 * 功能红外双目跟随模块 独立测试程序 * 引脚定义与主项目 pinsdefine.h 完全一致 * * 使用方法 * 1. 烧录本程序到零知派迷你板 * 2. 打开串口监视器波特率115200 * 3. 用手或物体在左右传感器前方移动 * 4. 观察串口输出的检测状态变化 * 5. 通过电位器调节每个传感器的检测距离 **************************************************************************************/ #define IR_LEFT_PIN 21 // ServoPWM3 #define IR_RIGHT_PIN 24 // ServoPWM4 void setup() { Serial.begin(115200); delay(200); pinMode(IR_LEFT_PIN, INPUT_PULLUP); pinMode(IR_RIGHT_PIN, INPUT_PULLUP); Serial.println(F()); Serial.println(F( 红外双目跟随模块 独立测试程序)); Serial.println(F()); Serial.println(F(L1 表示左传感器检测到物体)); Serial.println(F(R1 表示右传感器检测到物体)); Serial.println(F()); Serial.println(F(状态说明)); Serial.println(F( L0 R0 → 目标丢失)); Serial.println(F( L1 R0 → 目标在左侧 → 左转)); Serial.println(F( L0 R1 → 目标在右侧 → 右转)); Serial.println(F( L1 R1 → 目标在正前方 → 停车)); Serial.println(F()); } void loop() { int leftVal digitalRead(IR_LEFT_PIN); int rightVal digitalRead(IR_RIGHT_PIN); // 传感器检测到物体输出 LOW取反后 1 表示检测到 bool leftDetected (leftVal LOW); bool rightDetected (rightVal LOW); Serial.print(F(L)); Serial.print(leftDetected ? 1 : 0); Serial.print(F( R)); Serial.print(rightDetected ? 1 : 0); // 状态判断 if (leftDetected rightDetected) { Serial.println(F( → 停车目标居中且已近)); } else if (leftDetected !rightDetected) { Serial.println(F( → 左转目标偏左)); } else if (!leftDetected rightDetected) { Serial.println(F( → 右转目标偏右)); } else { Serial.println(F( → 搜索目标丢失)); } delay(100); }五、调试流程演示5.1 测试流程①灵敏度测试上电传感器前无遮挡、串口显示 L0 R0 → 搜索目标丢失、如有误检测调节电位器降低灵敏度②遮挡测试用手掌挡住左传感器串口显示 L1 R0 → 左转目标偏左、用手掌挡住右传感器串口显示 L0 R1 → 右转目标偏右、用手掌同时挡住两个传感器串口显示 L1 R1 → 停车目标居中且已近③跟随模式测试发送命令G手掌从左侧移到右侧状态从左转、停车到右转状态依次变化确认状态切换平滑5.2 演示视频零知派迷你板智能小车-红外双目跟随模块调试展示独立测试程序在串口监视器上的实时输出用手在不同位置遮挡两个传感器对应串口输出的状态变化演示灵敏度调节——用螺丝刀旋转电位器观察触发距离的变化展示整车跟随效果六、项目跟随功能实现确认模块本身没问题之后再看完整项目里跟随功能是怎么组织的。这部分代码分布在两个文件里文件职责sc_perception.h/.cppIRSensor::read()——底层读取两个 GPIO 电平转换为布尔值sc_behaviors.h/.cppFollowBehavior::update()——上层跟随状态机6.1 IRSensor底层感知层// sc_perception.cpp IRSensor::IRSensor() { // INPUT_PULLUP无物体时保持HIGH避免悬空导致误触发 pinMode(ServoPWM3, INPUT_PULLUP); pinMode(ServoPWM4, INPUT_PULLUP); } void IRSensor::read(bool *isLeft, bool *isRight) { // 检测到物体 → LOW → isLeft/isRight true // 无物体 → HIGH → false *isLeft (digitalRead(ServoPWM3) LOW); *isRight (digitalRead(ServoPWM4) LOW); }6.2 FollowBehavior跟随状态机最终版本状态机FOLLOW跟随状态lIR rIR → stop()双触发正对且近停止lIR !rIR → 左转对准-FOLLOW_TURN, FOLLOW_TURN!lIR rIR → 右转对准FOLLOW_TURN, -FOLLOW_TURN连续 5 帧无触发_lostFrames LOST_THRESH切换回 SEARCH_CWvoid FollowBehavior::update() { bool lIR false, rIR false; g_ir.read(lIR, rIR); // 调试输出正式发布可屏蔽 Serial.print(F([FOLLOW] L)); Serial.print(lIR); Serial.print(F( R)); Serial.println(rIR); // ── 有目标进入跟随 ───────────────────────────────────────── if (lIR || rIR) { _lostFrames 0; if (_st ! FOLLOW) { _st FOLLOW; Serial.println(F([FOLLOW] 发现目标进入跟随)); BTSerial.println(F([FOLLOW] Target found)); } if (lIR rIR) { // 双触发目标正对且已非常近停止 g_motor.stop(); } else if (lIR !rIR) { // 左侧触发目标在左侧 → 左转对准 g_motor.motorRun(-FOLLOW_TURN, FOLLOW_TURN); } else { // 右侧触发目标在右侧 → 右转对准 g_motor.motorRun(FOLLOW_TURN, -FOLLOW_TURN); } return; } // ── 无目标消抖后进入搜索 ─────────────────────────────────── if (_st FOLLOW) { _lostFrames; if (_lostFrames LOST_THRESH) { g_motor.stop(); // 消抖期间保持停止 return; } _st SEARCH_CW; _ts millis(); _phase 0; _lostFrames 0; g_motor.stop(); Serial.println(F([FOLLOW] 目标丢失开始搜索)); BTSerial.println(F([FOLLOW] Lost, searching)); return; } // ── 搜索阶段 ───────────────────────────────────────────────── unsigned long elapsed millis() - _ts; switch (_phase) { case 0: g_motor.motorRun(SEARCH_SPEED, -SEARCH_SPEED); if (elapsed SPIN_MS) { g_motor.stop(); _phase 1; _ts millis(); } break; case 1: if (elapsed PAUSE_MS) { _phase 2; _ts millis(); } break; case 2: g_motor.motorRun(-SEARCH_SPEED, SEARCH_SPEED); if (elapsed SPIN_MS * 2) { g_motor.stop(); _phase 3; _ts millis(); } break; case 3: if (elapsed PAUSE_MS) { _phase 0; _ts millis(); } break; default: _phase 0; _ts millis(); break; } }调试历程功能迭代内容卡死不动最初 onEnter() 进入搜索状态旋转IR引脚没有接线读到的是拉高的 HIGH跟随逻辑方向反了motorRun(-FOLLOW_TURN, FOLLOW_TURN) 实际上是转向弄反跟随效果不稳定抖动明显降低搜索和跟随转速加入丢失目标消抖连续5帧确认丢失才切换6.3 系统流程图①参数调优指南问题现象可能原因调整方案搜索时转速过快找到目标有明显顿挫SEARCH_SPEED太大降低到 50~65对准时过冲来回抖动FOLLOW_TURN太大降低到 45~55目标稍微晃动就进入搜索LOST_THRESH太小增加到 8~10丢失目标后反应太慢才开始搜索LOST_THRESH太大减小到 3~5双触发区间太窄小车总在左右摆两传感器间距太大缩小传感器间距传感器始终触发误触发灵敏度太高逆时针调电位器降低灵敏度②与避障模式B命令的功能共用说明同一对 IR 传感器在两种模式下复用逻辑完全不同对比项跟随模式G避障辅助B传感器安装推荐角度正前方偏内 ±15°斜前方 45°/135°触发含义目标在那一侧应转向靠近那一侧有障碍应转向远离转向决策转向触发侧左触发→左转转离触发侧左触发→右转速度控制慢速跟随双触发停车紧急规避直接全速转向这也是代码里两个模块功能共用同一套硬件的典型案例上层算法完全不同但底层IRSensor::read()接口是相同的体现了感知层与行为层分离的设计价值七、常见问题解答FAQQ1传感器接好了跟随时小车原地转但不追目标是什么问题A首先用独立测试程序检查把手放在左侧传感器前串口显示的是L1还是R1。如果显示R1说明左右信号线接反了换线即可。如果双侧都是0检查供电和电位器Q2红外传感器在阳光下失效怎么办A该模块对环境光有一定的适应性但在强阳光直射的情况下阳光中的红外分量会干扰接收管导致误触发。解决方法逆时针调小电位器降低灵敏度同时给传感器加装遮光外壳可用黑色热缩管套住模块两侧资料整合LM393 数据手册TI lm393.pdfLM393 应用电路 差分比较器应用电路红外跟随和红外避障虽然用了同样的硬件但控制逻辑完全不同。避障只需要二值判断有/没有障碍而跟随需要正确理解“目标在左还是在右”并执行对应的转向动作——方向一旦搞反整个功能就完全失效了