找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2956|回复: 3
打印 上一主题 下一主题
收起左侧

电设 管道钢珠的程序和电路原理图+51单片机源程序

[复制链接]
跳转到指定楼层
楼主
电路原理图如下:



系统理论分析与计算

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)通过采样钢珠在不同角度通过两个传感器的时间差进行拟合曲线,得出拟合曲线方程并计算,从而显示出管道的的倾斜角度;

单片机源程序如下:
  1. #include "reg51.h"       
  2. #define LCDPORT P0  //液晶的数据口


  3. sbit DU = P2^0; //数码管段选
  4. sbit WE = P2^1; //数码管位选
  5. sbit CS88 = P2^2; //8X8点阵使能
  6. sbit DS1302=P2^7; //HJ-C52主板 时钟复位 关掉DS1302 以免影响其他IO口实验。
  7. sbit LCD1602=P2^5;//HJ-C52主板 LCD1602复位 关掉LCD1602显示 以免影响其他IO口实验。
  8. sbit LCD1602_RS = P1^0;        //位定义,液晶的数据/命令选择
  9. sbit LCD1602_RW = P1^1;        //位定义,液晶的读写选择
  10. sbit LCD1602_EN = P2^5;        //位定义,液晶使能信号

  11. sbit k1=P3^4;         //选择
  12. sbit k2=P3^5;         //确认返回
  13. sbit k3=P3^6;         //加
  14. sbit k4=P3^7;         //减

  15. sbit catch_A = P2^0;        //A传感器引脚定义
  16. sbit catch_B = P2^4;        //B传感器引脚定义




  17. unsigned int ang,time,ang_ge,ang_shi,ang_bai,power;
  18. float time_buff=0;
  19. char buft = 0;
  20. char i=0,j=0,n=0,flag_1=0,flag_2=0,flag_0=1,flag_buf=0;
  21. char ten,bits,a,b,c,d,z=1;
  22. char NO_a = 0,NO_b = 0,buff;//NO_a、NO_b分别代表A传感器、B传感器检测到的钢珠数,buff表示识别运动方向的标志

  23. unsigned char code ucForum0[] =" Welcome  SZ076 ";
  24. unsigned char code ucForum_0[] =" Pipe Ball Move";
  25. unsigned char code ucForum[] ="ang:";          //在CODE区定义一个用于显示的常量字符串
  26. unsigned char code ucForum1[]="Set fuc:";

  27.           
  28. unsigned char code ucForum2[]="Num:";
  29. unsigned char code ucForum3[]="Dir:";
  30. unsigned char code ucForum5[]="Cyc:";

  31. void conversion(char date);
  32. void direction();
  33. void screen_0();
  34. void screen_1();
  35. void screen_2();
  36. void hj_c52();  //HJ-C52复位函数
  37. void key_control();
  38. void Delay(unsigned int uiCount);        //延时函数
  39. void LCD1602_CheckBusy(void);        //液晶忙检测
  40. void LCD1602_WriteInformation(unsigned char ucData,bit bComOrData);        //在液晶上写数据或者写命令,0为命令,1为数据
  41. void LCD1602_Init(void);        //液晶初始化
  42. void LCD1602_MoveToPosition(unsigned char x,unsigned char y);        //液晶的坐标移动到指定位置
  43. void LCD1602_DisplayOneCharOnAddr(unsigned char x,unsigned char y,unsigned char ucData);        //在液晶指定位置显示字符
  44. void LCD1602_DisplayString(unsigned char addr,unsigned char *ucStr);        //在液晶上显示字符串

  45. //按键控制
  46. void key_control()          
  47. {               
  48.                   
  49.                   if(k1==0)
  50.                   {
  51.                        
  52.                            j++;
  53.                            while(k1!=1);
  54.                            if(j==2)  j=0;
  55.                   }

  56.                   if(k2 == 0)
  57.                   {
  58.                                 i++;
  59.                                 if(i==1)
  60.                                 {
  61.                                         flag_0=0;
  62.                                         flag_1=1;
  63.                                         flag_2=0;
  64.                                 }
  65.                                 else  
  66.                                 {
  67.                                         flag_1=0;
  68.                                         flag_2=1;
  69.                                         flag_0=0;

  70.                         }
  71.                                 if(i>=2)  i=0;
  72.                                 NO_b=0;                          //将计过的球数清零
  73.                         buff = 0;                  //将运动方向标志清零
  74.                                 while(k2!=1);
  75.                                 LCD1602_WriteInformation(0x01,0);
  76.                   }
  77.        

  78.                   if(k3==0)
  79.                  {
  80.                                    n++;
  81.                                 while(k3!=1);
  82.                   }


  83.                  
  84.                   if(k4==0)
  85.                  {
  86.                                    n--;
  87.                                 while(k4!=1);
  88.                   }

  89. }


  90. //数据处理
  91. void conversion(char date)                       
  92. {
  93.                   date<0?date=-date:date;
  94.                   ten=date/10+0x30;
  95.                   bits=date%10+0x30;
  96. }


  97. //        判断小球运动方向
  98. void direction()                                 
  99. {
  100.                   while(catch_A == 0)         //判断小球通过A传感器与否
  101.                 {
  102.                      
  103.                          if(c == 0)
  104.                          {          
  105.                                  NO_a++;
  106.                                  c++;          //防止触发A传感器期间多次执行NO_a++;
  107.                          }
  108.                          a = 1;
  109.                      if(a > b)
  110.                      {
  111.                      buff = 2;     //  从B到A
  112.                                  a  = 0;
  113.                      }
  114.                 }
  115.                 c = 0;
  116.                 while(catch_B == 0)
  117.                 {
  118.                         if(d == 0)
  119.                         {
  120.                                 NO_b++;
  121.                                 d++;
  122.                         }
  123.                         b = 1        ;
  124.                     if(b > a)
  125.                     {
  126.                                   buff = 1;    //从A到B
  127.                             b = 0;
  128.                     }
  129.                 }
  130.                 d = 0;

  131. }

  132. //初始界面
  133. void screen_0()
  134. {
  135.                   if(flag_0==1)
  136.                   {
  137.                           LCD1602_DisplayString(0x80,ucForum0);        //显示的内容
  138.                          
  139.                           LCD1602_DisplayString(0xc0,ucForum_0);        //显示的内容

  140.                   }
  141. }


  142. //界面一
  143. void screen_1()                       
  144. {
  145.                  if(flag_1==1)
  146.                                  {

  147.                                          if(j==0)
  148.                                          {
  149.                                            LCD1602_WriteInformation(0xcf,0);
  150.                                            LCD1602_WriteInformation(42,1);
  151.                                    z+=n;
  152.                                            if(z>=4) z=1;
  153.                                            if(z<=0)        z=3;
  154.                                            n=0;
  155.                                          }
  156.                                   
  157.                                   LCD1602_DisplayString(0x80,ucForum);        //显示的内容
  158.                                              LCD1602_DisplayString(0xc0,ucForum1);        //显示的内容
  159.                                           LCD1602_WriteInformation(0xca,0);
  160.                                           LCD1602_WriteInformation(z%10+48,1);
  161.                  }
  162. }

  163. void screen_2()           //界面二
  164. {
  165.                   char Cyc = 0;
  166.                              if(flag_2==1)
  167.                                   {
  168.                           LCD1602_DisplayString(0x80,ucForum2);        //Num
  169.                                                                       
  170.                                      LCD1602_DisplayString(0x88,ucForum3);        //Dir
  171.                                     
  172.                                      LCD1602_DisplayString(0xc0,ucForum5);        //Cyc
  173.                                   
  174.                                   

  175.                                   switch(z)
  176.                                   {
  177.                                           case 1:       
  178.                                                 conversion(NO_b);
  179.                                                         LCD1602_WriteInformation(0x84,0);          //计数
  180.                                                         LCD1602_WriteInformation(ten,1);
  181.                                                         LCD1602_WriteInformation(0x85,0);
  182.                                                     LCD1602_WriteInformation(bits,1);  
  183.                                         break;
  184.                                         case 2:
  185.                                                 if(buff == 1)                                                  //方向
  186.                                                         {
  187.                                                           LCD1602_WriteInformation(0x8c,0);          
  188.                                                           LCD1602_WriteInformation(0x30,1);
  189.                                                           LCD1602_WriteInformation(0x8d,0);
  190.                                                           LCD1602_WriteInformation(1+0x30,1);
  191.                                                         }
  192.                                             if(buff == 2)
  193.                                                         {
  194.                                                           LCD1602_WriteInformation(0x8c,0);
  195.                                                           LCD1602_WriteInformation(1+0x30,1);
  196.                                                           LCD1602_WriteInformation(0x8d,0);
  197.                                                           LCD1602_WriteInformation(0x30,1);
  198.                                                         }   
  199.                                         break;
  200. //                                          case 3:       
  201. //                                                flag_buf=1;                                                                           //角度
  202. //                                                angle_zhi();
  203. //                                                        LCD1602_WriteInformation(0xc4,0);
  204. //                                                        LCD1602_WriteInformation((power/10)+0x30,1);
  205. //                                                        LCD1602_WriteInformation(0xc5,0);
  206. //                                                        LCD1602_WriteInformation(((power%10))+0x30,1);  
  207. //                                                        conversion(power);
  208. //                                                        LCD1602_WriteInformation(0xc4,0);
  209. //                                                        LCD1602_WriteInformation(ten,1);
  210. //                                                        LCD1602_WriteInformation(0xc5,0);
  211. //                                                        LCD1602_WriteInformation(bits,1);

  212. //                                                        LCD1602_WriteInformation(0xc6,0);
  213. //                                                        LCD1602_WriteInformation(time/1000+0x30,1);
  214. //                                                        LCD1602_WriteInformation(0xc7,0);
  215. //                                                        LCD1602_WriteInformation(time/100%10+0x30,1);
  216. //                                                        LCD1602_WriteInformation(0xcd,0);
  217. //                                                        LCD1602_WriteInformation(time/10%10+0x30,1);
  218. //                                                        LCD1602_WriteInformation(0xcf,0);
  219. //                                                        LCD1602_WriteInformation(time%10+0x30,1);

  220. //                                        break;
  221.                                         case 3:                                                                                   //周期
  222.                                                 Cyc=NO_b/2;
  223.                                                         conversion(Cyc);
  224.                                                         LCD1602_WriteInformation(0xc4,0);
  225.                                                         LCD1602_WriteInformation(ten,1);
  226.                                                         LCD1602_WriteInformation(0xc5,0);
  227.                                                         LCD1602_WriteInformation(bits,1);
  228.                                         break;
  229.                                  }
  230.     }
  231. }

  232. //main函数
  233. void main()
  234. {
  235.    
  236.     hj_c52();  //HJ-C52复位函数
  237.         LCD1602_Init();          //液晶初始化
  238.         TMOD=0x01;   //
  239.         TH0=0;
  240.         TL0=0;

  241.         while(1)                 //程序循环
  242.         {
  243.                    key_control();
  244.                 screen_0();
  245.                 screen_1();
  246.                 screen_2();
  247.                 direction();
  248.                 if(k1 == 0)
  249.                 {
  250.                                 Delay(20);
  251.                                 if(k1==0)
  252.                                 {
  253.                                         flag_buf++;
  254.                                         while(k1 != 1);
  255.                                 }
  256.                 }
  257.                 while(flag_buf==1)
  258.        {
  259.           if(catch_A == 0)
  260.               {
  261.                     TH0 = 0;
  262.                         TL0 = 0;
  263.                         TR0 = 1;        //定时器T0计数
  264.                        
  265.                         while(catch_B == 1)
  266.                         {
  267.                                  if(TF0 == 1)
  268.                                  {
  269.                                    buft++;
  270.                                    TF0 = 0;
  271.                                  }
  272.                         }
  273.                         TR0 = 0        ;        //定时器T0停止
  274.                         time=((TH0*256) + TL0 + (65536*buft))/10;           //ms为单位
  275.                         time_buff=time/100.0;
  276.                         power=(int)((-(0.6566*time_buff*time_buff)+28.75*time_buff+13.76)/(time_buff-8.925))+0.5;
  277.                         conversion(power);
  278.                         LCD1602_WriteInformation(0x84,0);
  279.                         LCD1602_WriteInformation(ten,1);
  280.                         LCD1602_WriteInformation(0x85,0);
  281.                         LCD1602_WriteInformation(bits,1);
  282.                         TH0 = 0;
  283.                         TL0 = 0;
  284.                         time = 0;
  285.                         buft = 0;
  286.              }
  287.                          if(k1 == 0)
  288.                         {
  289.                                 Delay(20);
  290.                                 if(k1==0)
  291.                                 {
  292.                                         flag_buf++;
  293.                                         while(k1 != 1);
  294.                                 }
  295.                         }
  296.   }
  297.     if(flag_buf==2)
  298.         {
  299.            flag_buf=0;
  300.            LCD1602_WriteInformation(0x01,0);
  301.        
  302.         }
  303.         }
  304.        
  305. }
  306.                





  307. /******************************************************************************
  308. 函数名称:LCD1602_CheckBusy
  309. 函数功能:忙检测
  310. *******************************************************************************/
  311. void LCD1602_CheckBusy(void)               
  312. {
  313.         unsigned char i = 255;
  314.         LCDPORT = 0xFF;  //读之前先置位,准备读取IO口数据
  315.         LCD1602_RS = 0;
  316.         LCD1602_RW = 1;         //使液晶处于读数据状态
  317.         LCD1602_EN = 1;         //使能液晶,高电平有效
  318.         while((i--) && (LCDPORT & 0x80));        //忙检测
  319.         LCD1602_EN = 0;
  320. }

  321. /******************************************************************************
  322. 函数名称:LCD1602_WriteInformation
  323. 函数功能:向LCD1602液晶写入数据或者命令
  324. ********************************************************************/
  325. void LCD1602_WriteInformation(unsigned char ucData,bit bComOrData)         
  326. {
  327.         LCD1602_CheckBusy();         //在写入数据或者命令前先进行忙检测
  328.         LCDPORT = ucData;                 //先将数据或者命令送至IO
  329.         LCD1602_RS = bComOrData;        //确定是写入数据还是写命令
  330.         LCD1602_RW = 0;                //使液晶处于写入信息状态
  331.         LCD1602_EN = 1;                //使能液晶,高电平有效
  332.         LCD1602_EN = 0;
  333. }

  334. /******************************************************************************
  335. 函数名称:LCD1602_Init
  336. 函数功能:液晶初始化函数
  337. *******************************************************************************/
  338. void LCD1602_Init(void)                 
  339. {
  340.         LCD1602_WriteInformation(0x38,0);
  341.         Delay(200);
  342.         LCD1602_WriteInformation(0x38,0);
  343.         Delay(100);
  344.         LCD1602_WriteInformation(0x38,0);
  345.         Delay(100);
  346.         LCD1602_WriteInformation(0x38,0);         //写入命令,5x7点阵工作方式,8位数据接口
  347.         Delay(100);
  348.         LCD1602_WriteInformation(0x0c,0);        //显示设置,开显示,光标不显示,不闪烁
  349.         Delay(20);
  350.         LCD1602_WriteInformation(0x01,0);        //清屏指令
  351.         Delay(20);
  352. }

  353. /******************************************************************************
  354. 函数名称:LCD1602_MoveToPosition
  355. 函数功能:将液晶的光标移动到指定的位置
  356. *******************************************************************************/
  357. void LCD1602_MoveToPosition(unsigned char x,unsigned char y)       
  358. {
  359.         if(0 == x)
  360.                 LCD1602_WriteInformation((0x80 | y),0);           //光标定位到第一行的y列
  361.         if(1 == x)
  362.                 LCD1602_WriteInformation((0xC0 | y),0);           //光标定义到第二行的y列
  363. }

  364. /******************************************************************************
  365. 函数名称:LCD1602_DisplayOneCharOnAddr
  366. 函数功能:在指定的位置上显示指定的字符
  367. *******************************************************************************/
  368. void LCD1602_DisplayOneCharOnAddr(unsigned char x,unsigned char y,unsigned char ucData)
  369. {
  370.         LCD1602_MoveToPosition(x,y);   //光标位置
  371.         LCD1602_WriteInformation(ucData,1);          //写入数据
  372. }

  373. /******************************************************************************
  374. 函数名称:LCD1602_DisplayString
  375. 函数功能:显示字符串
  376. *******************************************************************************/
  377. void LCD1602_DisplayString(unsigned char addr,unsigned char *ucStr)       
  378. {
  379.     LCD1602_WriteInformation(addr,0);
  380.         while(*ucStr != '\0')           //字符串结束之前,循环显示
  381.         {
  382.                  LCD1602_WriteInformation(*ucStr,1);         //依次写入每一个字符
  383.                  ucStr++;                                                                 //指针增加
  384.         }
  385. }

  386. /******************************************************************************
  387. 函数名称:Delay
  388. 函数功能:延时函数
  389. *******************************************************************************/
  390. void Delay(unsigned int uiCount)
  391. {
  392.         unsigned char j = 244;
  393.         for(;uiCount > 0;uiCount--) while(--j);       
  394. }


  395. /******************************************************************/
  396. // 以下为HJ-C52复位函数
  397. /******************************************************************/
  398.     void hj_c52()
  399.     {
  400.     LCD1602=0;//关掉LCD1602 以免影响点阵管IO口电评
  401.     DS1302=0;//关掉DS1302 以免影响点阵管IO口电评
  402.     CS88=0;     //关掉8X8点阵显示
  403.     WE=1;  
  404.     P0=0Xff;
  405.     WE=0;        //关掉数码管显示
  406.     CS88=0;      //关掉8X8点阵显示
  407.     }
复制代码

所有资料51hei提供下载:
原理图.rar (436.93 KB, 下载次数: 18)
M题程序.rar (60.15 KB, 下载次数: 23)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:447051 发表于 2019-1-26 10:47 | 只看该作者
看起来不错啊!有空试试看!
回复

使用道具 举报

板凳
ID:473161 发表于 2019-1-26 17:11 | 只看该作者
谢谢楼主
回复

使用道具 举报

地板
ID:492460 发表于 2019-3-31 13:52 | 只看该作者

楼主,角度有问题啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表