技术文档

单片机 测速仪 单片机实例分享,反射式红外测速仪DIY

小编 2025-07-03 技术文档 23 0

单片机实例分享,反射式红外测速仪DIY

常用的测速方法

常用的测速传感器可输出脉冲信号,只要通过频率电压或电流转换就能与电压、电流输入型的指针表和数字表匹配。频率电流转换的方法有阻容积分法、电荷泵法和专用集成电路法,前两种方法在磁电转速仪中也有运用。专用集成电路大多数是阻容积分法、电荷泵法的综合。目前,常用的专用集成电路有LM331、AD654和VF32等,转换精度在0.1%以上;但在低频时,这种转换就无能为力。采用单片机或FPGA做F/D和D/A转换,转换精度在0.5%~0.05%,量程从0~2Hz到0~20kHz,频率低于10Hz时反映时间也会变长。

在显示精度、可靠性、成本和使用灵活性上有一定要求时,就可直接采用脉冲频率运算型测速仪。频率运算方法有定时计数法(测频法)、定数计时法(测周法)和同步计数计时法。测频法在测量上有±1的误差,低速时误差较大。测周法也有±1个时间单位的误差,在高速时,误差也很大。同步计数计时法综合了上述两种方法的优点,在整个测量范围都达到了很高的精度,万分之五以上精度的测量转速仪表基本都采用同步计数计时法。

反射式红外测速仪的设计

这里我们介绍一款实用的反射式红外测速仪的设计与制作。

反射式红外测速仪在测量物体运转速度时,首先向被测物体发射出红外线脉冲,利用被测物体表面的反射能力(可在被测物体表面粘贴白色的反射纸等),使红外接收器收到光脉冲信号,然后通过光电转换电路将光脉冲信号转变为电脉冲信号,电脉冲信号通过放大和处理后,输入到单片机的计数控制门,与内部的标准表秒脉冲信号相比较,经运算后,通过显示器将被测物体运动的旋转速度显示出来。

红外探头的测量距离根据实际需要,可设计成近距离和远距离两类。近距离的探头可采用小功率发光管和光敏受光管。如果是远距离的测量,探头就可采用中、大功率的发光二极管或者是合适的激光二极管。

1.系统设计方案

图26.1为反射式红外测速仪的系统构成方框图,由单片机控制器、38kHz载频振荡器、红外线发射/接收电路、8×2点阵字符型液晶屏及工作电源等组成。

图26.1 反射式红外测速仪的系统构成方框图

2.转速测试原理

转速测试原理见图26.2。进入测试状态后,38kHz的载频振荡器起振工作,驱动红外发射管向外发射红外载频信号。单片机首先检测信号的边沿,当一个脉冲的下降沿到来时(图中A点),计数器开始对脉冲计数,同时,单片机还启动定时器进行测试计时。当定时器计时到1000ms时(图中B点),单片机发出一个准备结束本次测试的信号,这时程序又开始检测信号的下降沿,当下降沿到来时(图中C点),单片机对脉冲的计数cnt及对测试时间的计时time完成。此时根据公式:转速=(cnt/time)×60000即可算出此时的转速。当计时到1300ms时(图中D点),单片机输出显示,将测得的转速显示到液晶屏上。此次测试、显示完成后,又进入下一次的测试、显示,周而复始。

图26.2 转速测试原理

测速仪常用于电机、电扇、纸张、塑料、化纤、洗衣机、汽车、飞机、轮船等制造业中。依据对转速检测原理的不同,测速仪可分为以下几种类型。

离心式测速仪:利用离心力与拉力的平衡来检测转速,是最传统的机械式测速工具,测量精度一般在1~2级。

磁性测速仪:利用旋转磁场,在金属罩帽上产生旋转力,通过旋转力与游丝力的平衡来检测转速。

电动式测速仪:电动式测速仪由小型交流发电机、电缆、电动机和磁性表头组成。磁性表头与小型交流电动机同轴连接在一起,小型交流发电机产生交流电,交流电通过电缆输送,并驱动小型交流电动机,小型交流电动机的转速与被测轴的转速一致,磁性表头指示的转速自然就是被测轴的转速。

闪光式测速仪:闪光式测速仪可发出频率可调的脉冲闪光,利用人眼视觉暂留的原理对转动物体进行测速。除了检测转速(往复速度)外,还可以观测循环往复运动物体的静像。

电子式测速仪:电子式测速仪是以现代电子技术及计算机技术为基础而设计的,一般有传感器和显示器,有的还有信号输出和控制。

3.电路设计

反射式红外测速仪的电路如图26.3所示。单片机选择Atmel公司的ATmega48,负责整个测试系统的运行。IC2及阻容元件组成了38kHz的载频振荡器,其载频经VT1放大后驱动红外发射管IR向外发射红外线。IC4为38kHz的一体化红外接收头,它负责红外线的接收、放大及解调,它将解调出的脉冲信号送入单片机进行计数处理。IC5为液晶显示模块,使用了8×2的点阵字符型液晶屏(带背光),形体较小,用于显示测试得到的转速。

图26.3 反射式红外测速仪电路图

整机供电使用9V积层单池,经稳压器IC5稳定为5V后,供单片机工作。笔者实际制作的发射、接收组件如图26.4所示,使用热熔胶固定。制作完成的样机上的液晶屏、电源开关及按键如图26.5所示,按键SB目前没有使用,作为备用,整机照片如图26.6所示。

图26.4 发射、接收组件

图26.5 液晶屏及控制按键

图26.6 反射式红外测速仪整机照片

主函数

void main(void)//主函数

{

uchar temp;//定义单字节无符号局部变量

float count,time,x;//定义浮点型局部变量

Delay_nms(400);//延时400ms,等待电源稳定

init_devices();//初始化单片机

InitLcd();//初始化液晶模块

display1();//液晶屏显示欢迎界面

Delay_nms(2000);//等待2s

display2();//液晶屏显示工作界面

DisFlag=1;//测速显示标志置1

while(1)//无限循环

{

WDR();//看门狗喂狗指令

if(DisFlag==1)//如果测速显示标志为1

{

time=(float)tx;//整数转成浮点数

count=(float)cx;

x=count/time;x=x*30000;//数学计算

DisVal=(uint)x;

/******将测得的4位转速值存放于显示缓冲区*******/

disx[3]=(DisVal/1000)%10;

disx[2]=(DisVal/100)%10;

disx[1]=(DisVal%100)/10;

disx[0]=DisVal%10;

/**********在液晶屏上显示转速值*********/

DisplayOneChar(4,1,disx[3]+0x30);

DisplayOneChar(5,1,disx[2]+0x30);

DisplayOneChar(6,1,disx[1]+0x30);

DisplayOneChar(7,1,disx[0]+0x30);

/**此次显示完成后,相关变量初始化,准备进入下一次的测试**/

DisFlag=0;WorkTime=0;

DisTime=0;

EndFlag=0;Start=0;cnt=0;

}

else//否则如果测速显示标志为0则进行脉冲取样

{

do{

temp=PIND&0x04;WDR();JS=1;//等待下降沿后下一次测试

if(Counter>1500)

{Counter=0;JS=0;DisFlag=1;cx=0;goto END;}

}while(temp==0x04);

BeginFlag=1;Start=1;GICR=0x40;

//重开INT0中断

END:;

}

}

}

4.软件设计

程序主要分为主控程序、液晶屏驱动程序和头文件三大部分,这样设计速度快、结构完善,并且也便于整个程序的装配。程序使用ICC7.14C集成开发环境编译。限于篇幅,这里仅介绍一下主函数,完整程序可以到QQ群下载。

调试与应用

本机唯一需要调整的是红外发射电路的38kHz载频,它关系到红外测速仪的使用灵敏度及可靠性。整机检查无误后通电,用一个10kΩ的多圈可调电位器代替R6,用示波器或频率计测R7电阻的任一端,细调电位器,使频率为38.000kHz,越准确越好。调好后,取下电位器,测出其阻值,用一个同阻值的固定电阻代替电位器,焊在R6位置。整机其他部分全是数字信号处理,因此只要器件良好,就无需调整了。

红外发射管需要套一个直径5mm的黑色热塑套管,并且与红外接收头稍微隔开一点距离安装,防止发射出的红外光直接进入红外接收头。当然也不能离开太远,以免降低接收灵敏度。

项目实战:51单片机霍尔自行车里程测速仪设计项目 原理图 程序

最近后台有小伙伴私信我说,我讲得都太基础了,有没有做过单片机霍尔传感器测速度相关的项目,我现在就把以前做的一个单片机霍尔自行车里程测速仪项目分享给大家。

这个也是我以前做过的一个项目,现在拿出来分享给大家,大家不用觉得难,不过就是硬件做基础,然后用软件代码去控制而已,只要按照教程一步步来做你就会发现其实很简单。

好了,针对此项目下面有几点说明

1、单片机是通用的无论51还是52、无论stc还是at都一样,引脚功能都一样。

程序也是一样的。

2、原理图中的.ddb、.Bkp等格式是要用protel打开的,没有软件的不要紧,

3、程序中的.c文件可以用记事本(文本文档)打开,就是程序了。其他的是写程序是自动生成的,没什么用的。

4、可以按照正面布局,不要按照实物的背面焊接,要按照原理图焊接。

数码管脚位排布说明:

正面朝自己,秒点在下,左下为1脚,逆时针排布,左上为最后一个脚!请坛友焊接前弄清脚位排布再焊接!祝你们成功!

废话不多说,直接上实物图:

霍尔自行车测速电路原理图:

元器件列表

单片机霍尔自行车里程测速仪参考源程序:

//说明1:P00—P07:a-----dp P27—P24:com1-----com4 P34切换显示 P32—INT0 一个磁钢

//说明2:此程序针对车轮周长为207cm,其他型号周长,可改变参数就行

//说明3:数码管从左至右 高------低

#include<reg51.h>

#include"juxun001.h"

//主函数=====================

void main()

{

time0_int0_init();//定时器0和外部中断0的初始化

while(!TR0) //上电一直未切割时就显示 0.0.0.0

{

init_display();

}

while(1)

{

if(!change)//按下切换按键显示里程

{

delay1m(5);

if(!change)

{

flag = ~flag;

}

while(!change);

}

}

}

//==定时器0中断函数

void time0_interrupt()interrupt 1

{

TL0 = (65536 - 5000) % 256;// 12M晶振,5ms定时

TH0 = (65536 - 5000) / 256;

display_function();

time_counter++;

time_counter8++;

if(time_counter8 >= 1600)//大于8s没切割,车子视为停下了,速度为:0,但里程还记着

{

time_counter8 = 0;

speed = 0;//速度为 0

point1 = 0;

buf1[3] = speed%10;buf1[2] = speed/10%10;

buf1[1] = speed/100%10;buf1[0] = speed/1000%10;

}

}

//==========外部中断0中断函数=

void int0_interrupt()interrupt 0

{

external_counter++;

if(external_counter ==1 )TR0 = ~TR0;//第一次切割打开定时器0

if(external_counter == 65535)external_counter = 0;

time_counter8 = 0; //只要8秒内有切割,车子就仍在运行

if(external_counter % 2 == 0)//切割2次 更新下速度

{ //*5是因为中断一次是5MS

if(flag10){speed =((ulong)(36000)*zhouchang)/(time_counter * 5);flag1=1;}

else if(flag11){speed =((ulong)(36000)2zhouchang)/(time_counter * 5);}//速度:单位为 m/h ,*1000的目的是不出现浮点数

if((speed >= 100)&&(speed < 1000)) //100 ---- 1000 3位整数

{

point1 = 1;buf1[3] = speed%10;buf1[2] = speed/10%10;

buf1[1] = speed/100%10;buf1[0] = 0;}

else if((speed >= 1000)&&(speed < 10000)) //1000 ---- 10000 4位整数

{

point1 = 1;speed = (uint)speed;

buf1[3] = speed%10;buf1[2] = speed/10%10;

buf1[1] = speed/100%10;buf1[0] = speed/1000%10;}

else if((speed >= 10000)&&(speed < 100000)) //10000 ----- 100000 5位整数

{

point1 = 2;

buf1[3] = speed/10%10;buf1[2] = speed/100%10;

buf1[1] = speed/1000%10;buf1[0] = speed/10000%10;}

else if((speed >= 100000)&&(speed < 1000000)) //100000 ------ 1000000 6位整数

{

point1 = 3;

buf1[3] = speed/100%10;buf1[2] = speed/1000%10;

buf1[1] = speed/10000%10;buf1[0] = speed/100000%10;}

time_counter = 0;

}

if(external_counter % 8 == 0)//每切割8次 更新下里程

{

s = (ulong)external_counter * zhouchang; //里程:单位为 cm

if((s >= 1000)&&(s < 10000))

{

point2 = 1; // 0.012 001212

buf2[3] = s/100%10;buf2[2] = s/1000%10;

buf2[1] = 0;buf2[0] = 0;}// 4位整数

else if((s >= 10000)&&(s < 100000))

{

point2 = 1;

buf2[3] = s/100%10;buf2[2] = s/1000%10;

buf2[1] = s/10000%10;buf2[0] = 0;}// 5位整数 0.123 012345

else if((s >= 100000)&&(s < 1000000))

{

point2 = 1;

buf2[3] = s/100%10;buf2[2] = s/1000%10;

buf2[1] = s/10000%10;buf2[0] = s/100000%10;} // 6位整数 1.234 1234 56

else if((s >= 1000000)&&(s < 10000000))

{

point2 = 2;

buf2[3] = s/1000%10;buf2[2] = s/10000%10;

buf2[1] = s/100000%10;buf2[0] = s/1000000%10;}// 7位整数 1234 567

else if((s >= 10000000)&&(s < 100000000))

{

point2 = 3;

buf2[3] = s/10000%10;buf2[2] = s/100000%10;

buf2[1] = s/1000000%10;buf2[0] = s/10000000%10;} // 8位整数 1234 5678

}

}

//==========开电源就显示的数据,初始显示速度

void init_display()

{

uchar i;

for(i = 0;i < 4;i++)

{

wei = bitcode[num - 1];

led = display1[buf1[num–]];

delay1m(4);

if(num == 0)num = 4;

}

}

//==显示函数=

void display_function()

{

if(flag == 0)//显示速度

{

switch(point1)

{

case 0:wei = bitcode[num-1];led = display1[buf1[num-1]];num–;break;//速度显示 0

case 1:if(num == 1){ wei = bitcode[num-1];led = 0x7f&display1[buf1[num-1]];num–;}

else { wei = bitcode[num-1];led = display1[buf1[num-1]];num–;}break;//最高位小数点亮

case 2:if(num == 2){ wei = bitcode[num-1];led = 0x7f&display1[buf1[num-1]];num–;}

else { wei = bitcode[num-1];led = display1[buf1[num-1]];num–;}break;//第二高位小数点亮

case 3:if(num == 3){ wei = bitcode[num-1];led = 0x7f&display1[buf1[num-1]];num–;}

else { wei = bitcode[num-1];led = display1[buf1[num-1]];num–;}break;//第三高位小数点亮

default:break;

}

if(num == 0)num = 4;

}

else if(flag == 1)//显示里程

{

switch(point2)

{

case 0:wei = bitcode[num-1];led = display1[buf2[num-1]];num–;break;//里程显示 0

case 1:if(num == 1){ wei = bitcode[num-1];led = 0x7f&display1[buf2[num-1]];num–;}

else { wei = bitcode[num-1];led = display1[buf2[num-1]];num–;}break;//最高位小数点亮

case 2:if(num == 2){ wei = bitcode[num-1];led = 0x7f&display1[buf2[num-1]];num–;}

else { wei = bitcode[num-1];led = display1[buf2[num-1]];num–;}break;//第二高位小数点亮

case 3:if(num == 3){ wei = bitcode[num-1];led = 0x7f&display1[buf2[num-1]];num–;}

else { wei = bitcode[num-1];led = display1[buf2[num-1]];num–;}break;//第三高位小数点亮

default:break;

}

if(num == 0)num = 4;

}

}

//=================定时器0和外部中断0的初始化函数=

void time0_int0_init()

{

TMOD |= 0x01;

TMOD &= 0xfd;//定时器0工作于方式1

TL0 = (65536 - 5000) % 256;//12M晶振,5ms定时

TH0 = (65536 - 5000) / 256;

IT0 = 1;//外部中断0,负跳变触发方式

TR0 = 0;

ET0 = 1;

EX0 = 1;

EA = 1;

}

//==========ms 级延时函数=

void delay1m(uchar x)

{

uchar i,j;

for(i=0;i<x;i++) //连数x次,约 x ms

for(j=0;j<120;j++); //数120 次,约1 ms

}

好了,以上就是这个项目的全部内容了。

最后,如果有什么意见或者建议欢迎您留言给我,让我们共同学习一起进步,鉴于无法上传附件,如果需要完整代码或设计文件,请留言或私信我,看到后会第一时间回复。

谢谢!

相关问答

而是成为人们娱乐、休闲、锻炼的首选.自行车 测速仪 能够满...

[最佳回答]Aspeople'slivingstandardsimprove,people'srequirementsforqualityoflifeincreasing,...

CPU风扇是PWM控制好还是电压控制好?

建议用PWM。控制原理来完成对直流电机的正转、反转以及其加速、减速过程的控制,在此过程中是通过单片机的定时器加上中断的方式产生不同时长的高低电压脉冲信...

猜你喜欢