资讯详情

资讯详情

红外回充技术基础:红外发射与接收的硬件选型与代码实现

扫地机、擦窗机、割草机器人这类产品一旦加了“自动回充”功能用户体验立马就上了一个台阶。而实现自动回充的路径其实有好几条激光建图导航、视觉导航、红外信标引导再加上不同方案的组合各家方案各有取舍。我这个项目选的是红外回充方案原因很简单成本低、可靠性足够、实现周期短而且在不依赖高精度地图的情况下也能做到厘米级的对接精度。这篇文章是这个系列的第一篇先把最基础也最容易被忽视的部分讲透——红外信号的接收和发射。后面几篇会接着聊信号解码、左右接收头的差分对准、回充座的控制逻辑以及整套系统在工程上怎么落地。这篇涉及的是整套方案的地基地基不打牢后面谈什么对准精度都是空话。先交代下背景。我用的主控是一颗Cortex-M0内核的单片机成本控制在几块钱要跑的代码包括红外解码、电机PID、碰撞检测和回充状态机。红外回充部分需要的硬件只有红外发射管、红外接收头、几个电阻电容再加上一颗40kHz左右的载波振荡也可以由MCU直接产生整套硬件成本不超过两三块钱。这对成本敏感的产品来说是很有吸引力的方案。代码方面这篇文章会在接收和发射两部分各给出一段可以直接用的源码并在关键位置解释为什么这么做以及哪些地方容易踩坑。无论你是第一次接触红外通信还是已经写过调制解调但想系统梳理一遍这篇文章都能给你一个相对完整的参考。1. 红外回充的整体设计与方案选型做红外回充之前我先把几种主流方案摆在桌面上对比了一轮因为方案选型直接决定后续硬件架构和软件复杂度。1.1 为什么选红外而不是激光或视觉回充这个动作本质上要解决两个问题一是从远处找到充电座的方向二是到了近处之后让充电极片和充电座电极精确对接。激光方案靠SLAM地图直接导航到充电座附近精度高但对主控算力和传感器成本的要求高入门级产品根本扛不住。视觉方案需要处理图像成本和功耗又是一个坎。红外的思路最朴素——充电座在固定位置持续发射红外光机器人身上带着红外接收管靠接收到的信号强度和左右差值来判断该往哪转、该走多远。红外方案的好处有三个第一器件成本足够低发射管加接收头整套不到两块钱比激光雷达便宜一两个数量级第二接收头的视角可以做得很宽机器人随便转个方向都能感应到信号不需要太精确的初始方位第三红外是光信号不像Wi-Fi或蓝牙那样容易被金属壳体屏蔽也不涉及复杂的配对流程上电就能用。当然红外也有明显的短板容易受环境光干扰信号传播距离有限一般几米以内而且充电座和机器人之间不能有遮挡。但这些短板在室内环境下基本可以接受所以很多中低端扫地机至今还在用红外回充。1.2 回充信号链路的整体拆解红外回充的完整链路可以分为三段来看发射端充电座内部的MCU或专用振荡电路驱动红外发射管发出经过38kHz载波调制的红外光。这里的“调制”是核心直接发恒定红外光在几米外根本区分不开环境光而调制之后接收端可以通过带通滤波器把38kHz分量单独提出来。传播链路红外光在空气中直线传播遇到障碍物会反射。为了让方向性更强发射管通常配合透镜或聚光罩使用把光束收窄到一定角度机器人走近后接收到的信号强度才会出现明显的梯度变化。接收端机器人身上的红外接收头把光信号转成电信号经过内部解调之后输出数字电平MCU测量这个电平的脉宽解析出充电座发射的编码数据同时根据左右两路接收强度的差值计算偏转角度。我在设计时把接收头固定在机身底盘左右两侧充电座则用两个发射管一个朝左前方扫一个朝右前方扫通过不同的编码区分左右。机器人收到“左发射管编码”多就说明自己偏右了需要往左修收到“右发射管编码”多就说明偏左了需要往右修。这个逻辑听起来简单但真正做稳定需要解决很多细节后面会展开。2. 硬件细节红外发射与接收的核心设计硬件是整个方案的骨架。这个项目里我先后调过三轮硬件前两轮都在器件选型上吃过亏后面会提到。先把最核心的电路和参数讲清楚。2.1 红外发射电路与关键器件选型红外发射管的核心参数是峰值波长、辐射强度和半功率角。常用的是940nm波长的发射管因为硅基光电探测器在这个波段的响应最灵敏。辐射强度用mW/sr表示直接决定信号能传多远。半功率角则决定光束的扩散范围角度越小方向性越好但覆盖范围小角度越大覆盖范围大但单位面积上的光强衰减更快。回充充电座一般希望光束覆盖机身左右偏转的整个范围同时尽量往前延伸所以我选了半功率角大约±30度、辐射强度在50mW/sr以上的发射管。配合一个简单的抛物面反光杯在1米处仍然能产生足够的信号强度给接收头。发射驱动电路上我用的方案是MCU引脚输出38kHz方波通过三极管放大后驱动发射管。电路非常简单但有几个参数值得仔细算。限流电阻的选择以3.3V供电、发射管压降1.3V、设计峰值电流100mA为例R (VCC - V_LED) / I_F (3.3 - 1.3) / 0.1 20Ω实际我取了22Ω的标称电阻峰值电流约90mA留了一点余量。这里要注意红外发射管允许的峰值电流远大于平均电流因为38kHz方波的占空比是50%平均电流只有峰值的一半。选管的时候要看数据手册里的“正向电流峰值”参数而不是只看平均电流。三极管我选的是2N3904这种通用小信号管放大倍数足够大饱和压降也小驱动100mA级别的电流没有问题。但有一点容易踩坑38kHz对应的周期约26.3微秒三极管的开关速度必须跟得上像2N3904的开关时间在几百纳秒级别完全够用但如果随手拿了颗功率三极管或者达林顿管开关时间可能到微秒级输出波形就会变形红外信号会平白无故衰减一截。2.2 红外接收电路与选型接收端有两种典型方案我分别说下。第一种是直接用一体化红外接收头比如TSOP38238、HS0038B这类。接收头内部集成了光敏二极管、AGC放大器、带通滤波器和解调器输入是红外光输出是解调后的数字电平。带通滤波器锁在38kHz附近天然就把环境光里的直流分量和其他频段的干扰滤掉了。对大多数项目来说这是首选电路就是接收头输出脚直接连MCU加一个上拉电阻和去耦电容就可以了。供电脚对地并联一个10μF电解电容和0.1μF瓷片电容这能显著抑制电源纹波对接收距离的干扰。第二种是用光敏二极管加分立解调电路。这种方案的好处是可以自定义载波频率和带宽在特殊应用场合比如强环境光干扰下能做更强的抗干扰处理但调试复杂度高得多而且元件一致性容易出问题。除非量产数量很大需要极致降成本否则没必要走这条路。我在这个项目里用的是TSOP38238。它有几条关键参数值得记住载波频率38.0kHz带宽约±2kHz输出逻辑收到38kHz调制信号时输出低电平没有信号时输出高电平最小突发长度至少6个载波周期约600μsIR头才能识别为有效信号供电范围2.5V~5.5V静态电流约0.4mA第3条“最小突发长度”在实际编码里非常关键。因为这个参数意味着发射端发出的脉冲宽度必须大于600微秒否则接收头直接忽略。举个例子有些协议里用500微秒的短脉冲表示数据0用1600微秒的长脉冲表示数据1这个500微秒就短于接收头的最小突发长度实际使用起来距离会剧烈下降甚至完全收到不到。所以自定义协议时最短脉冲宽度不能小于700微秒我留了余量用的是800微秒。2.3 常用红外接收头对比项目选型时候我列了一张对比表这里贴出来供参考。型号载波频率供电电压输出电平优势注意点TSOP3823838kHz2.5~5.5V低有效抗干扰好静态电流小最小突发长度600μsHS0038B38kHz2.7~5.5V低有效兼容性好容易买到封装偏大响应稍慢VS1838B38kHz2.7~5.5V低有效便宜几毛钱一只一致性一般静电敏感光敏二极管分立解调自定义按电路自定义可定制性强调试复杂元件多我自己最后是在TSOP38238和VS1838B之间纠结了一下。前者的性能一致性更好近远距离接收都有稳定表现后者便宜到可以忽略成本但批次之间灵敏度差异比较大如果产品要过一致性测试建议还是优先选TSOP38238这类有长期供货保障的型号。3. 发射端软件实现如何产生可靠的38kHz红外信号硬件只能保证“能发”发得好不好要靠软件。发射端的核心任务有两个一是稳定产生38kHz的载波二是按照协议把数据位“填”到载波上。3.1 调制原理与定时器PWM实现红外发射的实质是载波信号38kHz方波叠加在数据信号上。数据为“1”的时段里发射管以38kHz频率快速亮灭数据为“0”的时段里发射管保持熄灭。接收头收到载波后内部解调输出低电平没有载波时输出高电平。用MCU实现38kHz方波有几种办法纯延时翻转GPIO、定时器中断翻转GPIO、硬件PWM输出。我强烈建议用硬件PWM原因有两点延时会占用CPU而回充状态下MCU还要同时处理电机控制、光电编码盘测速和碰撞传感器根本没时间在循环里干等。定时器中断翻转适合没有PWM外设的MCU但中断频率是76kHz对系统调度有压力而且抖动会影响信号质量。我的主控是STM32F0系列Cortex-M0核心定时器资源还算丰富。用TIM1的通道1产生PWM配置如下/* 38kHz PWM 初始化 */ void IR_TX_Init(void) { GPIO_InitTypeDef gpio; TIM_TimeBaseInitTypeDef tim_base; TIM_OCInitTypeDef tim_oc; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_2); // PA8 - TIM1_CH1 gpio.GPIO_Pin GPIO_Pin_8; gpio.GPIO_Mode GPIO_Mode_AF; gpio.GPIO_Speed GPIO_Speed_10MHz; gpio.GPIO_OType GPIO_OType_PP; gpio.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, gpio); // 时钟48MHz分频48 - 计数频率1MHzARR26 - 载波频率约38.46kHz tim_base.TIM_Prescaler 48 - 1; tim_base.TIM_CounterMode TIM_CounterMode_Up; tim_base.TIM_Period 26 - 1; tim_base.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseInit(TIM1, tim_base); tim_oc.TIM_OCMode TIM_OCMode_PWM1; tim_oc.TIM_Pulse 13; // 50% 占空比 tim_oc.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC1Init(TIM1, tim_oc); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_CtrlPWMOutputs(TIM1, ENABLE); TIM_Cmd(TIM1, DISABLE); // 先关闭需要时再开 }这里分频后计数频率是1MHz也就是说定时器每1微秒加一。自动重装载值设为26产生的方波频率是1MHz / 26 ≈ 38.46kHz正好落在接收头的带宽范围内。为什么不是精确的38.000kHz因为接收头带通滤波器的带宽通常有±2kHz的容差38.46kHz完全在有效范围内反而比纠结那个0.4kHz的偏差划算——毕竟用整数分频更容易算出准确脉宽。3.2 自定义协议的帧格式设计很多入门教程直接拿NEC协议来用但我测试下来发现NEC的最小脉冲是562.5微秒此时接收头的AGC已经有点吃力最远接收距离比长脉冲格式要缩水一些。我干脆自己定义了一套适合回充场景的帧格式最短脉冲宽度800微秒数据率相比NEC有所降低但每帧也就几十个bit完全够用距离却稳了很多。帧格式如下引导码: 9ms 载波 4.5ms 熄灭 数据位0: 1.0ms 载波 1.0ms 熄灭 数据位1: 1.6ms 载波 0.8ms 熄灭 结束码: 1.0ms 载波 4.0ms 熄灭可选用“载波时间”和“熄灭时间”的组合来区分0和1。接收端测量这两个时间就能正确解码而且1.0ms以上的载波脉宽让接收头的AGC放大器有充足的时间稳定输出实际测试比NEC格式远至少30%。代价是单个bit时间变长但一帧数据引导码8位地址8位数据8位校验总共也就30多毫秒回充发射端每50毫秒发一帧完全够用。发射代码里我封装了一个简单的发送函数#define BIT_0_CARRIER_US 1000 #define BIT_0_IDLE_US 1000 #define BIT_1_CARRIER_US 1600 #define BIT_1_IDLE_US 800 #define LEAD_CARRIER_US 9000 #define LEAD_IDLE_US 4500 void IR_SendByte(uint8_t data, uint32_t carrier, uint32_t idle) { // 发送一个bit: carrier时间内开PWMidle时间内关PWM TIM_Cmd(TIM1, ENABLE); delay_us(carrier); TIM_Cmd(TIM1, DISABLE); delay_us(idle); } void IR_SendFrame(uint8_t addr, uint8_t data) { // 引导码 IR_SendByte(0x00, LEAD_CARRIER_US, LEAD_IDLE_US); // 地址和数据 uint8_t payload addr; for (int i 0; i 8; i) { if (payload 0x80) { IR_SendByte(0x00, BIT_1_CARRIER_US, BIT_1_IDLE_US); } else { IR_SendByte(0x00, BIT_0_CARRIER_US, BIT_0_IDLE_US); } payload 1; } payload data; for (int i 0; i 8; i) { if (payload 0x80) { IR_SendByte(0x00, BIT_1_CARRIER_US, BIT_1_IDLE_US); } else { IR_SendByte(0x00, BIT_0_CARRIER_US, BIT_0_IDLE_US); } payload 1; } // 结束码 TIM_Cmd(TIM1, ENABLE); delay_us(1000); TIM_Cmd(TIM1, DISABLE); delay_us(4000); }这个发送函数看起来很简单但确实能跑。真正的工程优化在后面加了DMA和定时器级联但那是降低CPU占用的优化手段基础版本先保证功能正确。我在项目里用的是基于定时器硬件PWM加GPIO使能的方案发送一帧大约30毫秒期间CPU会阻塞但因为回充发射端就只管发信号30毫秒的阻塞影响不大。如果机器人身上的接收端也承担了避障功能那就需要改成DMA方式后面有机会单独讲。4. 接收端软件实现从脉冲到数据帧的解码接收端比发射端复杂一个档次因为发射端是自己产生的信号所有时序都是确定的接收端面对的是经过空气衰减、环境光干扰、器件个体差异之后的模拟世界。解码的可靠性决定了整套回充方案能不能稳定工作。4.1 解码原理与脉宽测量TSOP38238的输出逻辑是收到38kHz载波时输出低电平没有载波时输出高电平。所以MCU收到的数据流是一串高低电平交替的方波其中高电平时间等于发射端“熄灭”的时间低电平时间等于发射端“载波”的时间可能比发射的载波时间略长AGC有滞后。解码要做的事情就是测量每个高电平和低电平的持续时间然后根据时间长度判断是哪一种bit。测量脉宽常用的方案有两种外部中断加定时器计数GPIO边沿触发中断在中断里读取定时器的计数值算出相邻边沿的间隔。输入捕获模式定时器空闲时自动捕获边沿时间戳不需要CPU频繁中断。从工程稳健性角度看输入捕获更优尤其当MCU还要处理其他任务时。我在项目里用的是TIM2的通道1和通道2分别接左右两个红外接收头的输出引脚配置成输入捕获模式每个上升沿自动把定时器的值存到寄存器里然后产生一次中断CPU只负责读结果不用精确定位边沿。解码状态机的基本流程是等待一个低电平持续时间超过8ms引导码的特征确认引导码结束随后的高电平持续约4.5ms依次采集8位地址和8位数据每一bit都记录低电平时间high_time和下一段高电平时间low_time对时间和做判决载波1.0ms左右的是bit 0载波1.6ms左右的是bit 14.2 接收解码代码附源码下面给出接收端的核心状态机代码。这段代码在我在几个项目里反复用过裁剪后可以直接移植到自己的工程里。typedef enum { RX_STATE_IDLE, RX_STATE_LEAD, RX_STATE_DATA, RX_STATE_DONE } IR_RxState; #define RX_LEAD_HIGH_US 9000 #define RX_LEAD_LOW_US 4500 #define RX_BIT0_HIGH_US 1000 #define RX_BIT0_LOW_US 1000 #define RX_BIT1_HIGH_US 1600 #define RX_BIT1_LOW_US 800 #define RX_TOLERANCE_US 400 // 容差±400us uint8_t g_rx_byte[2]; IR_RxState g_rx_state RX_STATE_IDLE; uint8_t g_rx_bit_count 0; uint8_t g_rx_current_byte 0; uint32_t g_rx_last_time 0; /* 在GPIO边沿中断里调用参数level是当前电平time是定时器计数值 */ void IR_RxEdge(uint8_t level, uint32_t time) { uint32_t duration time - g_rx_last_time; g_rx_last_time time; switch (g_rx_state) { case RX_STATE_IDLE: // 只有低电平载波且超过8ms才可能是引导码 if (!level duration RX_LEAD_HIGH_US - RX_TOLERANCE_US) { g_rx_state RX_STATE_LEAD; g_rx_bit_count 0; g_rx_current_byte 0; } break; case RX_STATE_LEAD: if (level duration RX_LEAD_LOW_US - RX_TOLERANCE_US) { g_rx_state RX_STATE_DATA; } else { g_rx_state RX_STATE_IDLE; } break; case RX_STATE_DATA: if (!level duration RX_BIT0_HIGH_US) { // 载波时间超过1.0ms说明是bit1 g_rx_current_byte (g_rx_current_byte 1) | 1; } else { g_rx_current_byte (g_rx_current_byte 1) | 0; } g_rx_bit_count; if (g_rx_bit_count 8) { g_rx_byte[g_rx_byte_index] g_rx_current_byte; g_rx_current_byte 0; g_rx_bit_count 0; if (g_rx_byte_index 2) { g_rx_state RX_STATE_DONE; g_rx_byte_index 0; IR_RxCallback(g_rx_byte[0], g_rx_byte[1]); } } break; case RX_STATE_DONE: g_rx_state RX_STATE_IDLE; break; } }代码里有几个值得注意的细节。第一容差设置。我给引导码和数据bit都加了±400微秒的容差。为什么能容忍这么大的偏差因为发射端是MCU精确延时抖动本身很小但环境中存在反射、散射、接收头AGC的滞后等因素会让接收端测出来的脉宽和发射端不完全一致。测试数据显示近场强信号下偏差不到100微秒距离拉到3米以上、信号很弱时脉宽可能拉长到600微秒。400微秒是综合考虑误码率和抗干扰后的折中。第二状态机的超时处理。上面的代码没有写超时但实际工程里必须在状态机里加一个定时器看门狗——如果超过100毫秒没收到完整帧强制回到IDLE状态。原因很简单红外信号不像串口有明确的帧结束标志一旦中途断掉状态机可能卡在DATA状态永远等下一个bit。第三左右双通道的处理。回充机器人的接收端至少有左右两个实际有些产品还会在顶部加第三个。多个接收头意味着MCU要同时监听多个输入可以在每个输入上都跑一遍同样的状态机做三份独立的变量。串口分析时你会看到左右两路各自输出解码结果而这个结果正是后面转向判断的数据来源。4.3 回充场景的信号强度判断思路解码数据只是第一步回充对准还需要知道“信号强不强”。接收头输出的是数字电平无法直接读出模拟强度但我们可以变通把同一帧内载波持续的时间统计出来载波时间越长说明信号越强。具体做法是接收端统计一帧内所有低电平时间的总和。如果信号很强AGC快速饱和解码出的脉宽接近发射端原始数据如果信号很弱AGC放大倍数拉满载波脉宽会变宽同时相邻bit之间的高电平时间缩短甚至有些bit的载波部分被拉长到难以区分。我实测下来用“低电平总时长”作为信号强度的粗粒度估计在2米范围内能区分出大概5档强度对机器人的转向判断足够用了。当然这不是真正意义上模拟量但红外回充本身追求的就不是精确测距而是“往信号强的一边转”这种模糊逻辑完全够用。如果想要更精细的信号强度可以把接收头换成光敏二极管加运放的方案直接读模拟电压不过复杂度会上升不少这个系列后面如果讲到高精度对接部分再详细展开。5. 联调常见问题与排查技巧这部分是我真正花时间最多的地方。代码写出来只是开始联调阶段遇到的问题一个比一个隐蔽如果没有一套系统的排查思路很容易陷入“代码没改问题忽好忽坏”的困境。5.1 我踩过的坑汇总这一小节列几个我实际遇到过、并且花费了大量时间定位的问题。第一个坑是电源纹波。最初版PCB上红外接收头和电机驱动共用一路5V电源电机一转接收距离直接从3米掉到0.5米。示波器一量发现电机启动瞬间的电压跌落和纹波干扰非常大接收头的VCC脚上叠加了接近200mV的噪声。解决办法是接收头供电单独走一路LC滤波5V经过一个10Ω电阻加一个220μF电容形成RC滤波效果立竿见影接收恢复到了稳定状态。后来我再设计PCB红外接收头附近必定留一个10μF和0.1μF并联的去耦电容位置尽量靠近VCC引脚。第二个坑是红外发射管电流不够载波距离太近。第一次测试我按1kΩ限流电阻给发射管供电实测电流才3mA红外信号距离只有30厘米。数据手册上写着“典型工作电流20mA”实际回充场景至少需要50到100mA的峰值电流才能保证3到5米的探测距离。很多人看到发射管规格书上写的20mA就以为只能用20mA实际上那是直流最大连续电流如果工作在低占空比脉冲调制下瞬时电流可以大很多。我的设计里用了22Ω限流峰值90mA占空比50%平均电流45mA低于规格书的最大连续电流但发射距离提升非常明显。第三个坑是接收头的AGC“抢信号”。当机器人和充电座距离非常近10厘米以内时红外信号过强接收头内部AGC会自降增益导致输出波形反而异常解码失败。我管这个叫“近场饱和”。处理办法不是去调硬件而是在回充逻辑里设置一个“近场盲区”当左右两路都显示信号强度极高但解码失败时停止前进改为原地小幅旋转直到解码恢复为止。这段逻辑在对接阶段非常实用否则机器人会反复“顶”充电座却对接不上。第四个坑是环境光干扰。正常室内灯光基本不会影响38kHz的接收头因为带通滤波器只放行38kHz附近的信号白炽灯和LED的频闪频率不在这个范围。但如果阳光直射接收头AGC可能被阳光中的红外分量压制导致灵敏度下降。规避手段有两个接收头加装遮光罩限制入射角度以及在充电座信号里增加固定的引导码校验——不是任何38kHz信号都能唤醒机器人的对接逻辑必须解析出合法的地址和数据。5.2 实用的排查工具与调试技巧调试红外信号和调试SPI、UART这类有线通信不一样最大的障碍是“看不见”。下面几个工具帮我省了大量时间。第一个工具是手机摄像头。现在大多数手机摄像头都能看到红外光——把发射管对准摄像头屏幕能明显看到紫色光点。这个办法可以用来快速判断发射管是否在工作、光束的大致角度和范围成本为零效率极高。第二个工具是逻辑分析仪一定要用支持采样率不低于1MHz的那种。把接收头的输出脚接到逻辑分析仪上可以直接看到高低电平的波形测量每个脉冲的宽度。这套方法比单纯用示波器方便因为逻辑分析仪能一口气采集几秒的数据方便回放分析。第三个工具就是一个简单的“信号强度指示”调试接口。在代码里加一段调试逻辑把左右接收头的信号强度通过串口或者调试用的状态灯输出。比如信号弱亮红灯信号适中亮黄灯信号强亮绿灯。我后来把这套逻辑做成了产品自检流程的一部分产线测试时不用额外设备就能判断回充模块是否正常。调试顺序上我的习惯是先发射后接收再联调。先确认发射管的38kHz输出是否正常手机摄像头能看到光再用逻辑分析仪确认接收头输出波形是否与预期一致最后才接上解码状态机去解整车数据。这一步一步排查下来比如最头疼的“发射端明明在发接收端却收不到”问题80%的可能是接受头的电源或者载波频率偏了。写在最后的实操体会这套红外收发方案我从原型验证到小批量试产前前后后改了四版PCB每次改版都能发现新问题。最大的体会是红外硬件看起来简单但真正决定成败的往往不是代码而是电源处理、光学遮挡、器件选型这些容易被忽略的细节。如果让我给刚上手的人一个建议我不会让你上来就去调算法而是先花一个晚上把发射端和接收端的最小系统跑通用手机摄像头确认发射管在亮用逻辑分析仪确认接收头在解码串口打印出每一帧的地址和数据。这步做扎实了后面不管是做双路差分对准还是做回充状态机你都有一双“眼睛”帮你看着信号。这篇文章是整个红外回充方案的第一篇重点在收发链路。下一篇我会写左右双通道的信号强度计算和差分转向控制那部分才是真正让机器人“走回家”的关键算法。到时候见。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →