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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

MPU6050用51單片機角度融合怎么計算?

[復制鏈接]
跳轉到指定樓層
樓主
ID:954170 發表于 2021-10-19 17:08 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
50黑幣
我把mpu6050的計算程序移植到51單片機上面,程序沒有報錯,卻計算不出角度,煩請指導一下,或給出正確的計算函數程序如下:
  1. #include <REG52.H>
  2. #include <math.h>    //Keil library
  3. #include <stdio.h>   //Keil library
  4. #include <INTRINS.H>
  5. typedef unsigned char  uchar;
  6. typedef unsigned short ushort;
  7. typedef unsigned int   uint;
  8. typedef unsigned char  u8;
  9. //--聲明一些需要使用的變量--//
  10. uchar MPU6050_DATA[14];
  11. int Gyro_x,Gyro_y,Gyro_z;
  12. int Gyro_angle_x=0,Gyro_angle_y=0,Gyro_angle_z=0;
  13. int Acc_x,Acc_y,Acc_z;
  14. int Temp;

  15. int                xdata g_x=0,g_y=0,g_z=0;                                        //陀螺儀矯正參數
  16. float        xdata a_x=0,a_y=0;                                                        //角度矯正參數
  17. float        data  AngleX=0,AngleY=0;                                        //四元數解算出的歐拉角
  18. float        xdata Angle_gx=0,Angle_gy=0,Angle_gz=0;                //由角速度計算的角速率(角度制)
  19. float        xdata Angle_ax=0,Angle_ay=0,Angle_az=0;                //由加速度計算的加速度(弧度制)
  20. //****************************************
  21. // 定義51單片機端口
  22. //****************************************
  23. #define DataPort P0                //LCD1602數據端口
  24. sbit    SCL=P1^1;                        //IIC時鐘引腳定義
  25. sbit    SDA=P1^0;                        //IIC數據引腳定義
  26. sbit    LCM_RS=P3^5;                //LCD1602命令端口
  27. sbit    LCM_RW=P3^6;                //LCD1602命令端口
  28. sbit    LCM_EN=P3^4;                //LCD1602命令端口

  29. //****************************************
  30. // 定義MPU6050內部地址
  31. //****************************************
  32. #define        SMPLRT_DIV                0x19        //陀螺儀采樣率,典型值:0x07(125Hz)
  33. #define        CONFIG                        0x1A        //低通濾波頻率,典型值:0x06(5Hz)
  34. #define        GYRO_CONFIG                0x1B        //陀螺儀自檢及測量范圍,典型值:0x18(不自檢,2000deg/s)
  35. #define        ACCEL_CONFIG        0x1C        //加速計自檢、測量范圍及高通濾波頻率,典型值:0x01(不自檢,2G,5Hz)
  36. #define        ACCEL_XOUT_H        0x3B
  37. #define        ACCEL_XOUT_L        0x3C
  38. #define        ACCEL_YOUT_H        0x3D
  39. #define        ACCEL_YOUT_L        0x3E
  40. #define        ACCEL_ZOUT_H        0x3F
  41. #define        ACCEL_ZOUT_L        0x40
  42. #define        TEMP_OUT_H                0x41
  43. #define        TEMP_OUT_L                0x42
  44. #define        GYRO_XOUT_H                0x43
  45. #define        GYRO_XOUT_L                0x44
  46. #define        GYRO_YOUT_H                0x45
  47. #define        GYRO_YOUT_L                0x46
  48. #define        GYRO_ZOUT_H                0x47
  49. #define        GYRO_ZOUT_L                0x48
  50. #define        PWR_MGMT_1                0x6B        //電源管理,典型值:0x00(正常啟用)
  51. #define        WHO_AM_I                        0x75        //IIC地址寄存器(默認數值0x68,只讀)
  52. #define        SlaveAddress        0xD0        //IIC寫入時的地址字節數據,+1為讀取
  53. //****************************************
  54. //定義類型及變量
  55. //****************************************
  56. uchar dis[4];                                                        //顯示數字(-511至512)的字符數組
  57. int        dis_data;                                                //變量
  58. //int        Temperature,Temp_h,Temp_l;        //溫度及高低位數據
  59. //****************************************
  60. //函數聲明
  61. //****************************************
  62. void  delay(unsigned int k);                                                                                //延時
  63. //LCD相關函數
  64. void  InitLcd();                                                                                                                //初始化lcd1602
  65. void  lcd_printf(uchar *s,int temp_data);
  66. void  WriteDataLCM(uchar dataW);                                                                        //LCD數據
  67. void  WriteCommandLCM(uchar CMD,uchar Attribc);                                //LCD指令
  68. void  DisplayOneChar(uchar X,uchar Y,uchar DData);                        //顯示一個字符
  69. void  DisplayListChar(uchar X,uchar Y,uchar *DData,L);        //顯示字符串
  70. //MPU6050操作函數
  71. void  InitMPU6050();                                                                                                        //初始化MPU6050
  72. void  Delay5us();
  73. void  I2C_Start();
  74. void  I2C_Stop();
  75. void  I2C_SendACK(bit ack);
  76. bit   I2C_RecvACK();
  77. void  I2C_SendByte(uchar dat);
  78. uchar I2C_RecvByte();
  79. void  I2C_ReadPage();
  80. void  I2C_WritePage();
  81. void  display_ACCEL_x();
  82. void  display_ACCEL_y();
  83. void  display_ACCEL_z();
  84. uchar Single_ReadI2C(uchar REG_Address);                                                //讀取I2C數據
  85. void  Single_WriteI2C(uchar REG_Address,uchar REG_data);//向I2C寫入數據
  86. void Delay2us(void)
  87. {
  88.         u8 i;
  89.         i = 11;                // @24MHZ, 6 + 33 = 39T, 1.625us
  90.         while (--i);
  91. }
  92. void Read_MPU6050(u8 *buf)
  93. {
  94.         u8        i;
  95.         
  96.         I2C_Start();                  //起始信號
  97.         I2C_SendByte(SlaveAddress);   //發送設備地址+寫信號
  98.         I2C_SendByte(ACCEL_XOUT_H);    //內部寄存器地址,
  99.         I2C_Start();                   //起始信號
  100.         I2C_SendByte(SlaveAddress+1);  //發送設備地址+讀信號
  101.         for(i=0; i<13; i++)
  102.         {
  103.                 buf[i] = I2C_RecvByte();       //讀出寄存器數據
  104.                 SDA = 0;                    //寫應答信號
  105.                 SCL = 1;                    //拉高時鐘線
  106.                 Delay2us();                 //延時
  107.                 SCL = 0;                    //拉低時鐘線
  108.                 Delay2us();                 //延時
  109.         }
  110.                 buf[i] = I2C_RecvByte();        //最后一個字節
  111.                 SDA = 1;                    //寫非應答信號
  112.                 SCL = 1;                    //拉高時鐘線
  113.                 Delay2us();                 //延時
  114.                 SCL = 0;                    //拉低時鐘線
  115.                 Delay2us();                 //延時
  116.         I2C_Stop();                    //停止信號
  117. }



  118. //****************************************
  119. //整數轉字符串
  120. //****************************************

  121. void lcd_printf(uchar *s,int temp_data)
  122. {
  123.         if(temp_data<0)
  124.         {
  125.                 temp_data=-temp_data;
  126.                 *s='-';
  127.         }
  128.         else *s=' ';
  129.         *++s =temp_data/100+0x30;
  130.         temp_data=temp_data%100;     //取余運算
  131.         *++s =temp_data/10+0x30;
  132.         temp_data=temp_data%10;      //取余運算
  133.         *++s =temp_data+0x30;
  134. }
  135. //****************************************
  136. //延時
  137. //****************************************
  138. void delay(unsigned int k)
  139. {
  140.         unsigned int i,j;
  141.         for(i=0;i<k;i++)
  142.         {
  143.                 for(j=0;j<121;j++);
  144.         }
  145. }
  146. //****************************************
  147. //LCD1602初始化
  148. //****************************************
  149. void InitLcd()
  150. {
  151.         WriteCommandLCM(0x38,1);
  152.         WriteCommandLCM(0x08,1);
  153.         WriteCommandLCM(0x01,1);
  154.         WriteCommandLCM(0x06,1);
  155.         WriteCommandLCM(0x0c,1);
  156.         DisplayOneChar(0,0,'A');
  157.         DisplayOneChar(0,1,'G');
  158. }
  159. //****************************************
  160. //LCD1602寫允許
  161. //****************************************
  162. void WaitForEnable(void)
  163. {
  164.         DataPort=0xff;
  165.         LCM_RS=0;LCM_RW=1;_nop_();
  166.         LCM_EN=1;_nop_();_nop_();
  167.         while(DataPort&0x80);
  168.         LCM_EN=0;
  169. }
  170. //****************************************
  171. //LCD1602寫入命令
  172. //****************************************
  173. void WriteCommandLCM(uchar CMD,uchar Attribc)
  174. {
  175.         if(Attribc)WaitForEnable();
  176.         LCM_RS=0;LCM_RW=0;_nop_();
  177.         DataPort=CMD;_nop_();
  178.         LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  179. }
  180. //****************************************
  181. //LCD1602寫入數據
  182. //****************************************
  183. void WriteDataLCM(uchar dataW)
  184. {
  185.         WaitForEnable();
  186.         LCM_RS=1;LCM_RW=0;_nop_();
  187.         DataPort=dataW;_nop_();
  188.         LCM_EN=1;_nop_();_nop_();LCM_EN=0;
  189. }
  190. //****************************************
  191. //LCD1602寫入一個字符
  192. //****************************************
  193. void DisplayOneChar(uchar X,uchar Y,uchar DData)
  194. {
  195.         Y&=1;
  196.         X&=15;
  197.         if(Y)X|=0x40;
  198.         X|=0x80;
  199.         WriteCommandLCM(X,0);
  200.         WriteDataLCM(DData);
  201. }
  202. //****************************************
  203. //LCD1602顯示字符串
  204. //****************************************
  205. void DisplayListChar(uchar X,uchar Y,uchar *DData,L)
  206. {
  207.         uchar ListLength=0;
  208.         Y&=0x1;
  209.         X&=0xF;
  210.         while(L--)
  211.         {
  212.                 DisplayOneChar(X,Y,DData[ListLength]);
  213.                 ListLength++;
  214.                 X++;
  215.         }
  216. }
  217. //**************************************
  218. //延時5微秒(STC90C52RC@12M)
  219. //不同的工作環境,需要調整此函數
  220. //當改用1T的MCU時,請調整此延時函數
  221. //**************************************
  222. void Delay5us()
  223. {
  224.         _nop_();_nop_();_nop_();_nop_();
  225.         _nop_();_nop_();_nop_();_nop_();
  226.         _nop_();_nop_();_nop_();_nop_();
  227.         _nop_();_nop_();_nop_();_nop_();
  228.         _nop_();_nop_();_nop_();_nop_();
  229.         _nop_();_nop_();_nop_();_nop_();
  230. }
  231. //**************************************
  232. //I2C起始信號
  233. //**************************************
  234. void I2C_Start()
  235. {
  236.             Delay2us();                 //延時
  237.         Delay2us();                 //延時
  238.         SDA = 1;                    //拉高數據線
  239.         SCL = 1;                    //拉高時鐘線
  240.         Delay2us();                 //延時
  241.         Delay2us();                 //延時
  242.         SDA = 0;                    //產生下降沿
  243.         Delay2us();                 //延時
  244.         SCL = 0;                    //拉低時鐘線
  245.         Delay2us();                 //延時
  246. }
  247. //**************************************
  248. //I2C停止信號
  249. //**************************************
  250. void I2C_Stop()
  251. {
  252.     Delay2us();                 //延時
  253.     SDA = 0;                    //拉低數據線
  254.     SCL = 1;                    //拉高時鐘線
  255.         Delay2us();                 //延時
  256.     SDA = 1;                    //產生上升沿
  257.         Delay2us();                 //延時
  258. }
  259. //**************************************
  260. //I2C發送應答信號
  261. //入口參數:ack (0:ACK 1:NAK)
  262. //**************************************
  263. void I2C_SendACK(bit ack)
  264. {
  265.     SDA = ack;                  //寫應答信號
  266.     SCL = 1;                    //拉高時鐘線
  267.     Delay5us();                 //延時
  268.     SCL = 0;                    //拉低時鐘線
  269.     Delay5us();                 //延時
  270. }
  271. //**************************************
  272. //I2C接收應答信號
  273. //**************************************
  274. bit I2C_RecvACK(void)
  275. {
  276.     SDA = 1;
  277.         Delay2us();                 //延時
  278.     SCL = 1;                    //拉高時鐘線
  279.     Delay2us();                 //延時
  280.     CY = SDA;                   //讀應答信號
  281.     SCL = 0;                    //拉低時鐘線
  282.     Delay2us();                 //延時
  283.     return CY;
  284. }
  285. //**************************************
  286. //向I2C總線發送一個字節數據
  287. //**************************************
  288. void I2C_SendByte(u8 dat)
  289. {
  290.     u8 i;
  291.     for (i=0; i<8; i++)         //8位計數器
  292.     {
  293.         dat <<= 1;              //移出數據的最高位
  294.         SDA = CY;               //送數據口
  295.         SCL = 1;                //拉高時鐘線
  296.         Delay2us();             //延時
  297.         SCL = 0;                //拉低時鐘線
  298.         Delay2us();             //延時
  299.     }
  300.     I2C_RecvACK();
  301. }
  302. //**************************************
  303. //從I2C總線接收一個字節數據
  304. //**************************************
  305. uchar I2C_RecvByte()
  306. {
  307.     u8 i;
  308.     u8 dat = 0;
  309.     SDA = 1;                    //使能內部上拉,準備讀取數據,
  310.     for (i=0; i<8; i++)         //8位計數器
  311.     {
  312.         dat <<= 1;
  313.         SCL = 1;                //拉高時鐘線
  314.         Delay2us();             //延時
  315.         dat |= SDA;             //讀數據
  316.         SCL = 0;                //拉低時鐘線
  317.         Delay2us();             //延時
  318.     }
  319.     return dat;
  320. }
  321. //**************************************
  322. //向I2C設備寫入一個字節數據
  323. //**************************************
  324. void Single_WriteI2C(u8 REG_Address,u8 REG_data)
  325. {
  326.     I2C_Start();                  //起始信號
  327.     I2C_SendByte(SlaveAddress);   //發送設備地址+寫信號
  328.     I2C_SendByte(REG_Address);    //內部寄存器地址,
  329.     I2C_SendByte(REG_data);       //內部寄存器數據,
  330.     I2C_Stop();                   //發送停止信號
  331. }
  332. //**************************************
  333. //從I2C設備讀取一個字節數據
  334. //**************************************
  335. u8 Single_ReadI2C(u8 REG_Address)
  336. {
  337.         u8 REG_data;
  338.         I2C_Start();                   //起始信號
  339.         I2C_SendByte(SlaveAddress);    //發送設備地址+寫信號
  340.         I2C_SendByte(REG_Address);     //發送存儲單元地址,從0開始
  341.         I2C_Start();                   //起始信號
  342.         I2C_SendByte(SlaveAddress+1);  //發送設備地址+讀信號
  343.         REG_data=I2C_RecvByte();       //讀出寄存器數據
  344.         
  345.         SDA = 1;                    //寫應答信號
  346.         SCL = 1;                    //拉高時鐘線
  347.         Delay2us();                 //延時
  348.         SCL = 0;                    //拉低時鐘線
  349.         Delay2us();                 //延時
  350.         
  351.         I2C_Stop();                    //停止信號
  352.         return REG_data;
  353. }
  354. //**************************************
  355. //初始化MPU6050
  356. //**************************************
  357. void InitMPU6050()
  358. {
  359.         Single_WriteI2C(PWR_MGMT_1, 0x00);        //解除休眠狀態
  360.         Single_WriteI2C(SMPLRT_DIV, 0x07);
  361.         Single_WriteI2C(CONFIG, 0x04);
  362.         Single_WriteI2C(GYRO_CONFIG, 0x08);
  363.         Single_WriteI2C(ACCEL_CONFIG, 0x08);
  364. }
  365. //**************************************
  366. //合成數據
  367. //**************************************
  368. int GetData(uchar REG_Address)
  369. {
  370.         char H,L;
  371.         H=Single_ReadI2C(REG_Address);
  372.         L=Single_ReadI2C(REG_Address+1);
  373.         return (H<<8)+L;   //合成數據
  374. }
  375. //**************************************
  376. //在1602上顯示10位數據
  377. //**************************************
  378. void Display10BitData(int value,uchar x,uchar y)
  379. {
  380.         value/=64;                                                        //轉換為10位數據
  381.         lcd_printf(dis, value);                        //轉換數據顯示
  382.         DisplayListChar(x,y,dis,4);        //啟始列,行,顯示數組,顯示長度
  383. }
  384. //*********************************************************************
  385. //****************角度計算*********************************************
  386. //*********************************************************************
  387. #define        pi                3.14159265f                           
  388. #define        Kp                0.8f                        
  389. #define        Ki                0.001f                        
  390. #define        halfT        0.004f           

  391. float idata q0=1,q1=0,q2=0,q3=0;   
  392. float idata exInt=0,eyInt=0,ezInt=0;  

  393. void IMUupdate(float gx, float gy, float gz, float ax, float ay, float az)
  394. {
  395.         float data norm;
  396.         float idata vx, vy, vz;
  397.         float idata ex, ey, ez;

  398.         norm = sqrt(ax*ax + ay*ay + az*az);        
  399.         ax = ax / norm;
  400.         ay = ay / norm;
  401.         az = az / norm;

  402.         
  403.         vx = 2*(q1*q3 - q0*q2);
  404.         vy = 2*(q0*q1 + q2*q3);
  405.         vz = q0*q0 - q1*q1 - q2*q2 + q3*q3 ;

  406.         ex = (ay*vz - az*vy) ;
  407.         ey = (az*vx - ax*vz) ;
  408.         ez = (ax*vy - ay*vx) ;

  409.         exInt = exInt + ex * Ki;
  410.         eyInt = eyInt + ey * Ki;
  411.         ezInt = ezInt + ez * Ki;

  412.         gx = gx + Kp*ex + exInt;
  413.         gy = gy + Kp*ey + eyInt;
  414.         gz = gz + Kp*ez + ezInt;

  415.         q0 = q0 + (-q1*gx - q2*gy - q3*gz) * halfT;
  416.         q1 = q1 + ( q0*gx + q2*gz - q3*gy) * halfT;
  417.         q2 = q2 + ( q0*gy - q1*gz + q3*gx) * halfT;
  418.         q3 = q3 + ( q0*gz + q1*gy - q2*gx) * halfT;

  419.         norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
  420.         q0 = q0 / norm;
  421.         q1 = q1 / norm;
  422.         q2 = q2 / norm;
  423.         q3 = q3 / norm;

  424.         AngleX = asin(2*(q0*q2 - q1*q3 )) * 57.2957795f;
  425.         AngleY = asin(2*(q0*q1 + q2*q3 )) * 57.2957795f;
  426. }
  427. //*********************************************************
  428. //主程序
  429. //*********************************************************
  430. void main()
  431. {               
  432.         delay(500);                //上電延時
  433.         InitLcd();                //液晶初始化
  434.         InitMPU6050();        //初始化MPU6050

  435.         delay(150);

  436.         while(1)
  437.         {                   Read_MPU6050(MPU6050_DATA);
  438.                 Acc_x = MPU6050_DATA[0]<<8|MPU6050_DATA[1];
  439.                 Acc_y = MPU6050_DATA[2]<<8|MPU6050_DATA[3];
  440.                 Acc_z = MPU6050_DATA[4]<<8|MPU6050_DATA[5];
  441.                 Temp  = MPU6050_DATA[6]<<8|MPU6050_DATA[7];
  442.                 Gyro_x = MPU6050_DATA[8]<<8|MPU6050_DATA[9];
  443.                 Gyro_y = MPU6050_DATA[10]<<8|MPU6050_DATA[11];
  444.                 Gyro_z = MPU6050_DATA[12]<<8|MPU6050_DATA[13];
  445.                
  446.                 Angle_ax = Acc_x/8192.0;
  447.                 Angle_ay = Acc_y/8192.0;
  448.                 Angle_az = Acc_z/8192.0;
  449.                
  450.                 Angle_gx = Gyro_x/65.5;
  451.                 Angle_gy = Gyro_y/65.5;
  452.                 Angle_gz = Gyro_z/65.5;
  453.                
  454.                 IMUupdate(Angle_gx*0.0174533f,Angle_gy*0.0174533f,Angle_gz*0.0174533f,Angle_ax,Angle_ay,Angle_az);
  455.                 Display10BitData(GetData(ACCEL_XOUT_H),2,0);        //顯示X軸加速度
  456.                 Display10BitData(GetData(ACCEL_YOUT_H),7,0);        //顯示Y軸加速度
  457.                 Display10BitData(GetData(ACCEL_ZOUT_H),12,0);        //顯示Z軸加速度
  458.                 Display10BitData(AngleX,2,1);        //顯示俯仰角
  459.                 Display10BitData(AngleY,7,1);        //顯示橫滾角
  460.                 Display10BitData(GetData(GYRO_ZOUT_H),12,1);        //未改,顯示Z軸角速度
  461.                 delay(500);
  462.         }
  463. }
復制代碼


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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 色偷偷噜噜噜亚洲男人 | 国产一级淫片a直接免费看 免费a网站 | 国产福利资源在线 | 草草视频在线观看 | 青青久在线视频 | 久久久久免费观看 | 真人女人一级毛片免费播放 | 日韩视频免费看 | 日本一本在线 | 欧美综合一区 | 电影91久久久| 亚洲精品一区二区三区在线 | 韩日在线 | 成人午夜激情 | 午夜精品久久久久久不卡欧美一级 | 亚洲精品在线免费 | 一区二区三区中文字幕 | 黄色国产 | 欧美日本在线观看 | 国产欧美一区二区久久性色99 | 国产一区二区三区久久久久久久久 | 国产98在线 | 免费, | 毛片在线免费播放 | 超碰最新在线 | 色姑娘综合网 | 国产午夜精品久久久 | 日韩精品 电影一区 亚洲 | 精品欧美一区二区在线观看欧美熟 | 在线观看av网站 | 久久男女视频 | 91精品国产91久久久久久吃药 | 日韩欧美国产一区二区三区 | 国产午夜精品理论片a大结局 | 91高清免费 | 99久久精品国产毛片 | 在线成人一区 | 久久久视频在线 | 色婷婷一区 | 欧美激情国产日韩精品一区18 | 奇米四色影视 | 久久精品国产一区二区三区不卡 |