扫地机器人红外回充方案:发射与接收硬件实战详解
2026/9/17 17:30:04 网站建设 项目流程

1. 项目整体思路拆解

做扫地机回充方案,很多人一上来就想着怎么搞视觉、搞激光雷达,但对绝大多数DIY项目来说,红外回充才是性价比最高、最容易落地的一条路。这套方案的核心逻辑很简单:扫地机在低电量时,通过红外接收管捕捉充电座发出的红外信号,靠信号强度或者接收角度来判断充电座在哪个方向,然后调整机身姿态,最终对准充电极片完成充电。

我在这个系列里要做的,就是把整套红外回充方案拆开揉碎,从红外发射、接收、信号解码、对准算法到最终的充电动作,一个一个讲清楚。本篇是第一篇,核心聚焦在红外信号的发射与接收这两个物理层环节,同时也是整套方案的基石。如果这两块没做好,后面谈什么算法、对准都是空中楼阁。

为什么选红外而不是其他方式?三个原因。第一,红外收发器件成本极低,一个发射管加一个一体化接收头,加起来不超过两块钱,比超声波模块、视觉模块便宜一个数量级。第二,红外方案技术成熟,消费级扫地机器人从十几年前就开始用这套方案,大量现成的经验可以借鉴。第三,红外抗干扰能力在室内环境下足够用,只要做好调制和解调,日光、白炽灯这些常见干扰源都能规避掉。

但红外的短板也很明显:方向性强、传播距离有限、容易受遮挡。所以整个方案的设计关键,就是怎么在有限的红外信号条件下,把有效距离拉长、把接收角度算准、把误码率降下来。本篇的内容安排,就是围绕这三个目标展开的。

2. 硬件选型与电路设计

2.1 发射端:红外LED的关键参数

红外发射管的核心参数有三个:发射波长、辐射强度、发射角度。波长方面,市面上最常见的红外LED峰值波长是940nm,这与一体化接收头的峰值响应波长正好匹配。买的时候不要只看是不是红外LED,一定要确认波长在920nm到960nm之间,偏差太大直接影响接收灵敏度。

辐射强度用mW/sr表示,这个值越大,同样的驱动电流下发射距离越远。常用的5mm直插式红外LED,在20mA驱动下辐射强度一般在10到30mW/sr之间。如果做充电座这种固定端设备,我建议选大功率的,比如辐射强度50mW/sr以上的型号,配合适当的驱动电流,发射距离可以轻松做到8米以上,给扫地机留出足够的回充距离裕量。

发射角度同样关键。角度越大,光束越分散,覆盖范围越广;角度越小,光束越集中,有效距离越远。充电座发射端我建议选30度到60度之间的型号。角度太小了,扫地机只有在很正的角度才能收到信号,实用性差;角度太大了,距离稍微远一点信号强度就不够,同样不好用。

2.2 接收端:一体化接收头的选型逻辑

接收端我不建议用光敏二极管加运放自己做放大电路,调试起来费时费力,性能还不一定好。直接买一体化红外接收头,也就是经常听到的IRM3638、1838T这类器件,性价比极高,几毛钱一个。

这里要展开讲一下一体化接收头的工作原理。这种器件内部集成了光敏二极管、自动增益控制电路、带通滤波器、解调器和输出级,外部只需要接电源、地和输出三个引脚就能工作。它会对接收到的红外信号做带通滤波,只让38kHz附近的载波信号通过,然后解调出基带信号,最后在输出引脚上恢复出高电平或低电平的数字信号。

选型的时候有几个坑要注意。第一,接收头的载波频率必须和发射端一致,绝大多数接收头是38kHz,也有36kHz、40kHz的型号,买之前看清楚规格书。第二,接收头有脉冲驱动和连续驱动两种工作模式,脉冲驱动模式灵敏度更高,但要求信号是有间隔的脉冲串,正好符合NEC协议的特点。第三,不同厂家的接收头,虽然引脚定义相同,但内部电路参数有差异,我建议选定一个型号后就不要乱换,否则可能影响接收距离和误码率。

2.3 电路连接速查表

模块引脚连接到说明
红外LED发射端正极三极管集电极通过三极管开关驱动,不要直接接MCU引脚
红外LED发射端负极GND(经限流电阻)限流电阻根据驱动电流计算
一体化接收头VCC3.3V或5V按规格书要求供电
一体化接收头GNDGND共地必须可靠
一体化接收头OUTMCU外部中断引脚推荐支持上升沿/下降沿中断的引脚
接收头电源去耦电容VCC到GND100nF电容紧靠接收头放置,非常重要

这个表是从我实际验证过的电路里整理出来的。特别强调一下接收头电源引脚旁边那个100nF去耦电容,很多DIY玩家会漏掉。一体化接收头内部有自动增益控制电路,工作时电流变化比较大,如果电源纹波过大,会导致接收灵敏度下降甚至误触发。加了去耦电容后,实测接收距离能提升20%左右,这个改善非常明显。

3. 红外编码协议设计

3.1 为什么要用38kHz载波调制

直接给红外LED通断电发信号行不行?理论上行,但实际上在室内环境根本没法用。因为阳光、白炽灯、节能灯这些光源都会产生红外辐射,如果直接把基带信号送到发射管,接收端无法区分哪些是有用信号、哪些是环境光干扰。

解决这个问题的标准做法是载波调制:把要发送的数据信号,调制到38kHz的载波上。一体化接收头内部有带通滤波器,只让38kHz附近的信号通过,其他频率一概滤除。这样环境光产生的宽带红外辐射就会被滤掉,接收端能看到的就只有我们发出去的调制信号了。

38kHz这个频率不是随便定的。早期红外遥控协议发展的时候,行业里做了大量测试,最终选定了这个频率区间。它避开了大多数环境光源的干扰频率,同时接收头的陶瓷谐振器在这个频率下可以做得小巧且稳定。现在市面上绝大多数一体化接收头都针对38kHz做了优化,所以我们设计发射端时,直接把载波频率定为38kHz就对了。

3.2 NEC协议的帧格式解析

发射端和接收端之间传递的是什么?本质上是一串脉冲宽度不同的高低电平。为了让双方能正确理解这串电平的含义,需要约定一套编码规则。我选用的是消费电子领域最成熟的红外遥控协议——NEC协议。

NEC协议的数据帧包含以下几个部分:引导码、地址码、地址反码、命令码、命令反码。引导码由9ms的高电平和4.5ms的低电平组成,用来告诉接收端“一帧数据开始了”。地址码8位,用来区分不同的设备类型;地址反码是地址码的按位取反,用来做校验。命令码8位,是真正要传输的控制指令,命令反码同样用于校验。

这里要说一下NEC协议的位编码方式。逻辑“1”用560us的高电平加1690us的低电平表示;逻辑“0”用560us的高电平加560us的低电平表示。接收端的解码程序就是靠测量高电平持续时间和低电平持续时间的比例来区分0和1的,时序精度要求不算苛刻,但也不能偏差太大。

对于回充场景,我建议不要照搬标准NEC的地址码和命令码定义。标准NEC用16位的地址码来区分设备类型,但充电座和扫地机是成对工作的,不存在多设备共存的问题,反而更需要的是用数据内容来表达“当前红外信号来自哪个方向、充电座在左边还是右边”这类信息。

所以我的做法是:保留NEC的引导码和位编码规则,但把数据段重新定义。用1个字节表示信号来源方向,比如0x01表示充电座中央、0x02表示充电座左侧区域、0x03表示充电座右侧区域;再用1个字节做校验,简单的做法是取反校验,更可靠的做法是用CRC8校验。

3.3 为什么选择NEC协议而不是其他协议

当前主流的红外协议除了NEC,还有SONY的SIRC协议、飞利浦的RC-5协议等。我逐一对比过,最终选择NEC协议有以下几个原因。

首先是容错性。NEC协议每个数据位都有明确的高低电平比例,接收端解码时可以通过测量电平持续时间来判断逻辑值,即使信号在传输过程中有一定程度的畸变,只要高低电平比例没有严重失真,依然能正确解码。RC-5协议是曼彻斯特编码,对时序精度的要求更苛刻,不太适合扫地机这种运动状态下接收信号的应用场景。

其次是干扰容忍度。NEC协议的一帧数据以9ms的引导码开始,接收端解码时可以先用引导码做一次预判,确认确实是有效信号后再去解码后续的地址码和命令码。这相当于一个硬件层面之外的软件滤波,能显著降低误触发概率。

再次是资料丰富度。由于NEC协议在消费电子领域应用极其广泛,网上能找到海量的现成代码和调试经验,遇到问题的时候基本都能搜到解决方案。对DIY项目来说,这一点非常重要。

4. 发射端实现详解

4.1 38kHz载波信号的产生方式

产生38kHz载波,有几种常见方案,各有优劣。

第一种是硬件PWM方式。很多单片机的定时器都支持PWM输出模式,把定时器的频率配到38kHz,占空比设为1/3,就能从引脚直接输出38kHz的载波信号。这个方案的优点是几乎不占用CPU资源,缺点是引脚选择受限,必须是支持PWM输出的引脚。

第二种是IO翻转方式。在定时器中断里翻转IO引脚电平,通过精确控制中断频率来产生38kHz信号。这个方案的优点是任意引脚都能用,缺点是要占用CPU资源,而且定时器中断频率越高,CPU负担越重。如果单片机主频不够高,还可能产生时序抖动。

第三种是使用专用的红外编码芯片,比如市场上常见的HT6221、NB9148这类芯片。它们内置了振荡器和编码电路,只需要外部接一个455kHz晶振和按键矩阵,就能自动产生完整的NEC协议波形。优点是纯硬件方案,不占用单片机资源,可靠性高;缺点是灵活性差,编码格式固定,不方便自定义数据内容。

在这里我推荐第一种方案:硬件PWM产生载波,然后用一个IO引脚控制发送数据。为什么不用专用编码芯片?因为回充场景下,充电座发射的信号需要根据扫地机的位置动态变化,数据内容是实时决定的,专用芯片无法满足这个需求。为什么不用IO翻转方案?因为在发射载波期间还要同时处理数据时序,IO翻转太依赖中断,容易出现时序竞争,代码写起来也很别扭。

具体到STM32平台,可以这么配置:用定时器的PWM输出模式,预分频器设置为CPU主频/38000再减去1,自动重装载值设为一个合适的数让输出频率稳定在38kHz。我实际用的配置是系统时钟72MHz,定时器预分频为72MHz/38000再减1,得到大约76MHz/38kHz的预分频比,自动重装载值设为1,输出比较值设为0,这样能输出精确的38kHz PWM波形,占空比大约1/3。

4.2 发射驱动的完整代码

下面给出我实际在STM32F103上验证过的发射代码。这段代码的作用是:把要发射的数据字节转换成NEC协议格式的电平序列,通过38kHz载波调制后输出到红外发射管。

先看头文件里的相关定义:

#define IR_TX_PORT GPIOA #define IR_TX_PIN GPIO_PIN_0 // 默认用PA0作为发射控制引脚 #define IR_PWM_TIM TIM2 // 默认用TIM2产生38kHz载波 // 载波开启和关闭的宏 #define IR_CARRIER_ON() HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1) #define IR_CARRIER_OFF() HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1) // NEC协议时序参数 #define NEC_LEAD_HIGH_US 9000 #define NEC_LEAD_LOW_US 4500 #define NEC_BIT1_HIGH_US 560 #define NEC_BIT1_LOW_US 1690 #define NEC_BIT0_HIGH_US 560 #define NEC_BIT0_LOW_US 560 #define NEC_END_US 560

然后是发送一帧数据的核心函数。发送过程是逐位进行的,逻辑1或逻辑0对应的“高电平+低电平”组合通过delay_us函数产生时序:

void IR_SendByteWithCarrier(uint8_t data) { uint8_t i; // 发送引导码:9ms载波 + 4.5ms低电平 IR_CARRIER_ON(); delay_us(NEC_LEAD_HIGH_US); IR_CARRIER_OFF(); delay_us(NEC_LEAD_LOW_US); // 逐位发送数据,从高位开始 for (i = 0; i < 8; i++) { if (data & 0x80) { // 逻辑1:560us载波 + 1690us低电平 IR_CARRIER_ON(); delay_us(NEC_BIT1_HIGH_US); IR_CARRIER_OFF(); delay_us(NEC_BIT1_LOW_US); } else { // 逻辑0:560us载波 + 560us低电平 IR_CARRIER_ON(); delay_us(NEC_BIT0_HIGH_US); IR_CARRIER_OFF(); delay_us(NEC_BIT0_LOW_US); } data <<= 1; } // 发送结束位:560us载波 IR_CARRIER_ON(); delay_us(NEC_END_US); IR_CARRIER_OFF(); }

delay_us函数要尽量精确,尤其是在发送逻辑1的时候,1690us的低电平时间如果偏差太大会导致接收端解码失败。在STM32上我用的是DWT(Data Watchpoint and Trigger)模块来实现微秒级延时,比简单的循环计数可靠得多。

4.3 发射端几个容易被忽略的细节

发射端代码看起来很简单,但实际做的时候有几个细节很容易翻车。

第一,载波的开启和关闭动作要“干净利落”。在发送引导码的高电平时间段,载波要连续发射,不能有中断进去干扰。如果用的单片机还要处理其他中断,发送红外信号期间最好临时屏蔽掉高频率的中断,否则载波波形中间只要出现一个毛刺,接收端的解调就可能出错。

第二,发射管的驱动电流要经过计算,不能盲目选大。红外LED的正向电压一般在1.2V到1.5V之间,驱动电流由限流电阻决定。假设供电电压为5V,三极管饱和压降约为0.2V,LED正向压降取1.4V,那么限流电阻为:

R = (5V - 0.2V - 1.4V) / 20mA = 170欧姆

实际可以取标准的180欧姆电阻。如果想加大发射距离,可以把电流提高到50mA甚至100mA,但这时候限流电阻要相应减小,同时确认所选LED的最大额定电流。不要超过LED的极限参数,否则LED光衰会加快,用几个月后发射距离明显缩短。

第三,在充电座这种固定设备上,建议用多个发射管并联广角覆盖。我实测过单管发射的有效角度大概在正负30度左右,超过这个角度扫地机就收不到信号了。用两个发射管分别成一定角度安装,可以显著扩大覆盖范围。如果需要多管同时发射,每个管子都要独立串联限流电阻,不能共用一个电阻,否则电流分配不均会导致某个管子偏亮,另一个偏暗。

5. 接收端实现详解

5.1 接收端数据处理流程

接收端的工作流程可以概括为四个步骤:捕获边沿、测量脉宽、解码字节、校验数据。一体化接收头的输出引脚平时是高电平,当收到38kHz载波信号时,输出引脚会变成低电平。这个特性决定了我们解码时要关注的是下降沿和上升沿之间的时间差。

完整的接收解码流程是这样的。第一步,初始化外部中断,把接收头输出引脚配置为下降沿和上升沿都触发中断,同时开启一个定时器用于测量脉宽。第二步,在中断服务函数里记录当前定时器的计数值,计算出上一次边沿到本次边沿的时间间隔。第三步,根据这个时间间隔判断当前收到的信号类型。第四步,解码完整帧后做校验,通过则交给上层逻辑处理。

这里要特别注意一个时序细节:一体化接收头的输出是低电平有效,而且解调过程中内部电路有延迟,实际输出的高低电平时序和发送端相比会有偏移。这个偏移量大约在几十微秒到一百多微秒之间,解码时不能对脉宽精度要求太苛刻。比如发送端逻辑1的低电平是1690us,接收端测到的可能是1600us到1800us之间,这都算正常范围。

5.2 解码程序的实现

下面的代码展示了接收端的核心解码逻辑。我用一个状态机来处理接收过程,这样可以避免在主循环里轮询导致的漏数据问题。

typedef enum { RX_IDLE, // 空闲状态,等待引导码 RX_LEAD_HIGH, // 已收到引导码高电平 RX_LEAD_LOW, // 已收到引导码低电平 RX_DATA, // 正在接收数据位 RX_FRAME_DONE // 一帧接收完成 } RX_StateTypeDef; volatile uint8_t rx_state = RX_IDLE; volatile uint32_t rx_last_time = 0; volatile uint8_t rx_byte_index = 0; volatile uint8_t rx_byte_data = 0; volatile uint8_t rx_buffer[4]; volatile uint8_t rx_frame_ready = 0;

在中断服务函数中,核心的脉宽判断逻辑如下。需要说明的是,我用了TIM2来做微秒计时器,把计数器频率配置成1MHz,这样计数器每计数一次就是1us,读到的差值直接就是微秒数。

void EXTI9_5_IRQHandler(void) { uint32_t now_time; uint32_t interval; if (EXTI_GetITStatus(EXTI_Line5) != RESET) { now_time = TIM2->CNT; interval = now_time - rx_last_time; rx_last_time = now_time; // 判断当前引脚电平,低电平表示载波开始(下降沿),高电平表示载波结束(上升沿) if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5) == RESET) { // 下降沿:载波刚开始 switch (rx_state) { case RX_IDLE: // 如果这段低电平脉宽接近9ms,说明是引导码的高电平部分 if (interval > 8000 && interval < 10000) { rx_state = RX_LEAD_HIGH; rx_byte_index = 0; rx_byte_data = 0; } break; case RX_DATA: // 这是前一个数据位的低电平结束后再次收到载波 // 根据上一次记录的高低电平比例来解码 break; default: break; } } else { // 上升沿:载波刚结束 switch (rx_state) { case RX_LEAD_HIGH: // 引导码的高电平结束,接下来应该是4.5ms的低电平 if (interval > 8000 && interval < 10000) { rx_state = RX_LEAD_LOW; } else { rx_state = RX_IDLE; } break; case RX_LEAD_LOW: // 4.5ms低电平结束,开始接收数据位 if (interval > 4000 && interval < 5000) { rx_state = RX_DATA; } else { rx_state = RX_IDLE; } break; case RX_DATA: // 数据位的载波结束,根据低电平持续时间判断0或1 if (interval > 1200 && interval < 2100) { // 逻辑1 rx_byte_data = (rx_byte_data << 1) | 0x01; } else if (interval > 300 && interval < 800) { // 逻辑0 rx_byte_data = (rx_byte_data << 1) | 0x00; } else { rx_state = RX_IDLE; break; } rx_byte_index++; if (rx_byte_index >= 8) { rx_buffer[rx_byte_index / 8 - 1] = rx_byte_data; if (rx_byte_index >= 32) { rx_state = RX_FRAME_DONE; rx_frame_ready = 1; } } break; default: break; } } EXTI_ClearITPendingBit(EXTI_Line5); } }

这段代码我故意保留了部分状态转移的省略,因为完整的代码比较长,这里展示的是核心的时序判断逻辑。实际使用时,还需要处理接收过程中出现异常时序时,状态机要能自动复位回到IDLE状态。我在每个分支里都加了else回退,就是为了保证任何一步出错都不会卡死。

5.3 判断充电座的方位

这是回充方案区别于普通红外遥控的关键点。普通遥控器只需要知道“收没收到信号”,而回充方案需要知道“信号来自哪个方向”。

我采用的方案是发射端三区域编码。充电座上有三个红外发射区域:左侧、中央、右侧。三个区域发射的数据内容不同,比如左侧发射0x02,中央发射0x01,右侧发射0x03。扫地机上安装两个或三个红外接收头,分别朝向不同的方向。当扫地机收到某个方向传过来的特定编码时,就能判断充电座在它的哪个方位。

接收端通过解码数据帧里的方向字节来决策:

接收到的方向码含义扫地机执行动作
0x01充电座中央区域说明正对充电座,保持直行
0x02充电座左侧区域说明偏左了,需要向右转调整
0x03充电座右侧区域说明偏右了,需要向左转调整
0x00或校验失败无效信号原地旋转扫描,重新寻找信号

这个方案的优点是逻辑简单可靠,不依赖精确的信号强度测量。接收头的输出是数字信号,解码后直接就能得到方位信息,不需要做ADC采样和阈值判断。缺点是需要充电座上有多个发射管,会增加一点硬件成本,但在DIY场景下完全可接受。

5.4 接收端硬件布局的实战经验

接收头在扫地机上的安装位置,直接决定了整个回充方案的可靠性。我踩过不少坑,这里分享几条经过实测的经验。

第一,接收头尽量安装在扫地机的前侧面上,离地高度要和充电座发射管的高度基本对齐。如果高度差距太大,扫地机开近了反而收不到信号,出现“近距离失联”的诡异现象。充电座发射管离地高度一般在5到8厘米,扫地机接收头安装时参考这个范围。

第二,同一个扫地机上最好安装两个接收头,一个朝正前方,一个略朝上或者略偏左/偏右。因为扫地机接近充电座的时候,并不总是正对着充电座,可能是以某个角度斜着靠近的。单接收头在这种情况下很容易丢失信号,双接收头交叉覆盖能大幅提高对准成功率。

第三,接收头不能紧贴着金属外壳或者电机安装。一体化接收头内部有高增益放大电路,对电磁干扰很敏感。电机转动时的电磁噪声可能导致接收头误触发,表现为扫地机明明没有靠近充电座,却不断解码出随机数据。解决方法是接收头周围保持一定距离的“净空区”,或者用导电布包裹接收头的侧面做电磁屏蔽。

6. 红外信号实测数据与调试心得

6.1 实测有效距离与角度

在正式集成到扫地机器人之前,我先做了大量的离台测试。这里把实测数据整理出来,供大家做方案设计时参考。

测试条件是:发射端使用5mm红外LED,波长940nm,辐射强度约26mW/sr,驱动电流20mA;接收头使用一体化38kHz接收头,型号1838T。发射端和接收端都离地8厘米,两端高度对齐。室内正常照明环境下测试。

水平距离正对角度偏转30度偏转60度备注
1米正常解码正常解码正常解码近距离三种角度都可稳定接收
3米正常解码正常解码间歇解码60度偏转时信号衰减明显
5米正常解码间歇解码无法解码系统设计建议最大距离4米以内
7米间歇解码无法解码无法解码超过有效工作范围

从这个表可以得到两个关键结论。第一,有效工作距离和角度是相互制约的,角度越大,有效距离越短。设计回充策略时,远距离阶段主要靠正对接收来引导扫地机大致朝充电座方向前进,近距离阶段才开始依靠角度信息做精细对准。第二,如果扫地机需要从较远处开始回充,建议在靠近充电座5米左右的区域设置一个“信号搜索区”,扫地机先原地旋转找到信号方向,再朝那个方向直线前进。

6.2 干扰源排查方法与红光可视化调试

实测过程中遇到最多的问题是“为什么接收端偶尔会解出错误数据”。排查干扰源的方法是,让发射端停止发送,单独观察接收端有没有信号输出。如果有,说明环境中有38kHz附近的红外干扰。

常见的干扰源有三个:第一是电视、空调等家电的红外遥控信号,虽然协议不同,但载波频率可能相同,会被一体化接收头接收并放大;第二是某些节能灯和LED灯的驱动电路,会产生38kHz附近的红外频闪;第三是手机摄像头附近的红外距离传感器,虽然功率不大,但在近距离也可能造成干扰。

缓解措施有两个方向。软件层面,通过在数据帧里加校验码,能过滤掉大部分随机干扰。硬件层面,在接收头前面加装红外滤光片,也就是深红色的亚克力片,只让红外波段透过,能有效减少可见光带来的干扰。

另外分享一个调试技巧:把发射端的调制信号改成长亮模式,用手机摄像头对准发射管,能看到红外LED发出淡紫色的光。这个方法可以用来快速验证发射电路是否工作正常。手机摄像头对红外光的敏感度比人眼高很多,但注意不是所有手机的摄像头都能看到红外光,部分手机镜头有红外截止滤光片,看不到也是正常的。

6.3 接收性能的软件调优

接收端的性能不仅取决于硬件,软件参数同样影响巨大。这里给出几个我实测后验证有效的调优方向。

首先是接收头输出信号的处理。一体化接收头在没收到载波时输出高电平,收到载波时输出低电平。但由于内部自动增益控制电路的原因,在信号微弱或快速闪断时,输出波形可能出现“毛刺”,也就是不该翻转的时候翻转。处理方式是在MCU里加入简单的去毛刺逻辑,也就是连续采样几次,如果电平状态一致才认为电平真的翻转了。这个逻辑可以放在外部中断里做,也可以用定时器轮询来做。

其次是脉宽判断的容差范围。NEC协议标准时序是9ms、4.5ms、560us、1690us这些值,但实际接收时,由于接收头内部电路的延迟和发射端元件参数的偏差,脉宽会有5%到15%的漂移。判断逻辑的容差范围我记得在代码部分已经给出了,这里再强调一次:引导码高电平判断区间是8000到10000us,逻辑1的低电平判断区间是1200到2100us,逻辑0的低电平判断区间是300到800us。这个范围在多次实测中表现良好。

再次是连续接收的设计。扫地机在运动中接收信号,一个严重的问题是信号会频繁中断和恢复。如果每次中断都把状态机复位到IDLE,那么扫到半帧数据就丢了,解码成功率会非常低。我的做法是:在接收完一帧有效数据后,不立即复位状态机,而是保留状态,等待下一帧的引导码到来时再重新开始。这样即使中途丢了几位数据,只要下一帧引导码完整,解码依然能继续。

7. 常见问题与排查技巧实录

7.1 接收距离短,不到1米就解不到信号

这是DIY玩家问得最多的问题,通常有以下几个原因。先说最容易被忽略的:红外LED的波长不对。市面上有些标称“红外发射管”的灯珠,峰值波长在850nm甚至更低,接收头的响应灵敏度在940nm是最高的,在850nm处会下降不少。用万用表量LED压降可以大致判断,940nm的红外LED正向压降通常在1.2V左右,850nm的通常在1.5V左右。

其次是发射驱动电流不够。如果直接把MCU引脚接到LED正极,MCU引脚的输出能力只有几毫安到二十毫安,发射功率完全不够。解决方案是加三极管开关驱动电路,让MCU控制三极管的导通和截止,由外部电源来提供发射管的驱动电流。

再就是接收头电源噪声问题。前面说过,接收头电源引脚需要加100nF去耦电容,但如果电源本身纹波很大,还是要另外加一个低ESR的电解电容。我用示波器看过,接收头工作的时候电源引脚上的纹波能到50mV以上,加了10uF电解电容加100nF陶瓷电容的组合之后,纹波降到了10mV以内,接收距离明显提升。

7.2 能收到信号,但解码出来的数据是乱的

这个问题多半出在时序上。发射端和接收端对脉宽的理解不一致,导致解码时把逻辑0判成逻辑1。

我遇到过的典型场景是:用STM32的HAL库延时函数做发射时序,HAL_Delay函数的精度是毫秒级,完全不能用在高精度的微秒级延时上。后来我用DWT模块实现了微秒延时,时序误差控制在几微秒以内,问题立刻解决。

另一个可能的原因是接收头输出信号的上升沿和下降沿有延迟。发射端发送的逻辑1组合是560us高加1690us低,但接收头内部解调需要时间,实际输出的低电平时间可能比1690us长或者短。如果解码程序判断区间太窄,就会把有效信号误判为无效。解决办法是放宽判断区间,但同时不要让有效区间之间出现重叠,否则无法区分逻辑0和逻辑1。

7.3 扫地机转动时信号不稳定

转动过程中信号方向变化快,会有信号丢失和恢复的循环。我建议在算法层面做“移动平均”或者“滞后判断”,也就是连续收到2到3帧同一个方向的数据,才认为方向确实变了,避免因单帧误判导致机器人左右摇摆。这个内容虽然属于上位算法,但设计接收程序时就应该预留出对应的接口,每帧收到有效数据时把方向码存入一个循环缓冲区,供上层算法读取。

7.4 问题排查速查表

现象可能原因排查方法
发射管不亮电路连接错误、三极管极性接反用万用表量LED两端压降,正常约1.2V
接收距离短LED波长不对、驱动电流小、接收头电源纹波大检查LED型号参数,量驱动电流,确认去耦电容
解码数据乱码发射端延时不准、接收端脉宽判断区间不合理用示波器对比发送和接收波形,调宽判断区间
信号时有时无发射角度不匹配、接收头朝向不对检查发射管角度参数,调整接收头安装角度
偶尔误触发环境红外干扰、接收头靠近电机电磁干扰软件加校验码,硬件加滤波片,接收头远离干扰源

8. 写在后面的几句实在话

这套红外收发射频方案,单看每一个模块都不复杂,但真正把它们组合成一个能稳定工作的完整系统,需要花不少心思。我自己第一版做出来的时候,发射端和接收端单独测试都很正常,一装到扫地机上就各种各样的问题,不是距离不够就是解码不稳定,前前后后调整了一个多星期才达到比较满意的效果。

印象最深的一个坑是接收头的安装位置。最开始我把接收头放在扫地机主板的角落,旁边正好是电机驱动芯片,结果扫地机一出动就不断收到乱码,排查了很久才发现是电机电流变化通过地线耦合到了接收头电路。后来把接收头移到远离电机的位置,问题就彻底消失了。这类问题在原理图上看不出来,只能在实机上慢慢试。

如果看完这篇文章打算自己做一套,我的建议是从简单的做起。先不用管充电座的方位判断,用一块开发板加一个接收头,把发射端发送一个固定编码、接收端正确解码这一条链路跑通,再逐步增加功能。等基础链路稳定了,再考虑多发射管方位编码、扫地机对准算法这些上层逻辑。一步一个脚印来,踩过的坑才会变成属于自己的经验。

下一篇会继续讲充电座和扫地机之间的对准策略,包括如何利用红外信号控制扫地机直行、旋转和微调,也会附上完整的工程源码。这一篇先把收发基础打好,下一篇的算法才能跑得起来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询