找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12089|回复: 21
收起左侧

mpu6050卡尔曼滤波输出姿态角程序

  [复制链接]
ID:159760 发表于 2017-7-30 01:31 | 显示全部楼层 |阅读模式
经过调试可以正确读取数据并输出 姿态角

单片机源程序如下:


  1. /******************** (C) COPYRIGHT 2012 WildFire Team **************************
  2. * 文件名  :main.c
  3. * 描述    :I2C EEPROM(AT24C02)测试,测试信息通过USART1打印在电脑的超级终端。     
  4. * 实验平台:野火STM32开发板
  5. * 库版本  :ST3.0.0
  6. * 作者    :wildfire team
  7. **********************************************************************************/        
  8. #include "stm32f10x.h"
  9. #include "I2C_MPU6050.h"
  10. #include "usart1.h"
  11. #include "delay.h"
  12. #include "filter.h"
  13. #include "math.h"
  14. #include "misc.h"
  15. #include "TIMX.h"
  16. #define AIN2   PBout(15)
  17. #define AIN1   PBout(14)
  18. #define BIN1   PBout(13)
  19. #define BIN2   PBout(12)
  20. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))  
  21. #define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
  22. #define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))
  23. #define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C
  24. #define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C
  25. #define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C
  26. #define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C
  27. #define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C
  28. #define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C   
  29. #define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C   
  30. //#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出
  31. //#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入

  32. #define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出
  33. //#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入

  34. //#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出
  35. //#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入

  36. //#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出
  37. //#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入

  38. //#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出
  39. //#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

  40. //#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出
  41. //#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

  42. //#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出
  43. //#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入
  44. #define PI 3.14159265
  45. #define ZHONGZHI -6
  46. #define PWMA   TIM1->CCR1  //PA8

  47. #define PWMB   TIM1->CCR4  //PA11
  48. float Angle_Balance,Gyro_Balance,Gyro_Turn;  //平衡环控制相关变量
  49. float Encoder_left,Encoder_right;            //速度环控制相关变量
  50. int Moto1,Moto2;                                                            
  51. /*
  52. * 函数名:main
  53. * 描述  :主函数
  54. * 输入  :无
  55. * 输出  :无
  56. * 返回  :无
  57. */

  58. //中断分组处理函数
  59. void NVIC_Configuration(void)
  60. {

  61.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        //设置NVIC中断分组2:2位抢占优先级,2位响应优先级

  62. }
  63. int Read_Encoder(u8 TIMX);
  64. //位置平衡PID控制
  65. int balance(float Angle,float Gyro)
  66. {  
  67.    float Bias,kp=500,kd=1;
  68.          int balance;
  69.          Bias=Angle-ZHONGZHI;       //===求出平衡的角度中值 和机械相关
  70.          balance=kp*Bias+Gyro*kd;   //===计算平衡控制的电机PWM  PD控制   kp是P系数 kd是D系数
  71.          return balance;
  72. }

  73. //速度PI控制
  74. int velocity(int encoder_left,int encoder_right)
  75. {
  76.         static float Velocity,Encoder_Least,Encoder,Movement;
  77.         static float Encoder_Integral,Target_Velocity;
  78.         float kp=50,ki=kp/200;
  79.         Encoder_Least=(Encoder_left+Encoder_right)-0;
  80.         Encoder*=0.7;                                  //一阶低通滤波,上次速度差占70,本次速度差占30,减缓速度差值,减少对直立系统的干扰
  81.         Encoder+=Encoder_Least*0.3;                      //一阶低通滤波
  82.         Encoder_Integral+=Encoder;            //积分出位移,积分时间10ms
  83.         Encoder_Integral=Encoder_Integral-Movement;  //接受遥控器的数据,控制正反转
  84.         if(Encoder_Integral>15000){
  85.                 Encoder_Integral=15000;                   //积分限幅
  86.         }
  87.         if(Encoder_Integral<-15000)
  88.         {
  89.         Encoder_Integral=-15000;
  90.         }
  91.         Velocity=Encoder*kp+Encoder_Integral*ki;    //PI 控制器
  92.         
  93.         return Velocity;
  94.         
  95. }
  96. //限幅函数
  97. void Xianfu_Pwm(void)
  98. {        
  99.           int Amplitude=6900;    //===PWM满幅是7200 限制在6900
  100.     if(Moto1<-Amplitude) Moto1=-Amplitude;        
  101.                 if(Moto1>Amplitude)  Moto1=Amplitude;        
  102.           if(Moto2<-Amplitude) Moto2=-Amplitude;        
  103.                 if(Moto2>Amplitude)  Moto2=Amplitude;               
  104. }

  105. //绝对值函数
  106. int myabs(int a)
  107. {                    
  108.           int temp;
  109.                 if(a<0)  temp=-a;  
  110.           else temp=a;
  111.           return temp;
  112. }
  113. /*void MiniBalance_Motor_Init(void)
  114. {
  115.         RCC->APB2ENR|=1<<3;       //PORTB时钟使能   
  116.         GPIOB->CRH&=0X0000FFFF;   //PORTB12 13 14 15推挽输出
  117.         GPIOB->CRH|=0X22220000;   //PORTB12 13 14 15推挽输出
  118. }*/
  119. void MiniBalance_Motor_Init(void)
  120. {

  121. GPIO_InitTypeDef  GPIO_InitStructure;
  122.          
  123. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);         //使能PB,PE端口时钟
  124.         
  125. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;                                 //LED0-->PB.5 端口配置
  126. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
  127. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
  128. GPIO_Init(GPIOB, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOB.5
  129. //GPIO_SetBits(GPIOB,GPIO_Pin_5);        
  130. //GPIO_ResetBits(GPIOB,GPIO_Pin_6);        //PB.5 输出高

  131. //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                             //LED1-->PE.5 端口配置, 推挽输出
  132. //GPIO_Init(GPIOE, &GPIO_InitStructure);                                           //推挽输出 ,IO口速度为50MHz
  133. //GPIO_SetBits(GPIOE,GPIO_Pin_5);                                                  //PE.5 输出高
  134. }


  135. void MiniBalance_PWM_Init(u16 arr,u16 psc)
  136. {                                                         
  137.         MiniBalance_Motor_Init();  //初始化电机控制所需IO
  138.         RCC->APB2ENR|=1<<11;       //使能TIM1时钟   
  139.         RCC->APB2ENR|=1<<2;        //PORTA时钟使能     
  140.         GPIOA->CRH&=0XFFFF0FF0;    //PORTA8 11复用输出
  141.         GPIOA->CRH|=0X0000B00B;    //PORTA8 11复用输出
  142.         TIM1->ARR=arr;             //设定计数器自动重装值
  143.         TIM1->PSC=psc;             //预分频器不分频
  144.         TIM1->CCMR2|=6<<12;        //CH4 PWM1模式        
  145.         TIM1->CCMR1|=6<<4;         //CH1 PWM1模式        
  146.         TIM1->CCMR2|=1<<11;        //CH4预装载使能         
  147.         TIM1->CCMR1|=1<<3;         //CH1预装载使能         
  148.         TIM1->CCER|=1<<12;         //CH4输出使能           
  149.         TIM1->CCER|=1<<0;          //CH1输出使能        
  150.         TIM1->BDTR |= 1<<15;       //TIM1必须要这句话才能输出PWM
  151.         TIM1->CR1=0x8000;          //ARPE使能
  152.         TIM1->CR1|=0x01;          //使能定时器1                        
  153. }

  154. //PWM shewzhi
  155. void Set_Pwm(int moto1,int moto2)
  156. {
  157.         
  158.               int siqu=400;
  159.                         if(moto1<0)                 
  160.                         {
  161.                                 printf("AIN反向");
  162.                                 AIN1=0;   
  163.                         AIN2=1;
  164.                         }
  165.                         else         
  166.                         {
  167.                                 printf("AINfanxaing");
  168.                                 AIN2=0;
  169.                                 AIN1=1;
  170.                         }
  171.                         PWMA=myabs(moto1)+siqu;
  172.                   if(moto2<0)
  173.                         {        
  174.                                 BIN1=0;               
  175.                                 BIN2=1;
  176.                         }
  177.                         else      
  178.                         {                        
  179.                                 BIN1=1;                        
  180.                                 BIN2=0;
  181.                         }
  182.                         PWMB=myabs(moto2)+siqu;        
  183. }

  184. int main(void)
  185. {        
  186.   int Accel_Y,Accel_X,Accel_Z,Gyro_X,Gyro_Y,Gyro_Z;
  187.         float Acceleration_Z;                       //Z轴加速度计
  188.         int Balance_Pwm,Velocity_Pwm;
  189.         
  190.   NVIC_Configuration();          //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  191.         
  192.         /* 串口1初始化 */
  193.         USART1_Config();
  194.   /*GPIO 口初始化        */
  195.         MiniBalance_Motor_Init();
  196.         /*定时器1初始化*/
  197.         MiniBalance_PWM_Init(7199,0);
  198.         Encoder_Init_TIM2();            //=====编码器接口
  199.         Encoder_Init_TIM4();            //=====初始化编码器2
  200.         /*IIC接口初始化*/
  201.         I2C_MPU6050_Init();         
  202.         /*陀螺仪传感器初始化*/
  203.   InitMPU6050();
  204.         
  205.         /***********************************************************************/
  206.         
  207.         while(1)
  208.         {
  209.                 Accel_X=GetData(ACCEL_XOUT_H);
  210.                 Accel_Y=GetData(ACCEL_YOUT_H);
  211.                 Accel_Z=GetData(ACCEL_ZOUT_H);
  212.                 Gyro_X=GetData(GYRO_XOUT_H);
  213.                 Gyro_Y=GetData(GYRO_YOUT_H);
  214.                 Gyro_Z=GetData(GYRO_ZOUT_H);
  215.                 Encoder_left=-Read_Encoder(2);                                      //===读取编码器的值,因为两个电机的旋转了180度的,所以对其中一个取反,保证输出极性一致
  216.                 Encoder_right=Read_Encoder(4);
  217.                
  218.     /*printf("\r\n---------加速度X轴原始数据---------%d \r\n",Accel_X);
  219.                 printf("\r\n---------加速度Y轴原始数据---------%d \r\n",Accel_Y);        
  220.                 printf("\r\n---------加速度Z轴原始数据---------%d \r\n",Accel_Z);        
  221.                 printf("\r\n---------陀螺仪X轴原始数据---------%d \r\n",Gyro_X);        
  222.                 printf("\r\n---------陀螺仪Y轴原始数据---------%d \r\n",Gyro_Y);        
  223.                 printf("\r\n---------陀螺仪Z轴原始数据---------%d \r\n",Gyro_Z);*/
  224.                 //delay_ms(500);
  225.         
  226.                  if(Gyro_Y>32768)  Gyro_Y-=65536;                       //数据类型转换  也可通过short强制类型转换
  227.                         if(Gyro_Z>32768)  Gyro_Z-=65536;                       //数据类型转换
  228.                   if(Accel_X>32768) Accel_X-=65536;                      //数据类型转换
  229.                   if(Accel_Z>32768) Accel_Z-=65536;                      //数据类型转换
  230.                         Gyro_Balance=-Gyro_Y;                                  //更新平衡角速度
  231.                    Accel_Y=atan2(Accel_X,Accel_Z)*180/PI;                 //计算倾角        
  232.                   Gyro_Y =Gyro_Y/16.4;                                    //陀螺仪量程转换        
  233.              Kalman_Filter(Accel_Y,-Gyro_Y);//卡尔曼滤波        
  234.                         //else if(Way_Angle==3)   Yijielvbo(Accel_Y,-Gyro_Y);    //互补滤波
  235.             Angle_Balance=angle;                                   //更新平衡倾角
  236.                         Gyro_Turn=Gyro_Z;                                      //更新转向角速度
  237.                         Acceleration_Z=Accel_Z;                                //===更新Z轴加速度计        
  238.                         Gyro_Balance=-Gyro_Y;
  239.                         printf("卡尔曼滤波值%f,%f\n",Angle_Balance,Gyro_Turn);
  240.                         //Balance_Pwm =balance(Angle_Balance,Gyro_Balance);
  241.                         Velocity_Pwm=velocity(Encoder_left,Encoder_right);      
  242.                         Moto1=Velocity_Pwm;
  243.                         Moto2=Velocity_Pwm;
  244.                         printf("%d,%d\n",Moto1,Moto2);
  245.                         Xianfu_Pwm();   
  246.                         Set_Pwm(Moto1,Moto2);  
  247.                                 delay_ms(5);
  248.         }               


  249. }

  250. /******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/

  251. ……………………

  252. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
卡尔曼滤波输出姿态角.zip (2.14 MB, 下载次数: 429)
回复

使用道具 举报

ID:217957 发表于 2018-1-6 14:54 | 显示全部楼层
资料不错,参考一下
回复

使用道具 举报

ID:128321 发表于 2018-3-21 21:37 来自手机 | 显示全部楼层
mfc20010 发表于 2018-1-6 14:54
资料不错,参考一下

资料不错,参考一下
回复

使用道具 举报

ID:237206 发表于 2018-3-25 20:13 | 显示全部楼层
支持一下
回复

使用道具 举报

ID:290380 发表于 2018-5-3 21:18 | 显示全部楼层

资料不错,参考一下,支持一下
回复

使用道具 举报

ID:323802 发表于 2018-5-6 21:52 | 显示全部楼层
资料不错哦
回复

使用道具 举报

ID:329263 发表于 2018-5-14 01:48 | 显示全部楼层
可以把附件发给我嘛,676913753@qq.com没有币很难受
回复

使用道具 举报

ID:320612 发表于 2018-5-22 15:55 | 显示全部楼层
资料不错,参考一下,支持一下
回复

使用道具 举报

ID:337376 发表于 2018-6-5 17:21 | 显示全部楼层
很好的算法,谢谢分享
回复

使用道具 举报

ID:320161 发表于 2018-6-9 23:44 | 显示全部楼层
不能用骗人的!
回复

使用道具 举报

ID:368329 发表于 2018-7-9 23:43 | 显示全部楼层


资料不错,参考一下,支持一下
回复

使用道具 举报

ID:158903 发表于 2018-7-10 16:10 | 显示全部楼层
资料不错,参考一下,支持一下
马克
回复

使用道具 举报

ID:370943 发表于 2018-9-26 15:33 | 显示全部楼层
学习大神的作品
回复

使用道具 举报

ID:248291 发表于 2018-9-29 22:46 来自手机 | 显示全部楼层
学习一下
回复

使用道具 举报

ID:387286 发表于 2018-11-5 19:52 | 显示全部楼层
不能用,代码不全
回复

使用道具 举报

ID:502704 发表于 2019-4-2 18:47 | 显示全部楼层
资料不错,参考一下
回复

使用道具 举报

ID:442220 发表于 2019-7-29 19:42 | 显示全部楼层
学习了,最近急需这些
回复

使用道具 举报

ID:267330 发表于 2019-7-30 08:58 | 显示全部楼层
谢谢正是我需要的
回复

使用道具 举报

ID:421308 发表于 2019-8-2 08:54 | 显示全部楼层
资料不错,学习下
回复

使用道具 举报

ID:588621 发表于 2019-8-2 15:29 来自手机 | 显示全部楼层
厉害哦咯可以用下
回复

使用道具 举报

ID:443082 发表于 2020-6-4 23:54 | 显示全部楼层
资料不错,可以放到stm32f103c8t6上使用并且成功输出。感谢分享。
回复

使用道具 举报

ID:369024 发表于 2020-6-7 12:27 | 显示全部楼层
   没有姿态结算
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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