电路原理图如下:
系统理论分析与计算
1、管道倾斜角度的分析 小球在管道中运动需要受力,通过受力分析获取受力之间的关系角度;与力联系在一起的是加速度a,从而引入小球运动速度的公式;考虑到摩擦力,小球释放的方式,传感器的位置,通过整体固定来减小误差;通过程序对时间的精进减小误差。传感器A距离A端及S1 = 28.5cm,传感器B距离B端S2 = 2cm。摩擦系数0.04。 2、小球滚动加速度a的计算
(1)小球在管道中运动速度分析当从管道口放下小球时速度为零,通过加速度a变速运动,在通过两个电感式接近开关会计算这段距离的时间,通过物理分析可得方程组:S1 = 1/2*a*T1^2; S2 =(a*T1)*T2 + 1/2*a*T2^2;综合方程组可得S2/S1 = 2S1*(T2/T1) + S1*(T2/T1)^2;令x=T2/T1; (2)将带回公式S2/S1 = 2S1*(T2/T1) +S1*(T2/T1)^2求算T1代入公式会得(x+1)^2 = S2/S1;求得T1,T1 = T2/((S2/S1+1)^1/2-1); (3)求出加速度a因为a=2*S1/T1^2;两传感器间的距离已知; 所以最终a=(2S2+4S1-4*(S1*S2+S1^2)^1/2)/T1^2;
3、所求夹角余弦值的计算
(1)受力分析小球在运动过程中会受到重力,管壁的支持力和摩擦力,通过物理公式m*g*Sinx - u*m*g*Cosx =ma;( 注:u为摩擦系数,m为质量,a为加速度,x为角度) (2)夹角余弦值的公式化简通过数学三角函数公式化简得到最终等式为:Cosx=(-a*u+(-a^2+g^2+g*u^2)^1/2)/(g*(1+u^2));参数带入得算法公式:x=((0.5503*t^3-3.535*T^2)+72.59*x-260.5)/(x-8.322)+0.5;程序的设计 (1)程序功能描述与设计思路通过3个独立按键分别实现切换菜单,设置角度显示数据 1)通过单片机检测从传感器检测得来的开关量,实现对通过钢珠的计数并显示; 2)对比两个钢珠通过传感器的时间,显示钢珠运动方向; 3)通过采样钢珠在不同角度通过两个传感器的时间差进行拟合曲线,得出拟合曲线方程并计算,从而显示出管道的的倾斜角度;
单片机源程序如下:
- #include "reg51.h"
- #define LCDPORT P0 //液晶的数据口
- sbit DU = P2^0; //数码管段选
- sbit WE = P2^1; //数码管位选
- sbit CS88 = P2^2; //8X8点阵使能
- sbit DS1302=P2^7; //HJ-C52主板 时钟复位 关掉DS1302 以免影响其他IO口实验。
- sbit LCD1602=P2^5;//HJ-C52主板 LCD1602复位 关掉LCD1602显示 以免影响其他IO口实验。
- sbit LCD1602_RS = P1^0; //位定义,液晶的数据/命令选择
- sbit LCD1602_RW = P1^1; //位定义,液晶的读写选择
- sbit LCD1602_EN = P2^5; //位定义,液晶使能信号
- sbit k1=P3^4; //选择
- sbit k2=P3^5; //确认返回
- sbit k3=P3^6; //加
- sbit k4=P3^7; //减
- sbit catch_A = P2^0; //A传感器引脚定义
- sbit catch_B = P2^4; //B传感器引脚定义
- unsigned int ang,time,ang_ge,ang_shi,ang_bai,power;
- float time_buff=0;
- char buft = 0;
- char i=0,j=0,n=0,flag_1=0,flag_2=0,flag_0=1,flag_buf=0;
- char ten,bits,a,b,c,d,z=1;
- char NO_a = 0,NO_b = 0,buff;//NO_a、NO_b分别代表A传感器、B传感器检测到的钢珠数,buff表示识别运动方向的标志
- unsigned char code ucForum0[] =" Welcome SZ076 ";
- unsigned char code ucForum_0[] =" Pipe Ball Move";
- unsigned char code ucForum[] ="ang:"; //在CODE区定义一个用于显示的常量字符串
- unsigned char code ucForum1[]="Set fuc:";
-
- unsigned char code ucForum2[]="Num:";
- unsigned char code ucForum3[]="Dir:";
- unsigned char code ucForum5[]="Cyc:";
- void conversion(char date);
- void direction();
- void screen_0();
- void screen_1();
- void screen_2();
- void hj_c52(); //HJ-C52复位函数
- void key_control();
- void Delay(unsigned int uiCount); //延时函数
- void LCD1602_CheckBusy(void); //液晶忙检测
- void LCD1602_WriteInformation(unsigned char ucData,bit bComOrData); //在液晶上写数据或者写命令,0为命令,1为数据
- void LCD1602_Init(void); //液晶初始化
- void LCD1602_MoveToPosition(unsigned char x,unsigned char y); //液晶的坐标移动到指定位置
- void LCD1602_DisplayOneCharOnAddr(unsigned char x,unsigned char y,unsigned char ucData); //在液晶指定位置显示字符
- void LCD1602_DisplayString(unsigned char addr,unsigned char *ucStr); //在液晶上显示字符串
- //按键控制
- void key_control()
- {
-
- if(k1==0)
- {
-
- j++;
- while(k1!=1);
- if(j==2) j=0;
- }
- if(k2 == 0)
- {
- i++;
- if(i==1)
- {
- flag_0=0;
- flag_1=1;
- flag_2=0;
- }
- else
- {
- flag_1=0;
- flag_2=1;
- flag_0=0;
- }
- if(i>=2) i=0;
- NO_b=0; //将计过的球数清零
- buff = 0; //将运动方向标志清零
- while(k2!=1);
- LCD1602_WriteInformation(0x01,0);
- }
-
- if(k3==0)
- {
- n++;
- while(k3!=1);
- }
-
- if(k4==0)
- {
- n--;
- while(k4!=1);
- }
- }
- //数据处理
- void conversion(char date)
- {
- date<0?date=-date:date;
- ten=date/10+0x30;
- bits=date%10+0x30;
- }
- // 判断小球运动方向
- void direction()
- {
- while(catch_A == 0) //判断小球通过A传感器与否
- {
-
- if(c == 0)
- {
- NO_a++;
- c++; //防止触发A传感器期间多次执行NO_a++;
- }
- a = 1;
- if(a > b)
- {
- buff = 2; // 从B到A
- a = 0;
- }
- }
- c = 0;
- while(catch_B == 0)
- {
- if(d == 0)
- {
- NO_b++;
- d++;
- }
- b = 1 ;
- if(b > a)
- {
- buff = 1; //从A到B
- b = 0;
- }
- }
- d = 0;
- }
-
- //初始界面
- void screen_0()
- {
- if(flag_0==1)
- {
- LCD1602_DisplayString(0x80,ucForum0); //显示的内容
-
- LCD1602_DisplayString(0xc0,ucForum_0); //显示的内容
- }
- }
- //界面一
- void screen_1()
- {
- if(flag_1==1)
- {
- if(j==0)
- {
- LCD1602_WriteInformation(0xcf,0);
- LCD1602_WriteInformation(42,1);
- z+=n;
- if(z>=4) z=1;
- if(z<=0) z=3;
- n=0;
- }
-
- LCD1602_DisplayString(0x80,ucForum); //显示的内容
- LCD1602_DisplayString(0xc0,ucForum1); //显示的内容
- LCD1602_WriteInformation(0xca,0);
- LCD1602_WriteInformation(z%10+48,1);
- }
- }
- void screen_2() //界面二
- {
- char Cyc = 0;
- if(flag_2==1)
- {
- LCD1602_DisplayString(0x80,ucForum2); //Num
-
- LCD1602_DisplayString(0x88,ucForum3); //Dir
-
- LCD1602_DisplayString(0xc0,ucForum5); //Cyc
-
-
- switch(z)
- {
- case 1:
- conversion(NO_b);
- LCD1602_WriteInformation(0x84,0); //计数
- LCD1602_WriteInformation(ten,1);
- LCD1602_WriteInformation(0x85,0);
- LCD1602_WriteInformation(bits,1);
- break;
- case 2:
- if(buff == 1) //方向
- {
- LCD1602_WriteInformation(0x8c,0);
- LCD1602_WriteInformation(0x30,1);
- LCD1602_WriteInformation(0x8d,0);
- LCD1602_WriteInformation(1+0x30,1);
- }
- if(buff == 2)
- {
- LCD1602_WriteInformation(0x8c,0);
- LCD1602_WriteInformation(1+0x30,1);
- LCD1602_WriteInformation(0x8d,0);
- LCD1602_WriteInformation(0x30,1);
- }
- break;
- // case 3:
- // flag_buf=1; //角度
- // angle_zhi();
- // LCD1602_WriteInformation(0xc4,0);
- // LCD1602_WriteInformation((power/10)+0x30,1);
- // LCD1602_WriteInformation(0xc5,0);
- // LCD1602_WriteInformation(((power%10))+0x30,1);
- // conversion(power);
- // LCD1602_WriteInformation(0xc4,0);
- // LCD1602_WriteInformation(ten,1);
- // LCD1602_WriteInformation(0xc5,0);
- // LCD1602_WriteInformation(bits,1);
- // LCD1602_WriteInformation(0xc6,0);
- // LCD1602_WriteInformation(time/1000+0x30,1);
- // LCD1602_WriteInformation(0xc7,0);
- // LCD1602_WriteInformation(time/100%10+0x30,1);
- // LCD1602_WriteInformation(0xcd,0);
- // LCD1602_WriteInformation(time/10%10+0x30,1);
- // LCD1602_WriteInformation(0xcf,0);
- // LCD1602_WriteInformation(time%10+0x30,1);
- // break;
- case 3: //周期
- Cyc=NO_b/2;
- conversion(Cyc);
- LCD1602_WriteInformation(0xc4,0);
- LCD1602_WriteInformation(ten,1);
- LCD1602_WriteInformation(0xc5,0);
- LCD1602_WriteInformation(bits,1);
- break;
- }
- }
- }
- //main函数
- void main()
- {
-
- hj_c52(); //HJ-C52复位函数
- LCD1602_Init(); //液晶初始化
- TMOD=0x01; //
- TH0=0;
- TL0=0;
- while(1) //程序循环
- {
- key_control();
- screen_0();
- screen_1();
- screen_2();
- direction();
- if(k1 == 0)
- {
- Delay(20);
- if(k1==0)
- {
- flag_buf++;
- while(k1 != 1);
- }
- }
- while(flag_buf==1)
- {
- if(catch_A == 0)
- {
- TH0 = 0;
- TL0 = 0;
- TR0 = 1; //定时器T0计数
-
- while(catch_B == 1)
- {
- if(TF0 == 1)
- {
- buft++;
- TF0 = 0;
- }
- }
- TR0 = 0 ; //定时器T0停止
- time=((TH0*256) + TL0 + (65536*buft))/10; //ms为单位
- time_buff=time/100.0;
- power=(int)((-(0.6566*time_buff*time_buff)+28.75*time_buff+13.76)/(time_buff-8.925))+0.5;
- conversion(power);
- LCD1602_WriteInformation(0x84,0);
- LCD1602_WriteInformation(ten,1);
- LCD1602_WriteInformation(0x85,0);
- LCD1602_WriteInformation(bits,1);
- TH0 = 0;
- TL0 = 0;
- time = 0;
- buft = 0;
- }
- if(k1 == 0)
- {
- Delay(20);
- if(k1==0)
- {
- flag_buf++;
- while(k1 != 1);
- }
- }
- }
- if(flag_buf==2)
- {
- flag_buf=0;
- LCD1602_WriteInformation(0x01,0);
-
- }
- }
-
- }
-
- /******************************************************************************
- 函数名称:LCD1602_CheckBusy
- 函数功能:忙检测
- *******************************************************************************/
- void LCD1602_CheckBusy(void)
- {
- unsigned char i = 255;
- LCDPORT = 0xFF; //读之前先置位,准备读取IO口数据
- LCD1602_RS = 0;
- LCD1602_RW = 1; //使液晶处于读数据状态
- LCD1602_EN = 1; //使能液晶,高电平有效
- while((i--) && (LCDPORT & 0x80)); //忙检测
- LCD1602_EN = 0;
- }
- /******************************************************************************
- 函数名称:LCD1602_WriteInformation
- 函数功能:向LCD1602液晶写入数据或者命令
- ********************************************************************/
- void LCD1602_WriteInformation(unsigned char ucData,bit bComOrData)
- {
- LCD1602_CheckBusy(); //在写入数据或者命令前先进行忙检测
- LCDPORT = ucData; //先将数据或者命令送至IO
- LCD1602_RS = bComOrData; //确定是写入数据还是写命令
- LCD1602_RW = 0; //使液晶处于写入信息状态
- LCD1602_EN = 1; //使能液晶,高电平有效
- LCD1602_EN = 0;
- }
- /******************************************************************************
- 函数名称:LCD1602_Init
- 函数功能:液晶初始化函数
- *******************************************************************************/
- void LCD1602_Init(void)
- {
- LCD1602_WriteInformation(0x38,0);
- Delay(200);
- LCD1602_WriteInformation(0x38,0);
- Delay(100);
- LCD1602_WriteInformation(0x38,0);
- Delay(100);
- LCD1602_WriteInformation(0x38,0); //写入命令,5x7点阵工作方式,8位数据接口
- Delay(100);
- LCD1602_WriteInformation(0x0c,0); //显示设置,开显示,光标不显示,不闪烁
- Delay(20);
- LCD1602_WriteInformation(0x01,0); //清屏指令
- Delay(20);
- }
- /******************************************************************************
- 函数名称:LCD1602_MoveToPosition
- 函数功能:将液晶的光标移动到指定的位置
- *******************************************************************************/
- void LCD1602_MoveToPosition(unsigned char x,unsigned char y)
- {
- if(0 == x)
- LCD1602_WriteInformation((0x80 | y),0); //光标定位到第一行的y列
- if(1 == x)
- LCD1602_WriteInformation((0xC0 | y),0); //光标定义到第二行的y列
- }
- /******************************************************************************
- 函数名称:LCD1602_DisplayOneCharOnAddr
- 函数功能:在指定的位置上显示指定的字符
- *******************************************************************************/
- void LCD1602_DisplayOneCharOnAddr(unsigned char x,unsigned char y,unsigned char ucData)
- {
- LCD1602_MoveToPosition(x,y); //光标位置
- LCD1602_WriteInformation(ucData,1); //写入数据
- }
- /******************************************************************************
- 函数名称:LCD1602_DisplayString
- 函数功能:显示字符串
- *******************************************************************************/
- void LCD1602_DisplayString(unsigned char addr,unsigned char *ucStr)
- {
- LCD1602_WriteInformation(addr,0);
- while(*ucStr != '\0') //字符串结束之前,循环显示
- {
- LCD1602_WriteInformation(*ucStr,1); //依次写入每一个字符
- ucStr++; //指针增加
- }
- }
- /******************************************************************************
- 函数名称:Delay
- 函数功能:延时函数
- *******************************************************************************/
- void Delay(unsigned int uiCount)
- {
- unsigned char j = 244;
- for(;uiCount > 0;uiCount--) while(--j);
- }
- /******************************************************************/
- // 以下为HJ-C52复位函数
- /******************************************************************/
- void hj_c52()
- {
- LCD1602=0;//关掉LCD1602 以免影响点阵管IO口电评
- DS1302=0;//关掉DS1302 以免影响点阵管IO口电评
- CS88=0; //关掉8X8点阵显示
- WE=1;
- P0=0Xff;
- WE=0; //关掉数码管显示
- CS88=0; //关掉8X8点阵显示
- }
复制代码
所有资料51hei提供下载:
原理图.rar
(436.93 KB, 下载次数: 18)
M题程序.rar
(60.15 KB, 下载次数: 23)
|