久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3149|回復: 1
打印 上一主題 下一主題
收起左側

基于STC15W的風力擺控制系統設計 帶視頻與程序(電賽測控題)

[復制鏈接]
跳轉到指定樓層
樓主
風力擺視頻演示:


元件清單:



單片機源程序如下:
  1. //========================================================================
  2. //        城建學院電子實驗室
  3. //        修改日期2017.07.30
  4. //        版本V1.0
  5. //========================================================================
  6. //特別聲明:此程序
  7. //         
  8. //
  9. //
  10. //                                 MCU工作頻率:24MHz
  11. //=========================================================================

  12. #include <STC15F2K60S2.h>        //STC15系列通用頭文件
  13. #include <intrins.h>                //STC特殊命令符號聲明
  14. #include <MPU6050.H>                //MPU6050數字陀螺儀
  15. #include <STC15W4KPWM.H>        //單片機所有IO口初始化-PWM口初始化
  16. #include <IMU.H>                        
  17. #include <math.H>

  18. bit busy,flag=0;
  19. int ich1=0,ich2=0,ich3=0,ich4=0,ich5=0,ich6=0;                //匿名科技上位機
  20. //==================================================//
  21. //  PID算法變量
  22. //==================================================//
  23. int speed1=0,speed2=0,speed3=0,speed4=0;//電機速度參數
  24. int PWM1=0,PWM2=0,PWM3=0,PWM4=0;                //加載至PWM模塊的參數
  25. float Angle=0;
  26. char mode=1;
  27. //*****************角度參數*************************************************
  28. float Last_Angle_gx=0;                                          //外上一次陀螺儀數據
  29. float Last_Angle_gy=0;                                                  //上一次陀螺儀數據
  30. double Gyro_y=0,Gyro_x=0,Gyro_z=0;        //Y軸陀螺儀數據暫存
  31. double Accel_x=0,Accel_y=0,Accel_z=0;          //X軸加速度值暫存
  32. double Angle_ax=0,Angle_ay=0,Angle_az=0;  //由加速度計算的加速度(弧度制)
  33. double Angle_gy=0,Angle_gx=0,Angle_gz=0;  //由角速度計算的角速率(角度制)
  34. float data AngleX=0,AngleY=0;                                  //四元數解算出的歐拉角
  35. double Ax=0,Ay=0;                    //加入遙控器控制量后的角度
  36. double Vx=0,Vy=0;                    //加入遙控器控制量后的角度
  37. float ierrorx=0,ierrory=0; //誤差積分 積分根據情況,目前測試情況不需要積分
  38. //****************姿態處理和PID*********************************************
  39. float FR1=0,FR2=0;            //xy軸期望角度
  40. float  data PID_Output;                                //PID最終輸出量

  41. float xdata Last_Ax=0;
  42. float xdata Last_Ay=0;
  43. float xdata Last_vx=0;
  44. float xdata Last_vy=0;


  45. float R=0.20f;//擺幅半長 (m)
  46. unsigned int time=0;
  47. float A1=0,A2=0;

  48. sbit key1=P2^0;
  49. sbit key2=P2^1;
  50. sbit key3=P2^2;
  51. sbit key4=P2^3;




  52. //==================================================//
  53. //   PID 手動微調參數值
  54. //==================================================//
  55. // P值適當調,D值可以給很大!!! P值過大系統就會蕩

  56. #define Out_XP        4.5f        
  57. #define        Out_XI  0.0f         //I根據情況,目前不需要I
  58. #define        Out_XD  2200.0f        

  59. #define        Out_YP        Out_XP
  60. #define        Out_YI        Out_XI
  61. #define        Out_YD        Out_XD

  62. #define PI 3.15459
  63. #define T 1601//單擺周期(ms) 根據單擺公式用桿長計算

  64. //--------------------------------------------------//
  65. //  PID算法飛控自平衡 函數
  66. //--------------------------------------------------//
  67. void Flight(void)interrupt 1
  68. {
  69.     time+=10;
  70.         Gyro_x = GetData(GYRO_XOUT_H);//讀出 X軸陀螺儀數據
  71.         Gyro_y = GetData(GYRO_YOUT_H);//讀出 Y軸陀螺儀數據
  72.         Gyro_z = GetData(GYRO_ZOUT_H);//讀出 Z軸陀螺儀數據        
  73.         Accel_y= GetData(ACCEL_YOUT_H);//讀出 X軸加速度數據
  74.         Accel_x= GetData(ACCEL_XOUT_H);//讀出 Y軸陀螺儀數據                  
  75.         Accel_z= GetData(ACCEL_ZOUT_H);//讀出 Z軸加速度數據
  76.         //姿態數據算法 (借鑒STC官方算法)
  77.         Last_Angle_gx=Angle_gx;   //儲存上一次角速度數據
  78.         Last_Angle_gy=Angle_gy;          //儲存上一次角速度數據
  79.         Angle_ax=(Accel_x)/8192;  //加速度處理
  80.         Angle_az=(Accel_z)/8192;  //加速度量程 +-4g/S
  81.         Angle_ay=(Accel_y)/8192;  //轉換關系   8192LSB/g
  82.         Angle_gx=(Gyro_x)/65.5+4;   //陀螺儀處理
  83.         Angle_gy=(Gyro_y)/65.5+3;   //陀螺儀量程 +-500度/S
  84.         Angle_gz=(Gyro_z)/65.5;   //轉換關系65.5LSB/度

  85. //***********************************四元數解算***********************************
  86.         IMUupdate(Angle_gx*0.0174533,Angle_gy*0.0174533,Angle_gz*0.0174533,Angle_ax,Angle_ay,Angle_az);//0.174533為PI/180 目的是將角度轉弧度

  87. //****平衡算法***********************************************************************



  88.     FR1=A1*sin(2*PI*time/T);        //X軸控制
  89.         if(mode==3) FR2=A2*cos(2*PI*time/T); //Y軸控制
  90.         else if(mode==4) FR2=A2*cos(2*PI*time/(T/2)); //Y軸控制
  91.         else   FR2=A2*sin(2*PI*time/T); //Y軸控制
  92.         

  93.         if(time >= 1601)time=0;


  94. //************** MPU6050 X軸指向 ***********************************************************
  95.     Ax=FR1-(AngleX+2);   //X軸偏差

  96.         ich1=Ax;
  97.         ich2=Ay;
  98.         ich3=0;                 
  99.         ich4=0;
  100.         ich5=0;
  101.         ich6=0;

  102.         ierrorx +=Last_Ax-Ax;

  103.     PID_Output = Ax*Out_XP +Out_XI*ierrorx+(Last_Ax-Ax)*Out_XD;        //PID

  104.         if(PID_Output >  1000)        PID_Output =  1000;  //輸出量限幅
  105.         if(PID_Output < -1000)        PID_Output = -1000;
  106.         
  107.         speed1 =0+ PID_Output;        speed3 =0- PID_Output;

  108.         Last_Ax=Ax;

  109. //**************MPU6050 Y軸指向**************************************************

  110.           Ay=FR2-(AngleY);  //Y軸偏差

  111.         ierrory +=Last_Ay-Ay;

  112.     PID_Output = Ay*Out_YP +Out_YI*ierrory+(Last_Ay-Ay)*Out_XD;        //PID

  113.         if(PID_Output >  1000)        PID_Output =  1000;  //輸出量限幅
  114.         if(PID_Output < -1000)        PID_Output = -1000;
  115.                
  116.         speed2 =0+ PID_Output;        speed4 = 0- PID_Output;
  117.                         
  118.         Last_Ay=Ay;           

  119. //************************PID控制數值***************************************************
  120. //**************將速度參數加載至PWM模塊*************************************************        
  121.         //速度參數控制,防止超過PWM參數范圍0-1000
  122.         if(speed1>1000)speed1=1000;else if(speed1<0)speed1=0;PWM1=(speed1);                // 5
  123.         if(speed2>1000)speed2=1000;else if(speed2<0)speed2=0;PWM2=(speed2);                // 3
  124.         if(speed3>1000)speed3=1000;else if(speed3<0)speed3=0;PWM3=(speed3);                // 4
  125.         if(speed4>1000)speed4=1000;else if(speed4<0)speed4=0;PWM4=(speed4);                // 2   

  126.         PWM(1000-PWM1,1000-PWM2,1000-PWM3,1000-PWM4);
  127. }
  128.          
  129. //--------------------------------------------------//
  130. //  時間延時 函數
  131. //--------------------------------------------------//
  132. void Delay(unsigned int x)
  133. {
  134.         unsigned int i,j;
  135.     for(i=0;i<x;i++)
  136.     for(j=0;j<250;j++);
  137. }
  138. //--------------------------------------------------//
  139. //  定時器0 初始化函數 V2.0
  140. //--------------------------------------------------//


  141. void Timer0Init(void)        //10毫秒@24.000MHz
  142. {
  143.         TR0 = 0;
  144.         AUXR &= 0x7F;        //定時器時鐘12T模式
  145.         TMOD &= 0xF0;        //設置定時器模式
  146.         IE  = 0x82;
  147.         TL0 = 0xE0;                //設置定時初值
  148.         TH0 = 0xB1;                //設置定時初值
  149.         TF0 = 0;                //清除TF0標志
  150.         TR0 = 1;                //定時器0開始計時

  151. }

  152. //--------------------------------------------------//
  153. //  上位機串口 初始化函數 V2.0
  154. //  波特率115200,24MHZ
  155. //--------------------------------------------------//

  156. void Usart_Init()  //波特率115200,24MHZ
  157. {
  158.     SCON = 0x50;        
  159.         AUXR |= 0x40;               
  160.         AUXR &= 0xFE;               
  161.         TMOD &= 0x0F;        
  162.         TL1 = 0xcc;               
  163.         TH1 = 0xFF;               
  164.         ET1 = 0;               
  165.         TR1 = 1;        
  166. }

  167. void SendData(unsigned char dat)
  168. {
  169.     while (busy);            
  170.      busy = 1;
  171.     SBUF = dat;               
  172. }
  173. void Send(int Ax,int Ay,int Az,int Gx,int Gy,int Gz)
  174. {
  175.         unsigned char sum=0;
  176.         ES = 1;  
  177.         SendData(0xAA);   
  178.         SendData(0xAA);   
  179.         SendData(0x02);   
  180.         SendData(12);     
  181.         SendData(Ax>>8);     
  182.         SendData(Ax);  
  183.         SendData(Ay>>8);
  184.         SendData(Ay);
  185.         SendData(Az);
  186.         SendData(Az>>8);
  187.         SendData(Gx);
  188.         SendData(Gx>>8);
  189.         SendData(Gy);
  190.         SendData(Gy>>8);
  191.         SendData(Gz);
  192.         SendData(Gz>>8);
  193.         sum+=0xAA;sum+=0xAA;sum+=0x02;sum+=12;
  194.         sum+=Ax>>8;sum+=Ax;sum+=Ay>>8;sum+=Ay;sum+=Az>>8;sum+=Az;
  195.         sum+=Gx>>8;sum+=Gx;sum+=Gy>>8;sum+=Gy;sum+=Gz>>8;sum+=Gz;
  196.         SendData(sum);  
  197.         ES = 0;   
  198. }


  199. void mode1()
  200. {        
  201.         A1=0;
  202.         A2=0;
  203. }

  204. void mode2()
  205. {        
  206.         A1=(atan(R*cos(PI/180*Angle)/0.75))* 57.2957795f;//根據擺幅算出角度A         0.75m擺長
  207.         A2=(atan(R*sin(PI/180*Angle)/0.75))* 57.2957795f;//根據擺幅算出角度A

  208.         /*if(0==key3)
  209.         {
  210.                 Delay(10);
  211.                 if(key3==0) Angle+=15;
  212.                 if(Angle>=360) Angle=0;
  213.                 while(!key1);
  214.         }
  215.         if(key4==0)
  216.         {
  217.                 Delay(10);
  218.                 if(key4==0) Angle-=15;
  219.                 if(Angle<=-360) Angle=0;
  220.                 while(!key4);
  221.         }*/
  222. }

  223. void mode3()
  224. {        
  225.         A1=(atan(R*cos(PI/180*Angle)/0.75))* 57.2957795f;//根據擺幅算出角度A         0.75m擺長
  226.         /*if(key3==0)
  227.         {
  228.                 Delay(10);
  229.                 if(key3==0) flag=~flag;
  230.                 while(!key3);
  231.         }*/
  232.         if(!flag)  A2=A1;
  233.         else      A2=0-A1;
  234. }

  235. void mode4()
  236. {        
  237.         A1=(atan(R*cos(PI/180*Angle)/0.75))* 57.2957795f;//根據擺幅算出角度A         0.75m擺長
  238.         A2=A1/2;
  239. }

  240. //--------------------------------------------------//
  241. //  程序 主函數
  242. //--------------------------------------------------//
  243. void main(void)
  244. {
  245.         PWMGO();                //初始化PWM
  246.         Usart_Init();//串口初始化
  247.         Delay(10);    // 延時 100
  248.         InitMPU6050();        //初始化MPU-6050
  249.         Delay(100);    // 延時 100
  250.         Timer0Init();        //初始化定時器        
  251.         EA = 1;
  252.         while(1)
  253.         {
  254.                 Send(ich1,ich2,ich3,ich4,ich5,ich6);  //串口發送數據                                
  255.                 Delay(1);
  256.                 /*if(key1==0)
  257. ……………………

  258. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:
風力擺桿.zip (95.8 KB, 下載次數: 42)


評分

參與人數 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:1 發表于 2017-9-6 17:01 | 只看該作者
MPU-6050.C
  1. //========================================================================
  2. //        城建學院電子實驗室
  3. //        修改日期2017.07.30
  4. //        版本V1.0
  5. //========================================================================
  6. //特別聲明:此程序
  7. //         
  8. //
  9. //
  10. //                                 MCU工作頻率:24MHz
  11. //=========================================================================
  12. #include <STC15F2K60S2.h>        //STC15F2K60S2 STC15系列通用頭文件
  13. #include <intrins.h>
  14. #include <MPU6050.H>

  15. sbit    SCL=P3^5;                        //IIC時鐘引腳定義
  16. sbit    SDA=P3^4;                        //IIC數據引腳定義

  17. typedef unsigned char uchar;
  18. typedef unsigned char uint;       
  19. void  InitMPU6050();                //初始化MPU6050
  20. void  Delay2us();
  21. void  I2C_Start();
  22. void  I2C_Stop();
  23. bit   I2C_RecvACK();
  24. void  I2C_SendByte(uchar dat);
  25. uchar I2C_RecvByte();
  26. void  I2C_ReadPage();
  27. void  I2C_WritePage();
  28. uchar Single_ReadI2C(uchar REG_Address);                                        //讀取I2C數據
  29. void  Single_WriteI2C(uchar REG_Address,uchar REG_data);        //向I2C寫入數據
  30. //I^C時序中延時設置,具體參見各芯片的數據手冊  6050推薦最小1.3us 但是會出問題,這里延時實際1.9us左右
  31. void Delay2us()       
  32. {
  33.         unsigned char i;
  34.         i = 11;
  35.         while (--i);
  36. }
  37. //**************************************
  38. //I2C起始信號
  39. //**************************************
  40. void I2C_Start()
  41. {
  42.     SDA = 1;                    //拉高數據線
  43.     SCL = 1;                    //拉高時鐘線
  44.     Delay2us();                 //延時
  45.     SDA = 0;                    //產生下降沿
  46.     Delay2us();                 //延時
  47.     SCL = 0;                    //拉低時鐘線
  48. }
  49. //**************************************
  50. //I2C停止信號
  51. //**************************************
  52. void I2C_Stop()
  53. {
  54.     SDA = 0;                    //拉低數據線
  55.     SCL = 1;                    //拉高時鐘線
  56.     Delay2us();                 //延時
  57.     SDA = 1;                    //產生上升沿
  58.     Delay2us();                 //延時
  59. }
  60. //**************************************
  61. //I2C接收應答信號
  62. //**************************************
  63. bit I2C_RecvACK()
  64. {
  65.     SCL = 1;                    //拉高時鐘線
  66.     Delay2us();                 //延時
  67.     CY = SDA;                   //讀應答信號
  68.     SCL = 0;                    //拉低時鐘線
  69.     Delay2us();                 //延時
  70.     return CY;
  71. }
  72. //**************************************
  73. //向I2C總線發送一個字節數據
  74. //**************************************
  75. void I2C_SendByte(uchar dat)
  76. {
  77.     uchar i;
  78.     for (i=0; i<8; i++)         //8位計數器
  79.     {
  80.         dat <<= 1;              //移出數據的最高位
  81.         SDA = CY;               //送數據口
  82.         SCL = 1;                //拉高時鐘線
  83.         Delay2us();             //延時
  84.         SCL = 0;                //拉低時鐘線
  85.         Delay2us();             //延時
  86.     }
  87.     I2C_RecvACK();
  88. }
  89. //**************************************
  90. //從I2C總線接收一個字節數據
  91. //**************************************
  92. uchar I2C_RecvByte()
  93. {
  94.     uchar i;
  95.     uchar dat = 0;
  96.     SDA = 1;                    //使能內部上拉,準備讀取數據,
  97.     for (i=0; i<8; i++)         //8位計數器
  98.     {
  99.         dat <<= 1;
  100.         SCL = 1;                //拉高時鐘線
  101.         Delay2us();             //延時
  102.         dat |= SDA;             //讀數據
  103.         SCL = 0;                //拉低時鐘線
  104.         Delay2us();             //延時
  105.     }
  106.     return dat;
  107. }
  108. //**************************************
  109. //向I2C設備寫入一個字節數據
  110. //**************************************
  111. void Single_WriteI2C(uchar REG_Address,uchar REG_data)
  112. {
  113.     I2C_Start();                  //起始信號
  114.     I2C_SendByte(SlaveAddress);   //發送設備地址+寫信號
  115.     I2C_SendByte(REG_Address);    //內部寄存器地址,
  116.     I2C_SendByte(REG_data);       //內部寄存器數據,
  117.     I2C_Stop();                   //發送停止信號
  118. }
  119. //**************************************
  120. //從I2C設備讀取一個字節數據
  121. //**************************************
  122. uchar Single_ReadI2C(uchar REG_Address)
  123. {
  124.         uchar REG_data;
  125.         I2C_Start();                   //起始信號
  126.         I2C_SendByte(SlaveAddress);    //發送設備地址+寫信號
  127.         I2C_SendByte(REG_Address);     //發送存儲單元地址,從0開始
  128.         I2C_Start();                   //起始信號
  129.         I2C_SendByte(SlaveAddress+1);  //發送設備地址+讀信號
  130.         REG_data=I2C_RecvByte();       //讀出寄存器數據
  131.        
  132.         SDA = 1;                    //寫應答信號
  133.         SCL = 1;                    //拉高時鐘線
  134.         Delay2us();                 //延時
  135.         SCL = 0;                    //拉低時鐘線
  136.         Delay2us();                 //延時
  137.        
  138.         I2C_Stop();                    //停止信號
  139.         return REG_data;
  140. }

  141. //**************************************
  142. //初始化MPU6050
  143. //**************************************
  144. void InitMPU6050()
  145. {
  146.         Single_WriteI2C(PWR_MGMT_1, 0x00);        //解除休眠狀態
  147.         Single_WriteI2C(SMPLRT_DIV, 0x07);  //陀螺儀125hz
  148.         Single_WriteI2C(CONFIG, 0x04);      //21HZ濾波 延時A8.5ms G8.3ms  此處取值應相當注意,延時與系統周期相近為宜
  149.         Single_WriteI2C(GYRO_CONFIG, 0x08); //陀螺儀500度/S 65.5LSB/g
  150.         Single_WriteI2C(ACCEL_CONFIG, 0x08);//加速度+-4g  8192LSB/g
  151. }
  152. //**************************************
  153. //合成數據
  154. //**************************************
  155. int GetData(uchar REG_Address)
  156. {
  157.         char H,L;
  158.         H=Single_ReadI2C(REG_Address);
  159.         L=Single_ReadI2C(REG_Address+1);
  160.         return (H<<8)+L;   //合成數據
  161. }

  162.        
復制代碼
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品国产精品国产专区不片 | m豆传媒在线链接观看 | 亚洲一区国产 | 欧美不卡一区 | 免费毛片网站在线观看 | 美女爽到呻吟久久久久 | 成人亚洲精品久久久久软件 | 午夜精品久久久 | 超碰在线人 | a级片在线 | 亚洲一区 中文字幕 | 亚洲精品中文字幕 | 99久久精品国产毛片 | 自拍偷拍亚洲一区 | 欧美一二三 | 欧美精品一区二区三区蜜桃视频 | 欧美jizzhd精品欧美巨大免费 | 欧美精品一二区 | 精品国产乱码一区二区三区 | 欧美不卡视频一区发布 | 精品国产伦一区二区三区观看方式 | 九九激情视频 | 欧美日韩中文字幕在线播放 | 国产成人综合一区二区三区 | 亚洲欧美另类在线 | 情侣酒店偷拍一区二区在线播放 | 国产精品99一区二区 | 久久亚洲国产精品 | 91亚洲精品在线 | 91成人在线| 国产日韩欧美激情 | 国产成人精品午夜视频免费 | 国产精品av久久久久久久久久 | 欧美激情亚洲 | 91在线综合| 日韩欧美精品一区 | 亚洲综合视频一区 | 国产精品久久精品 | 爱操av | 国产精品一区一区 | 欧美成人久久 |