電路原理圖如下:
0.jpg (53.6 KB, 下載次數: 43)
下載附件
2019-1-25 22:47 上傳
系統理論分析與計算
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點陣顯示
- }
復制代碼
0.png (7.41 KB, 下載次數: 42)
下載附件
2019-1-25 22:50 上傳
所有資料51hei提供下載:
原理圖.rar
(436.93 KB, 下載次數: 18)
2019-1-25 22:09 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
M題程序.rar
(60.15 KB, 下載次數: 23)
2019-1-25 22:09 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|