http://mp.weixin.qq.com/mp/homepage?__biz=MzU3OTczMzk5Mg==&hid=7&sn=ad5d5d0f15df84f4a92ebf72f88d4ee8&scene=18#wechat_redirect --------------------------------------------------------------------------------------------------------------------------
本文主要测量电机的速度,然后用数字管显示电机的速度。该装置主要由光电速度测量部分、脉冲处理和显示部分两部分组成。光电速度测量部分主要由光电传感器组成。脉冲处理部分主要通过施密特触发器对接收到的脉冲进行波形校正,由单片机组成T输出电机的转速在单片机处理后显示。
让我们了解一下光电测速部分!
本设计选用光电传感器,采用穿透法测量电机转速。光电传感器是一种应用广泛的泛的设备,有各种形式,如透射、反射等,基本原理是当发射管光照射到接收管时,接收管指南,相反关闭。以透射为例,当不透明物体挡住发射与接收之间的间隙时,开关管关闭,否则打开。因此,在转轴上安装遮光叶片,如图3所示片,如图3所示,安装在转轴上,产生脉冲信号。当叶片较多时,旋转一周可以获得多个脉冲信号。这里我们只转10个孔!一分钟内,如果产生1万脉冲,电机转速为1万r/min.
速度测量的方法决定了速度测量信号的硬件连接,速度测量实际上是频率测量,因此,频率测量的一些原则也适用于速度测量。
通常可以用计数法、脉宽法和其他精度法进行测试。所谓计数法,就是给定闸门时间,在闸门时间内计数输入的脉冲数;脉宽测量是利用待测信号的脉宽控制计数门,计数高精度高频计数信号。由于闸门不能与被测信号同步,这两种方法都存在±第一种方法适用于高频信号,第二种方法适用于低频信号。等精度法对高低频信号适应性好。
在这里,为了简化讨论,只使用计数法进行测试。如上图所示:由于光电传感器不易模拟,我们使用555芯片形成一个施密特触发器,光电传感器获得的脉冲5脚输入,并通过3脚输出接收单片机T1(P3.5).。经89C51编程后由P通过数出通过数字管显示转速!
测量转速,使用光电传感器,被测电机带动纸片旋转,我们在纸片上开了10小孔,电机每旋转一周就会产生10个脉冲,产生12个脉冲,要求将转速值(转/分)显示在数码管上。
#include <REG52.H> #define uchar unsigned char #define uint unsigned int #define ulong unsigned long #define LED_DAT P1 sbit LED_SEG0 = P0^3; sbit LED_SEG1 = P0^2; sbit LED_SEG2 = P0^1; sbit LED_SEG3 = P0^0; //sbit pin_SpeedSenser = P3^5; ////光电传感器信号连接T1上 #define TIME_CYLC 100 //12M晶振,定时器10ms中断一次,我们计算一秒钟的速度。 // 1000ms/10ms = 100 #define PLUS_PER 10 //码盘的齿数,假设码盘上有10个齿,即传感器检测到10个脉冲,认为1圈。 // 1000ms/10ms = 100 #define PLUS_PER 10 //码盘的齿数,假设码盘上有10个齿,即传感器检测到10个脉冲,认为1圈。 #define K 100.0 ///校准系数。 unsigned char code table[]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; uchar data Disbuf[4];// 显示缓冲区 uint Tcounter = 0; //时间计数器 bit Flag_Fresh = 0; // 刷新标志 bit Flag_clac = 0; //计算转速标志 bit Flag_Err = 0; //超量程标志 //在数字管上显示四位数 void DisplayFresh(); //计算转速,并将结果放入数字管缓冲区 void ClacSpeed()T0 void init_timer0()T1 void init_timer() void Delay(uint ms); /* interrupt address is 0x000b */ void it_timer0() interrupt 1 { TF0 = 0; //d定时器 T0用于数字管的动态刷新 TH0 = 0xC0; /* init values */ TL0 = 0x00; Flag_Fresh = 1; Tcounter ; if(Tcounter>TIME_CYLC) { Flag_clac = 1;//周期到,该重新计算转速了 } } /* interrupt address is 0x001b */ void it_timer1() interrupt 3 { TF1 = 0; //定时器T1用于单位时间内收到的脉冲数 //速度不是很快,T永远不会受益 Flag_Err = 1; //如果速度很高,我们应该考虑另一种速度测量方法,脉冲宽度计算速度 } void main(void) { Disbuf[0] = 0.///开机时,初始化为0000 Disbuf[1] = 0; Disbuf[2] = 0; Disbuf[3] = 0; init_timer0(); init_timer1(); while(1) { if(Flag_Fresh) { Flag_Fresh = 0; DisplayFresh(); // 定期刷新数码管显示 } if(Flag_clac) { Flag_clac = 0; ClacSpeed(); //计算转速,并将结果放入数字管缓冲区 Tcounter = 0; //定期清零周期 TH1=TL1 = 0x00; ///脉冲计数清零 } if(Flag_Err) //超量程处理 { //数字管显示字母EEEE' Disbuf[0] = 0x9e; ///开机时,初始化为0000 Disbuf[1] = 0x9e; Disbuf[2] = 0x9e; Disbuf[3] = 0x9e; while(1) { DisplayFresh();//不再测速 等待复位i }}} } //在数字管上显示四位数 void DisplayFresh() { P2 |= 0xF0; LED_SEG0 = 0; LED_DAT = table[Disbuf[0]]; Delay(1); P2 |= 0xF0; LED_SEG1 = 0; LED_DAT = table[Disbuf[1]]; Delay(1); P2 |= 0xF0; LED_SEG2 = 0; LED_DAT = table[Disbuf[2]]; Delay(1); P2 |= 0xF0; LED_SEG3 = 0; LED_DAT = table[Disbuf[3]]; Delay(1); P2 |= 0xF0; } //计算转速,并将结果放入数字管缓冲区 void ClacSpeed() { uint speed ; uint PlusCounter; PlusCounter = TH1*256 TL1; speed = K*(PlusCounter/PLUS_PER)/60; //K是校准系数,如速度不准,调整K的大小 Disbuf[0] = (speed/1000); Disbuf[1] = (speed/100); Disbuf[2] = (speed/10); Disbuf[3] = speed; } ///初始化定时器T0 void init_timer0() { TMOD &= 0xf0; //定时10毫秒 /* GATE0=0; C/T0#=0; M10=0; M00=1; */ TMOD |= 0x01; TH0 = 0xC0; /* init values */ TL0 = 0x00; ET0=1; /* enable timer0 interrupt */ EA=1; /* enable interrupts */ TR0=1; /* timer0 run */ } ///延迟函数 void Delay(uint ms) { uchar i; while(ms--) for(i=0;i<100;i ); } ///初始化定时器T1 void init_timer1() { TMOD &= 0x0F; /* GATE0=0; C/T0#=1; M10=0; M00=1; */ TMOD |= 0x50; TH1 = 0x00; /* init values */ TL1 = 0x00; ET1=1; /* enable timer1 interrupt */ EA=1; /* enable interrupts */ TR1=1; /* timer1 run */ }