极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 56003|回复: 30

MPU-6050的姿态识别(只差z轴了)

[复制链接]
发表于 2012-9-30 22:29:15 | 显示全部楼层 |阅读模式
本帖最后由 ggko123 于 2012-10-2 08:57 编辑

我作为一直在论坛关注着6050的使用问题,几乎刨遍了所有有关的帖子,终于找到了一个合适的算法,就是所谓的一阶互补,
http://www.geek-workshop.com/forum.php?mod=viewthread&tid=1549
根据贴里的程序,我完成了x,y轴的程序,效果不错,能输出比较准确的角度
  1. #include "Wire.h"
  2. #include "i2cdev.h"
  3. #include "MPU6050.h"

  4. MPU6050 accelgyro;
  5. int16_t ax, ay, az;
  6. int16_t gx, gy, gz;

  7. #define Gry_offset_X 45//陀螺仪X轴的静态飘移。
  8. #define Gry_offset_Y 271
  9. #define Gyr_Gain -0.00763//由陀螺仪X轴读数转换为角速度值,=1/131,向前方向与X轴为反方向,故乘以-1

  10. #define ACC_Gain 0.000061//由读数转换为加速度值,=1/16384
  11. #define pi 3.1415926
  12. #define K_x 0.715//一阶互补滤波权重取值,不知由来,可更改。
  13. #define k_Y 1.3

  14. unsigned long preTime = 0;
  15. float angle_X = 0;
  16. float angle_Y = 0;

  17. void setup()
  18. {
  19.   Wire.begin();
  20.   Serial.begin(9600);
  21.   accelgyro.initialize();//MPU6050初始化。
  22. }

  23. void loop()
  24. {
  25.   
  26.   unsigned long now = millis();//当前时间(ms)
  27.   float dt = (now - preTime) / 500.0;//微分时间(s)
  28.   preTime = now;//上一次采样时间(ms)

  29.   
  30.   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);//读取六轴数值
  31.   
  32.   float Y_Accelerometer = ay * ACC_Gain;//转换为向前的加速度(g),为负值
  33.   float Z_Accelerometer = az * ACC_Gain;//转换为向下的加速度(g)
  34.   float X_Accelerometer = ax * ACC_Gain;
  35.   float angleA_X= atan(Y_Accelerometer/ Z_Accelerometer)* (-180)/ pi;//加速度仪,反正切获得弧度值,乘以180度/pi
  36.                                                                    //获得角度值,乘以-1得正
  37.   float angleA_Y= atan(X_Accelerometer/Z_Accelerometer)*(-180)/pi;
  38.                                                                   
  39.   float gx_revised = gx + Gry_offset_X;//陀螺仪x轴静态时修正后的角速度读数,向前为负值
  40.   float gy_revised = gy + Gry_offset_Y;
  41.   float omega_X= Gyr_Gain* gx_revised;//陀螺仪,转换为向前的角速度(o/s),Gyr_Gain取负,故负负得正
  42.   float omega_Y= Gyr_Gain* gy_revised;
  43.   float angle_dt_X = omega_X * dt;//角度的单次积分值
  44.   float angle_dt_Y = omega_Y * dt;

  45.   angle_X+= (Gyr_Gain * (gx + Gry_offset_X)) * dt;
  46.   angle_Y+= (Gyr_Gain * (gy + Gry_offset_Y)) * dt;


  47.   float A_X= K_x/ (K_x+ dt);
  48.   //陀螺仪的权值
  49.   float A_Y= k_Y/(k_Y+dt);
  50.   angle_X= A_X* (angle_X+ omega_X* dt)+ (1-A_X)* angleA_X;//一阶互补滤波后的输出角度(o)
  51.   angle_Y= A_Y*(angle_Y+omega_Y*dt)+(1-A_Y)*angleA_Y;
  52.   delay(10);
  53.   
  54.     Serial.println(angle_X);
  55.     Serila.println(angle_Y);
  56.     }
复制代码

但是到了z轴就卡住了,用同样的算法,z轴只能输出角度变化,不能输出准确的角度。
  1. #include "Wire.h"
  2. #include "i2cdev.h"
  3. #include "MPU6050.h"

  4. MPU6050 accelgyro;
  5. int16_t ax, ay, az;
  6. int16_t gx, gy, gz;

  7. #define Gry_offset 38//z轴偏移量
  8. #define Gyr_Gain -0.00763

  9. #define ACC_Gain 0.000061
  10. #define pi 3.1415926
  11. #define K 1.75//这个比例常数可以改的

  12. unsigned long preTime = 0;
  13. float angleG = 0;

  14. void setup()
  15. {
  16.   Wire.begin();
  17.   Serial.begin(9600);
  18.   accelgyro.initialize();


  19. void loop()
  20. {
  21.   
  22.   unsigned long now = millis();
  23.   float dt = (now - preTime) / 400.0;
  24.   preTime = now;

  25.   
  26.   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  27.   
  28.   float Y_Accelerometer = ay * ACC_Gain;
  29.   float X_Accelerometer = ax * ACC_Gain;
  30.   float angleA= atan(Y_Accelerometer/ X_Accelerometer)* (-180)/ pi;
  31.                                                                   
  32.                                                                   
  33.   float gz_revised = gz + Gry_offset;
  34.   float omega= Gyr_Gain* gz_revised;
  35.   float angle_dt = omega * dt;/

  36.   
  37.   angleG+= (Gyr_Gain * (gz + Gry_offset)) * dt;


  38.   float A= K/ (K+ dt);
  39.   angleG= A* (angleG+ omega* dt)+ (1-A)* angleA ;
  40.   
  41.   delay(10);

  42.     Serial.println(angleG);
  43.     }
复制代码

如图,有四次波动,代表四次旋转,波形上升是顺时针转动,下降是逆时针转动,但都会回到零点附近,不能停在具体偏转角度上。是算法问题,还是6050的设计问题?

我觉得离成功不远了,只有读出z轴角度,就能编写一个processing上的姿态识别程序,到时一定会写一篇详细过程,希望诸位大牛帮忙!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2012-10-1 19:35:38 | 显示全部楼层
弱弱的说。。我的z轴是配合地磁传感器换算的。。⊙﹏⊙
回复 支持 反对

使用道具 举报

发表于 2012-10-1 21:33:55 | 显示全部楼层
Z轴陀螺数据是没有办法使用z轴的加速度进行修正的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-1 22:35:10 | 显示全部楼层
能解释一下吗?如果我只用这个做四轴够用吗?
回复 支持 反对

使用道具 举报

发表于 2012-10-1 22:40:04 | 显示全部楼层
Z轴陀螺数据只能用罗盘数据进行修正,你做四轴的,只对z轴的数据进行PID修正控制就行了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-2 08:57:16 | 显示全部楼层
原来是这样啊,谢谢了,我之前还以为一个6050就能测出各轴的旋转量
回复 支持 反对

使用道具 举报

发表于 2012-10-2 15:35:21 | 显示全部楼层
你是做两轮小车的吗?我想问问,你怎么控制电机的。能说说吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-10-2 16:45:12 | 显示全部楼层
at97 发表于 2012-10-2 15:35
你是做两轮小车的吗?我想问问,你怎么控制电机的。能说说吗?

还没打算做小车,以后可能会尝试,目前都在做姿态识别程序,你可以看上面那个地址,程序很不错的
回复 支持 反对

使用道具 举报

发表于 2012-10-4 21:15:37 | 显示全部楼层
好程序留个名
回复 支持 反对

使用道具 举报

发表于 2012-10-4 21:17:27 | 显示全部楼层
还有问问楼主那个示波程序是怎么弄的,我是超级新手,请教一下
回复 支持 反对

使用道具 举报

发表于 2012-10-8 20:19:49 | 显示全部楼层
为什么你的微分时间一个除以500  一个除以400呢  不是都应该是除以1000吗??
回复 支持 反对

使用道具 举报

发表于 2012-10-9 09:00:25 | 显示全部楼层
能否把Z轴的代码也贴出来学习一下呢?
回复 支持 反对

使用道具 举报

发表于 2012-10-11 17:11:54 | 显示全部楼层
楼主问一下,我的MPU6050陀螺仪静态值为零,不知道你的为什么有静态值,还是我的有问题
回复 支持 反对

使用道具 举报

发表于 2012-10-11 18:57:56 | 显示全部楼层
C:\Users\Administrator\Desktop\杂项
  1.          X_Acc = A_X * ACC_Gain;
  2.      Y_Acc = A_Y * ACC_Gain;//转换为向前的加速度(g),为负值
  3.      Z_Acc = A_Z * ACC_Gain;//转换为向下的加速度(g)
  4.          X_Gyro=G_X*Gyr_Gain;
  5.          Y_Gyro=G_Y*Gyr_Gain;
  6.          Z_Gyro=G_Z*Gyr_Gain;
  7.         angleA_X=atan2(X_Acc,Z_Acc)*(-180)/pi;
  8. //        angleA_Y=atan2(X_Acc,Z_Acc)*(-180)/pi;

  9.         Kalman_Filter(angleA_X,Y_Gyro);
复制代码
滤波出来如下
回复 支持 反对

使用道具 举报

发表于 2012-10-11 19:00:19 | 显示全部楼层
卡尔曼滤波之后响应比较慢,,对你的代码里与哦几个不太明白,那个 ACC_Gain和Gyr_Gain,是怎么得来的,是什么意思
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-26 23:42 , Processed in 0.050138 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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