ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于51单片机的红外避障与测速系统设计详解

基于51单片机的红外避障与测速系统设计详解 简介一套基于STC89C52单片机的红外避障车辆测速仪表设计方案面向51单片机初学者、嵌入式硬件开发者以及正在开展课程设计或毕业设计的学生帮助其完成从系统搭建到文档撰写的完整准备。方案采用两个红外避障传感器检测人体或车辆通过起点与终点默认按1m距离计算速度并在首个传感器触发时由蜂鸣器鸣叫提示LCD1602液晶负责速度显示整体电路包含单片机、传感器、显示、报警与电源五个主要模块。压缩包共110个文件约45.41MB主要由jpg电路截图与系统框图、doc/docx任务书和开题报告、pdf参考论文及芯片资料、c/h源码与hex烧录文件构成另含mp4多媒体和schdoc原理图等。已有310人学习下载。包内同时收录程序源码、电路图、任务书、答辩技巧、开题报告、系统框图、程序流程图、器件清单及使用到的芯片资料可辅助读者对照实物完成项目也可直接用于答辩汇报与报告整理便于后续在此基础上二次开发与功能扩展。1. 把红外避障和测速做进同一块51单片机先分清两个传感器的活儿车载测速仪表通常只关心轮速脉冲红外避障关心前方有没有障碍。两者都叫“红外”但测速用对射式避障用反射式原理和信号形态完全不同。同一块51单片机只有两个外部中断和两个定时器如果全用中断处理脉冲丢失和优先级冲突很快就会把方案推翻。我一般把测速脉冲接外部中断0用定时器0做200ms闸门计数避障输出接普通IO口用定时器1做5ms扫描加软件消抖。这样测速的实时性不受避障查询影响避障也无需占用稀缺的外部中断资源。这个设计适合做课程设计、工程训练也适合给真实低速车辆加装电子仪表。只要会C语言、看过51单片机最小系统原理图就能按下面的公式和代码复现。2. 测速传感器选型对射式红外计数和霍尔方案的取舍以及脉冲频率怎么算速度2.1 为什么测速用对射式红外而不是反射式红外测速仪表的核心是获得一个与车轮转速严格成正比的脉冲序列。反射式红外传感器虽然也能测旋转但距离和角度稍微变化反射率就大幅波动输出脉冲占空比不稳定容易产生抖动。对射式红外由发射管和接收管分居两侧当车轮上的挡片或码盘经过中间空隙时阻断红外光接收管的电平发生跳变脉冲边沿非常干净可以直接接51单片机的外部中断脚。实际测试中把反射式避障模块对着车轮转轴测量时由于轮辐形状不规则输出波形会出现大量窄脉冲单片机外部中断很容易误触发。而对射式只要挡片宽度合适上升沿和下降沿的时间都能做到几十微秒以上符合51单片机外部中断的触发条件。霍尔传感器是另一个常用方案它输出方波不受油污影响但需要磁钢或测速齿轮安装成本高且磁钢高速旋转可能吸附铁屑。对射式红外没有磁性部件成本低适合教学和低成本车辆改装。这里选用对射式红外方案重点解决码盘设计和信号整形。2.2 脉冲频率与车速的换算公式车速不能用脉冲个数直接表示需要把脉冲频率乘以轮周长再除以每转脉冲数。设每转脉冲数为N轮子直径为D单位米则轮周长C πD。若脉冲频率为fHz则线速度vm/s f * C / N。换算成km/h乘以3.6v(km/h) f * π * D * 3.6 / N例如N4D0.6m速度 f * 3.14 * 0.6 * 3.6 / 4 f * 1.6956也就是1Hz脉冲约对应1.7km/h。需要特别注意的是D是指滚动半径对应的直径不是轮毂直径。轮胎受压后滚动半径会减小精确标定时最好让车在平整地面滚动10圈实测行驶距离除以10得到实际滚动周长。测量窗口的选择直接影响速度精度。如果取1秒计数高速时速度显示滞后明显所以常用200ms闸门。200ms内计数为k等效频率f k / 0.2 5k因此车速 k * 5 * 1.6956。代码里把1.6956乘以5得到8.478再取整数运算。下面表格给出不同参数的对照轮径0.6mN1Hz对应车速(km/h)200ms计数为1时车速(km/h)200ms计数为10时车速(km/h)23.3916.96169.641.708.4884.861.135.6556.5这里看到如果N2200ms内10个脉冲就对应169.6km/h已经超过一般车辆速度所以N取4时量程更合适。N越大低速分辨率越好但高速时中断频率越高。51单片机处理2kHz左右的脉冲中断没有问题也就是N4时车速对应约300km/h足够真实汽车使用。2.3 中断引脚、定时器初值和信号整形的最小硬件连接对射式红外接收管输出通常需要整形后才能接入P3.2。标准电路是接收管集电极输出接上拉电阻4.7k到5V发射极接地会有缓慢的上升沿。更好的做法是接LM393比较器或74HC14施密特触发器。我用LM393因为红外接收输出电平范围大比较器可以设定阈值抗干扰好。比较器输出端加10k上拉然后接P3.2。51单片机外部中断0支持下降沿触发设置IT01后每个脉冲下降沿进入一次中断。如果信号方向反了可以在程序里把IT0改为0从上升沿触发但标准芯片不支持选择沿极性就用外部反相器。STC部分增强型单片机支持上升沿或下降沿看具体型号数据手册。测速闸门定时器用T0方式116位定时器最大定时约71ms12MHz晶振所以一般做50ms中断软件累加4次得200ms。11.0592MHz晶振、12T模式下机器周期为12/11.0592M 1.085us。50ms定时需要计数50ms / 1.085us 46080次初值为65536 - 46080 19456即0x4C00。所以在定时器中断里重装初值TH00x4CTL00x00。注意如果使用STC的1T模式初值需要换成921600次减65536会超出16位必须采用自动重载或分频因此选12T模式是省事的关键。外部中断0的中断号是0定时器0中断号是1。中断优先级设置寄存器IP把PX0置1让外部中断独占最高优先级这样避障扫描在进行时测速脉冲仍然能优先得到响应。3. 红外避障模块的选型逻辑反射式模块、检测距离与抗干扰的3个可调参数3.1 反射式避障模块的输出形态和安装位置市面上常见的避障模块都是发射管加接收管加LM393比较器输出TTL电平。透明板上的电位器调节比较器阈值也就是调节有效检测距离。这种模块适合测距或避障但它的输出是“有障碍/无障碍”的开关量不是距离值。设计时把它当成一个开关因此主要处理好抖动和误报。安装位置直接决定检测性能。安装在车头正前方正对道路容易受到阳光干扰和地面反射。最佳方式是倾斜安装让红外光束与地面成30到45度夹角检测区域在车前方约10到50cm处。如果模块放在保险杠内红外发射管会被遮挡必须露出。外壳开孔要大于发射管直径并用黑色硅胶固定防止机械振动导致角度偏移。另外要确认模块输出是高电平表示有障碍还是低电平表示有障碍。我用的是低电平有效也就是有障碍时输出低电平。如果不确定可以用万用表在障碍物前后来回测量记录电平变化。这个逻辑直接写进代码里的obstacle_in 0条件。3.2 何时用查询、何时用中断避障检测不能挤掉测速脉冲很多初学者习惯把避障信号也接外部中断。但车辆在颠簸路面上障碍物造成的红外反射毛刺很多每次毛刺都触发中断避障服务函数还没跑完测速脉冲就已经丢了。所以避障信号不接外部中断接在普通IO口用定时器扫描加软件消抖。我使用定时器1做5ms中断在中断里读取P1.0连续两次为低才确认障碍。这个方案的关键是保证测速外部中断0的优先级最高。设置IP0x01把外部中断0设置为高优先级这样即使避障扫描正在执行测速脉冲也能打断它。51单片机的中断服务函数默认不嵌套如果你开了EA高优先级中断可以被低优先级中断嵌套因此低优先级中断的临界区要尽量短。避障扫描服务函数里不能做长延时只读引脚、置标志、清计数然后快速退出。避障扫描周期对响应延迟的影响如下表扫描周期(ms)消抖次数确认延迟(ms)72km/h下车移动距离(cm)52102010220402024080确认延迟等于扫描周期乘以消抖次数。高速时20cm延迟已经不小所以选择5ms扫描10ms确认。若想再快可以把消抖次数改为1代价是更容易误报。3.3 距离阈值、响应延迟与环境光补偿避障模块的电位器调节的是比较器参考电压。旋转电位器时指示灯会从常灭变为常亮。正确调节步骤接上5V电源将传感器对准空旷区域指示灯应熄灭。在目标检测距离处放一块白色纸板白色反射率高容易确认。缓慢旋转电位器直到指示灯刚亮为止此时检测距离约等于纸板距离。移开纸板确认指示灯熄灭如果还亮说明阈值太灵敏反方向旋一点。检测距离受物体颜色影响严重黑色吸光白色反射强。实测时可用下表参考目标表面白色纸板灰布黑色轮胎有效距离电位器调至30cm约30cm约18cm约8cm因此校准时的目标物材质最好与真实障碍物接近。车辆前方通常是保险杠或墙壁用白色纸板校准后再实测真实障碍物。若在阳光下测试红外接收管会收到大量阳光中的红外分量模块输出持续低电平造成误报。常规做法是给发射和接收管套上遮光罩只留前方开口同时让模块检测面朝下倾斜。软件上也可以设置障碍确认标志后如果连续5个扫描周期都没有再次读到障碍就先清除报警并重新检测避免一只飞虫闪过后被锁存。4. 代码实现51单片机测速中断与红外避障扫描的完整裸机流程4.1 测速脉冲计数与200ms闸门代码下面是用STC89C52为例的程序框架。先把全局变量定义放在文件头部#include reg52.h volatile unsigned int pulse_count 0; // 外部中断0累计的脉冲数 volatile unsigned int last_count 0; // 200ms闸门结束时的脉冲快照 volatile unsigned char timer0_50ms_cnt 0; // 50ms中断累积次数 unsigned int speed_kph 0; // 计算出的车速单位km/h外部中断0服务函数每来一个下降沿就加一void ext0_isr(void) interrupt 0 { pulse_count; // 一个挡片脉冲进入一次 }变量pulse_count是unsigned int最大65535。如果车速极快导致200ms内脉冲数超过65535计数器会回绕。但N4时要超过65535*5327kHz脉冲频率车速约55万km/h远远超出汽车范围所以不会溢出。为了严谨可以在主循环里限制当last_count超过一定值就提示传感器故障。定时器0中断每50ms执行一次累积4次得到200ms闸门void timer0_isr(void) interrupt 1 { TH0 0x4C; // 11.0592MHz, 12T, 50ms重装初值 TL0 0x00; timer0_50ms_cnt; if (timer0_50ms_cnt 4) { timer0_50ms_cnt 0; get_pulse_snapshot(); // 原子操作取快照 speed_kph calc_speed(last_count); } }取快照和清零必须在同一条临界区内完成。因为pulse_count同时被外部中断0修改如果期间来了新脉冲这个脉冲会被算进下次计数。由于外部中断0是高优先级它可以打断定时器0中断所以得临时关闭总中断void get_pulse_snapshot(void) { EA 0; // 关总中断保证原子性 last_count pulse_count; pulse_count 0; EA 1; // 开总中断 }速度计算公式用到定点数unsigned int calc_speed(unsigned int count) { unsigned long tmp; // 200ms内count个脉冲f count * 5 // 假设N4, D0.6m系数 1.6956 // 使用定点数count * 5 * 16956 / 10000 tmp (unsigned long)count * 5UL * 16956UL; return (unsigned int)(tmp / 10000UL); }这里的每个数值都加UL后缀防止中间变量按int运算溢出。count最大可能几千乘以5再乘16956大约几亿需要32位无符号数。如果车速显示3位数最后结果强制转回unsigned int没问题。若更换轮径计算公式中的16956要重新算。比如D0.5m时系数3.140.53.6/41.413就改成14130。4.2 红外避障扫描代码定时器1做5ms消抖使用定时器1方式1做5ms定时中断。11.0592MHz下5ms需要计数4608次初值65536 - 4608 60928即0xEE00。代码sbit obstacle_in P1^0; // 避障模块数字输出低电平有效 volatile unsigned char obstacle_flag 0; void timer1_isr(void) interrupt 3 { static unsigned char scan_cnt 0; TH1 0xEE; // 5ms重装值 TL1 0x00; if (obstacle_in 0) { scan_cnt; if (scan_cnt 2) { // 连续两次5ms扫描都是障碍确认 obstacle_flag 1; } } else { scan_cnt 0; obstacle_flag 0; } }这里连续两次意味着10ms确认。如果5ms扫描一次读取的是瞬时电平颠簸时的反射毛刺可能造成一次误判所以连续两次都低才置标志。因为定时器1中断的优先级默认低于外部中断0所以即使避障扫描被打断也不会影响测速。如果希望避障响应更快可以把scan_cnt判断改为1但更可能误报。4.3 主循环、LCD显示与报警驱动的完整流程主函数初始化void main(void) { init_timer0(); // 设置T0为方式1, 50ms init_timer1(); // 设置T1为方式1, 5ms init_ext0(); // 下降沿触发开中断 init_lcd1602(); // LCD初始化 EA 1; // 总中断开关 while (1) { if (obstacle_flag) { alarm_beep(); // 产生蜂鸣器脉冲 lcd_display_string(0, OBSTACLE! ); } else { alarm_off(); lcd_display_string(0, GO AHEAD ); } lcd_display_speed(speed_kph); delay_ms(5); // 简单延时防止LCD写入过快 } }lcd_display_string与lcd_display_speed的实现省略注意LCD1602写指令和写数据之间要判断忙碌标志否则屏幕可能出现乱码。速度显示用四位数例如“Speed: 008 km/h”。LCD主循环刷新频率可以到20Hz人眼看起来很连续。如果使用数码管则每次刷新需要动态扫描此时注意关闭显示位后更新段码避免拖影。5. 实测标定技巧用已知转速验证测速精度以及避障误报的排查顺序5.1 用手持电钻或直流电机模拟车轮转速进行标定没有整车测试台架时我常用可调速直流电机驱动车轮通过示波器或频率计读取P3.2上的脉冲频率。设定电机转速为120转/分钟即2转/秒每转4个脉冲则脉冲频率为8Hz。按系数1.6956理论车速约为13.6km/h。如果LCD显示偏差超过0.5km/h优先检查定时器初值是否正确以及晶振频率是否真的为11.0592MHz。STC单片机支持在程序里读取频率或使用内部RC振荡器内部RC振荡器精度约±1%测速仪表最好外接晶振。标定数据可以记录如下表格设定转速(转/分)理论车速(km/h)仪表显示(km/h)误差(km/h)606.870.212013.6140.424027.227-0.2如果误差呈现固定比例说明计算公式里的轮径D或每转脉冲N设置不准不是软件随机问题。实际车辆轮胎气压变化会改变滚动半径所以标定时要在正常胎压下进行。5.2 避障误报的排查顺序和抗干扰改造行驶中频繁误报先查供电再看安装最后才调电位器。发动机点火系统和火花塞会产生高频辐射红外模块的比较器如果布局不好容易把辐射检波成低电平。我按下面顺序排查序号检查对象方法1电源纹波示波器看5V输出报警瞬间电压跌落是否超过0.3V2信号线长度超过20cm时用双绞线且远离点火高压线3遮光罩用黑色热缩管罩住发射管和接收管前端4软件消抖扫描周期从5ms调到10ms确认误报警概率显著下降如果上述都无效就在避障信号输入到P1.0之间加一个510Ω电阻和0.1uF电容组成RC低通滤波再串联74HC14施密特触发器整形。注意加入RC后信号边沿会变缓但51单片机读取IO时只要在电平稳定区间采样不影响判断。实测中这个RC网络能滤除大部分毛刺但会让响应延迟约0.1ms可以忽略。本文还有配套的精品资源点击获取
返回列表