搜索
bottom↓
回复: 26

IMUupdate姿态解算的问题

[复制链接]

出0入0汤圆

发表于 2014-5-19 13:49:35 | 显示全部楼层 |阅读模式
最近玩用Arduino,用到MPU6050,解算算法如下:
//*****************????**********************/
//***************
//???????
//***************
void init_BaseIMU(void) {
  for (byte axis = XAXIS; axis <= ZAXIS; axis++) {
     EularAngle[axis] = 0.0;  
  }
}

////////////////////////////////////////////////////////////////////////////////
// Initialize IMU
////////////////////////////////////////////////////////////////////////////////

void IMU_Init(void)
{
  init_BaseIMU();
  q0 = 1.0;
  q1 = 0.0;
  q2 = 0.0;
  q3 = 0.0;
  exInt = 0.0;
  eyInt = 0.0;
  ezInt = 0.0;
       
  previousEx = 0;
  previousEy = 0;
  previousEz = 0;

  Kp = 0.2; // 2.0;
  Ki = 0.0005; //0.005;
}
////////////////////////////////////////////////////////////////////////////////
// IMU_Update
////////////////////////////////////////////////////////////////////////////////
void IMU_Update(float gx, float gy, float gz, float ax, float ay, float az, float G_Dt) {
  
  float norm;
  float vx, vy, vz;
  float q0i, q1i, q2i, q3i;
  float ex, ey, ez;
   
  halfT = G_Dt/2;
  
  // normalise the measurements
  norm = sqrt(ax*ax + ay*ay + az*az);      
  ax = ax / norm;
  ay = ay / norm;
  az = az / norm;
            
  // estimated direction of gravity and flux (v and w)
  vx = 2*(q1*q3 - q0*q2);
  vy = 2*(q0*q1 + q2*q3);
  vz = q0*q0 - q1*q1 - q2*q2 + q3*q3;
   
  // error is sum of cross product between reference direction of fields and direction measured by sensors
  ex = (vy*az - vz*ay);
  ey = (vz*ax - vx*az);
  ez = (vx*ay - vy*ax);
   
  // integral error scaled integral gain
  exInt = exInt + ex*Ki;
  if (isSwitched(previousEx,ex)) {
    exInt = 0.0;
  }
  previousEx = ex;
       
  eyInt = eyInt + ey*Ki;
  if (isSwitched(previousEy,ey)) {
    eyInt = 0.0;
  }
  previousEy = ey;

  ezInt = ezInt + ez*Ki;
  if (isSwitched(previousEz,ez)) {
    ezInt = 0.0;
  }
  previousEz = ez;
       
  // adjusted gyroscope measurements
  gx = gx + Kp*ex + exInt;
  gy = gy + Kp*ey + eyInt;
  gz = gz + Kp*ez + ezInt;
   
  // integrate quaternion rate and normalise
  q0i = (-q1*gx - q2*gy - q3*gz) * halfT;
  q1i = ( q0*gx + q2*gz - q3*gy) * halfT;
  q2i = ( q0*gy - q1*gz + q3*gx) * halfT;
  q3i = ( q0*gz + q1*gy - q2*gx) * halfT;
  q0 += q0i;
  q1 += q1i;
  q2 += q2i;
  q3 += q3i;
   
  // normalise quaternion
  norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
  q0 = q0 / norm;
  q1 = q1 / norm;
  q2 = q2 / norm;
  q3 = q3 / norm;
}
////////////////////////////////////////////////////////////////////////////////
// Calculate IMU
////////////////////////////////////////////////////////////////////////////////
void IMU_Cal(float roll,float pitch, float yaw, float longitudinalAccel, float lateralAccel, float verticalAccel, float G_DT) {
  IMU_Update(roll,pitch,yaw,longitudinalAccel,lateralAccel,verticalAccel,G_DT);
/* Angle[XAXIS] = atan2(2 * (q0*q1 + q2*q3), 1 - 2 *(q1*q1 + q2*q2)); //ROLL
  Angle[YAXIS] = asin(2 * (q0*q2 - q1*q3));                            //PITCH
  Angle[ZAXIS] = atan2(2 * (q0*q3 + q1*q2), 1 - 2 *(q2*q2 + q3*q3));   //YAW  */
  
  EularAngle[XAXIS] = atan2(2 * (q0*q1 + q2*q3), 1 - 2 *(q1*q1 + q2*q2)); //ROLL
  EularAngle[YAXIS] = asin(2 * (q0*q2 - q1*q3));                            //PITCH
  EularAngle[ZAXIS] = atan2(2 * (q0*q3 + q1*q2), 1 - 2 *(q2*q2 + q3*q3));
}
用到的是 Madgwick的算法,但是数据输出会出现几个问题:
1.较好的情况:上电打印输出都是三轴都是0.0,但是有时候,ROLL会从180左右降到零,YAW值有偏差。静止的状态。
2.动态,如果我只在X轴上转动固定住某个角度,当然会输出角度值,其他两轴的角度几乎是0,但是过一段时间其他两轴会增至3.14(弧度),我猜测是不是和KP,KI有关的。
求解答!

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2014-6-14 10:27:26 | 显示全部楼层
正好我也在试用这个算法,也是在ARDUINO上!

你的代码只是其中的一段,所以无从知道你的HALFT取值是多大?另外你的四元素初值是用了(1,0,0,0)?应该先用加计的值算出欧拉(roll,pitch),然后由欧拉出初始的四元素.......

如果KP,KI不能让你快速收敛,回到初值,改half T试试吧........
(我和你用的代码不一样,我是用了另外一个有MAG数据的 Madgwick算法,但是没有接入地磁,用16M晶振的ARDUINO MINI, half T我试了一下,实际在6-7ms的一半!

出0入0汤圆

 楼主| 发表于 2014-6-17 11:26:22 | 显示全部楼层
本帖最后由 caiming1234567 于 2014-6-17 11:37 编辑
BLACKBLUE007 发表于 2014-6-14 10:27
正好我也在试用这个算法,也是在ARDUINO上!

你的代码只是其中的一段,所以无从知道你的HALFT取值是多大?另 ...


已经没问题了,是加速度值校准问题,算出来没问题,除了偏航有点问题,没有校正。

出0入0汤圆

发表于 2014-7-19 13:28:56 | 显示全部楼层
caiming1234567 发表于 2014-6-17 11:26
已经没问题了,是加速度值校准问题,算出来没问题,除了偏航有点问题,没有校正。 ...

偏航似乎不能矫正,因为加速度计测不到

出0入0汤圆

发表于 2014-7-19 13:33:00 | 显示全部楼层
我也是用的这个算法,pitch角超过80度就会变成0,你的是这样吗?

出0入0汤圆

 楼主| 发表于 2014-7-25 11:35:41 | 显示全部楼层
小菜鸟001 发表于 2014-7-19 13:33
我也是用的这个算法,pitch角超过80度就会变成0,你的是这样吗?

没有,是0~89~0

出0入0汤圆

发表于 2014-7-25 13:37:25 | 显示全部楼层
BLACKBLUE007 发表于 2014-6-14 10:27
正好我也在试用这个算法,也是在ARDUINO上!

你的代码只是其中的一段,所以无从知道你的HALFT取值是多大?另 ...

请教,我看到过用加计算出欧拉角,再用欧拉角初始化四元数的,也有直接用(1,0,0,0)初始化四元数的,但是用(1,0,0,0)的,有一个初始化200次的采样,不知这两种有什么区别,请不吝赐教。

出0入0汤圆

发表于 2014-7-25 13:41:24 | 显示全部楼层
BLACKBLUE007 发表于 2014-6-14 10:27
正好我也在试用这个算法,也是在ARDUINO上!

你的代码只是其中的一段,所以无从知道你的HALFT取值是多大?另 ...

还有,有的程序中注释这个halft必须是采样周期的一半,不能随便调整这个参数吧?难道这是理论和实际的差别?

出0入0汤圆

发表于 2014-7-25 14:56:42 | 显示全部楼层
幽灵盾 发表于 2014-7-25 13:41
还有,有的程序中注释这个halft必须是采样周期的一半,不能随便调整这个参数吧?难道这是理论和实际的差 ...

1,{1,0,0,0}初值也可以的,好象前提是你的IMU放置要和代码中规定的一致!
2,half T可以变的,据原文讲应该是IMUUPDATA的代码执行时间的一半,我试过,用比这"一半"时间大一点的数进去,没啥问题.......
3,人家取200次ACC值然后再做初始四元,可能仅仅是为校准加计吧!但无论如何,MPU6050,9150都一个德行,零飘就是无论怎么校,起码有+/-0.8%的数值误码率差!

我也是门外汉,不瞎折腾的,以上可能有不对.......

另外,求教一下,罗盘椭圆球拟合有资料么?给我资料吧如果有.....

出0入0汤圆

发表于 2014-7-25 17:06:53 | 显示全部楼层
非常感谢你的热心回答,我大二,研究四轴也就一个多月,也是门外汉。然后发现如果不进行yaw的控制四轴也能飞起来,不过会一直旋转,然后就飞天花板上去了。单纯依靠6050的陀螺仪,四轴不旋转的飞几秒,会突然不受控的掉下来,我猜想是yaw角漂走了,导致PID拉不会来。我现在也正在弄HMC5883L也想搞椭圆拟合,或者加进IMU,做成AHRSupdate。我这里有椭圆拟合的资料,正准备研究,还有AHRS的算法,希望对你有所帮助。

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2014-7-25 17:08:04 | 显示全部楼层
BLACKBLUE007 发表于 2014-7-25 14:56
1,{1,0,0,0}初值也可以的,好象前提是你的IMU放置要和代码中规定的一致!
2,half T可以变的,据原文讲应该是 ...

非常感谢你的热心回答,我大二,研究四轴也就一个多月,也是门外汉。然后发现如果不进行yaw的控制四轴也能飞起来,不过会一直旋转,然后就飞天花板上去了。单纯依靠6050的陀螺仪,四轴不旋转的飞几秒,会突然不受控的掉下来,我猜想是yaw角漂走了,导致PID拉不会来。我现在也正在弄HMC5883L也想搞椭圆拟合,或者加进IMU,做成AHRSupdate。我这里有椭圆拟合的资料,正准备研究,还有AHRS的算法,希望对你有所帮助。

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2014-7-27 14:17:19 | 显示全部楼层
BLACKBLUE007 发表于 2014-7-25 14:56
1,{1,0,0,0}初值也可以的,好象前提是你的IMU放置要和代码中规定的一致!
2,half T可以变的,据原文讲应该是 ...

我有matlab的程序,精确度要求不高,可以试试!

出0入0汤圆

 楼主| 发表于 2014-7-27 14:19:55 | 显示全部楼层
幽灵盾 发表于 2014-7-25 13:41
还有,有的程序中注释这个halft必须是采样周期的一半,不能随便调整这个参数吧?难道这是理论和实际的差 ...

我程序里设置100HZ采样,halfT = 1/(2 * smaplefre) samplefre = 100.0f

出0入0汤圆

 楼主| 发表于 2014-7-27 14:21:47 | 显示全部楼层
BLACKBLUE007 发表于 2014-7-25 14:56
1,{1,0,0,0}初值也可以的,好象前提是你的IMU放置要和代码中规定的一致!
2,half T可以变的,据原文讲应该是 ...

可以发过来你的罗盘三轴的原始数据,要绕Z轴转两个360度的数据

出0入0汤圆

发表于 2014-7-28 08:17:58 | 显示全部楼层
caiming1234567 发表于 2014-7-27 14:21
可以发过来你的罗盘三轴的原始数据,要绕Z轴转两个360度的数据


最小二乘法3D校准参数:
float mag_bais[3] = {-26.1372, 78.1749,32.0521}, sclaeFactory_x[3] ={ 227.5400,-4.1942, 5.3723}, sclaeFactory_y[3] ={-4.1942,191.4929,2.2442} , sclaeFactory_z[3] ={5.3723,2.2442,220.0720};

我的罗盘是AK8975:校准输出格式magdata[],0,1,2=x,y,z:

mx = (float)mx_raw - mag_bais[0]
my = (float)my_raw - mag_bais[1]
mz = (float)mz_raw - mag_bais[2]

magdata[0] = sclaeFactory_x[0] * mx +  sclaeFactory_x[1] * my + sclaeFactory_x[2]*mz;   
magdata[1] = sclaeFactory_y[0] * mx +  sclaeFactory_y[1] * my + sclaeFactory_y[2]*mz;   
magdata[2] = sclaeFactory_z[0] * mx +   sclaeFactory_z[1] * my + sclaeFactory_z[2]*mz;   

出0入0汤圆

发表于 2014-7-28 18:21:54 | 显示全部楼层
楼主你好,我刚开始看这个算法,想问下下载的代码中,哪些部分是需要根据情况修改的
halfT如何确定
Kp,Ki如何得到
我现在得到的角度,无论怎么动,两个轴很小,一个轴接近180度。
用该算法需要注意些什么啊?
谢谢!

出0入0汤圆

 楼主| 发表于 2014-7-29 10:43:14 | 显示全部楼层
lianx325 发表于 2014-7-28 18:21
楼主你好,我刚开始看这个算法,想问下下载的代码中,哪些部分是需要根据情况修改的
halfT如何确定
Kp,Ki ...

1.你代码中执行解算函数的频率,即采样频率,我是这么理解的
2.PI的参数,看感觉,数据大了容易过调,就是说,你实际转了45度,输出数据显示先是出现大于45度的值,然后有慢慢回到45,这样是不行的,PI参数大了,2和0.005感觉还行,已经用到飞机上了,主要是准确性和灵敏度;
3.由于坐标系的不同,转欧拉角的公式不同

出0入0汤圆

 楼主| 发表于 2014-7-29 10:45:09 | 显示全部楼层
BLACKBLUE007 发表于 2014-7-28 08:17
最小二乘法3D校准参数:
float mag_bais[3] = {-26.1372, 78.1749,32.0521}, sclaeFactory_x[3] ={ 227. ...

我用的HMC5883l,看你的代码,对数据的处理不一样

出0入0汤圆

发表于 2014-7-29 11:37:23 | 显示全部楼层
caiming1234567 发表于 2014-7-29 10:43
1.你代码中执行解算函数的频率,即采样频率,我是这么理解的
2.PI的参数,看感觉,数据大了容易过调,就 ...

你初始化四元数了吗   怎么初始化

出0入0汤圆

发表于 2014-7-29 13:45:06 | 显示全部楼层
lianx325 发表于 2014-7-29 11:37
你初始化四元数了吗   怎么初始化

1,先校准你的传感器,然后用ACCEL和COMPASS求你当前位置的欧拉角,再由欧拉角求当前位置的四元素即是你当前位置的初始四元素!
(论坛上有主方面的贴的,有详细介绍)
2,所有的工作,都必须先从校准原始传感器值开始,第二步是传感器值的单位化。
3,HALF T要尽可能让它有多快设多快,否则YPR数据出来会慢慢飘.......
4,我的GYRO和ACCEL校准是参照DATASHEET做的,试过很多方法,感觉这种最好!AK8975,则是使用了其他地方找来的方法,目前还没有能力把它写在代码中进行自校准,这个数据用在代码中,YAW数据出来,无论ROLL,PITCH是不是同有时有输出,YAW不会跳变,所以感觉3D球形拟合对三轴罗盘的确有明显作用!

附上我用的传感器自校代码,也是网上找来的,但找的资料很多,记不得出处了(对作者表示感谢)!
(我改写的代码是用在LEGO NXT玩具上的,请自行修改)


void calibrateMPU9150(float * dest1, float * dest2)
{
  ubyte data[12];
  int ii, packet_count, fifo_count;
  long gyro_bias[3]  = {0, 0, 0}, accel_bias[3] = {0, 0, 0};

// reset device, reset all registers, clear gyro and accelerometer bias registers
  writeByte(mpu9150,MPU9150_ADDRESS, PWR_MGMT_1, 0x80); // Write a one to bit 7 reset bit; toggle reset device
  wait1Msec(200);

// get stable time source
// Set clock source to be PLL with x-axis gyroscope reference, bits 2:0 = 001
  writeByte(mpu9150,MPU9150_ADDRESS, PWR_MGMT_1, 0x01);
  writeByte(mpu9150,MPU9150_ADDRESS, PWR_MGMT_2, 0x00);
  wait1Msec(200);

// Configure device for bias calculation
  writeByte(mpu9150,MPU9150_ADDRESS, INT_ENABLE, 0x00);   // Disable all interrupts
  writeByte(mpu9150,MPU9150_ADDRESS, FIFO_EN, 0x00);      // Disable FIFO
  writeByte(mpu9150,MPU9150_ADDRESS, PWR_MGMT_1, 0x00);   // Turn on internal clock source
  writeByte(mpu9150,MPU9150_ADDRESS, I2C_MST_CTRL, 0x00); // Disable I2C master
  writeByte(mpu9150,MPU9150_ADDRESS, USER_CTRL, 0x00);    // Disable FIFO and I2C master modes
  writeByte(mpu9150,MPU9150_ADDRESS, USER_CTRL, 0x0C);    // Reset FIFO and DMP
  wait1Msec(100);

// Configure MPU6050 gyro and accelerometer for bias calculation
  writeByte(mpu9150,MPU9150_ADDRESS, CONFIG, 0x01);      // Set low-pass filter to 188 Hz
  writeByte(mpu9150,MPU9150_ADDRESS, SMPLRT_DIV, 0x00);  // Set sample rate to 1 kHz
  writeByte(mpu9150,MPU9150_ADDRESS, GYRO_CONFIG, 0x00);  // Set gyro full-scale to 250 degrees per second, maximum sensitivity
  writeByte(mpu9150,MPU9150_ADDRESS, ACCEL_CONFIG, 0x00); // Set accelerometer full-scale to 2 g, maximum sensitivity

  int  gyrosensitivity  = 131;   // = 131 LSB/degrees/sec
  int  accelsensitivity = 16384;  // = 16384 LSB/g

// Configure FIFO to capture accelerometer and gyro data for bias calculation
  writeByte(mpu9150,MPU9150_ADDRESS, USER_CTRL, 0x40);   // Enable FIFO
  writeByte(mpu9150,MPU9150_ADDRESS, FIFO_EN, 0x78);     // Enable gyro and accelerometer sensors for FIFO  (max size 1024 bytes in MPU-6050)
  wait1Msec(200);

// At end of sample accumulation, turn off FIFO sensor read
  writeByte(mpu9150,MPU9150_ADDRESS, FIFO_EN, 0x00);        // Disable gyro and accelerometer sensors for FIFO
  readBytes(mpu9150,MPU9150_ADDRESS, FIFO_COUNTH, 2, &data[0]); // read FIFO sample count
  fifo_count = ((int)data[0] << 8) | data[1];
  packet_count = fifo_count/12;// How many sets of full gyro and accelerometer data for averaging

for (ii = 0; ii < packet_count; ii++) {
    int accel_temp[3] = {0, 0, 0}, gyro_temp[3] = {0, 0, 0};
    readBytes(mpu9150,MPU9150_ADDRESS, FIFO_R_W, 12, &data[0]); // read data for averaging
    accel_temp[0] = (int) (((int)data[0] << 8) | data[1]  ) ;  // Form signed 16-bit integer for each sample in FIFO
    accel_temp[1] = (int) (((int)data[2] << 8) | data[3]  ) ;
    accel_temp[2] = (int) (((int)data[4] << 8) | data[5]  ) ;
    gyro_temp[0]  = (int) (((int)data[6] << 8) | data[7]  ) ;
    gyro_temp[1]  = (int) (((int)data[8] << 8) | data[9]  ) ;
    gyro_temp[2]  = (int) (((int)data[10] << 8) | data[11]) ;

    accel_bias[0] += (long) accel_temp[0]; // Sum individual signed 16-bit biases to get accumulated signed 32-bit biases
    accel_bias[1] += (long) accel_temp[1];
    accel_bias[2] += (long) accel_temp[2];
    gyro_bias[0]  += (long) gyro_temp[0];
    gyro_bias[1]  += (long) gyro_temp[1];
    gyro_bias[2]  += (long) gyro_temp[2];

}
    accel_bias[0] /= (long) packet_count; // Normalize sums to get average count biases
    accel_bias[1] /= (long) packet_count;
    accel_bias[2] /= (long) packet_count;
    gyro_bias[0]  /= (long) packet_count;
    gyro_bias[1]  /= (long) packet_count;
    gyro_bias[2]  /= (long) packet_count;

  if(accel_bias[2] > 0.0) {accel_bias[2] -= (long) accelsensitivity;}  // Remove gravity from the z-axis accelerometer bias calculation
  else {accel_bias[2] += (long) accelsensitivity;}

// Construct the gyro biases for push to the hardware gyro bias registers, which are reset to zero upon device startup
  data[0] = (-gyro_bias[0]/4  >> 8) & 0xFF; // Divide by 4 to get 32.9 LSB per deg/s to conform to expected bias input format
  data[1] = (-gyro_bias[0]/4)       & 0xFF; // Biases are additive, so change sign on calculated average gyro biases
  data[2] = (-gyro_bias[1]/4  >> 8) & 0xFF;
  data[3] = (-gyro_bias[1]/4)       & 0xFF;
  data[4] = (-gyro_bias[2]/4  >> 8) & 0xFF;
  data[5] = (-gyro_bias[2]/4)       & 0xFF;

// Push gyro biases to hardware registers
  writeByte(mpu9150,MPU9150_ADDRESS, XG_OFFS_USRH, data[0]);
  writeByte(mpu9150,MPU9150_ADDRESS, XG_OFFS_USRL, data[1]);
  writeByte(mpu9150,MPU9150_ADDRESS, YG_OFFS_USRH, data[2]);
  writeByte(mpu9150,MPU9150_ADDRESS, YG_OFFS_USRL, data[3]);
  writeByte(mpu9150,MPU9150_ADDRESS, ZG_OFFS_USRH, data[4]);
  writeByte(mpu9150,MPU9150_ADDRESS, ZG_OFFS_USRL, data[5]);

// Output scaled gyro biases for display in the main program
  dest1[0] = (float) gyro_bias[0]/(float) gyrosensitivity;
  dest1[1] = (float) gyro_bias[1]/(float) gyrosensitivity;
  dest1[2] = (float) gyro_bias[2]/(float) gyrosensitivity;

// Construct the accelerometer biases for push to the hardware accelerometer bias registers. These registers contain
// factory trim values which must be added to the calculated accelerometer biases; on boot up these registers will hold
// non-zero values. In addition, bit 0 of the lower byte must be preserved since it is used for temperature
// compensation calculations. Accelerometer bias registers expect bias input as 2048 LSB per g, so that
// the accelerometer biases calculated above must be divided by 8.

  long accel_bias_reg[3] = {0, 0, 0}; // A place to hold the factory accelerometer trim biases
  readBytes(mpu9150,MPU9150_ADDRESS, XA_OFFSET_H, 2, &data[0]); // Read factory accelerometer trim values
  accel_bias_reg[0] = (int) ((int)data[0] << 8) | data[1];
  readBytes(mpu9150,MPU9150_ADDRESS, YA_OFFSET_H, 2, &data[0]);
  accel_bias_reg[1] = (int) ((int)data[0] << 8) | data[1];
  readBytes(mpu9150,MPU9150_ADDRESS, ZA_OFFSET_H, 2, &data[0]);
  accel_bias_reg[2] = (int) ((int)data[0] << 8) | data[1];

  long mask = 1; // Define mask for temperature compensation bit 0 of lower byte of accelerometer bias registers
  ubyte mask_bit[3] = {0, 0, 0}; // Define array to hold mask bit for each accelerometer bias axis

  for(ii = 0; ii < 3; ii++) {
    if(accel_bias_reg[ii] & mask) mask_bit[ii] = 0x01; // If temperature compensation bit is set, record that fact in mask_bit
  }

  // Construct total accelerometer bias, including calculated average accelerometer bias from above
  accel_bias_reg[0] -= (accel_bias[0]/8); // Subtract calculated averaged accelerometer bias scaled to 2048 LSB/g (16 g full scale)
  accel_bias_reg[1] -= (accel_bias[1]/8);
  accel_bias_reg[2] -= (accel_bias[2]/8);

  data[0] = (accel_bias_reg[0] >> 8) & 0xFF;
  data[1] = (accel_bias_reg[0])      & 0xFF;
  data[1] = data[1] | mask_bit[0]; // preserve temperature compensation bit when writing back to accelerometer bias registers
  data[2] = (accel_bias_reg[1] >> 8) & 0xFF;
  data[3] = (accel_bias_reg[1])      & 0xFF;
  data[3] = data[3] | mask_bit[1]; // preserve temperature compensation bit when writing back to accelerometer bias registers
  data[4] = (accel_bias_reg[2] >> 8) & 0xFF;
  data[5] = (accel_bias_reg[2])      & 0xFF;
  data[5] = data[5] | mask_bit[2]; // preserve temperature compensation bit when writing back to accelerometer bias registers

  // Push accelerometer biases to hardware registers
  writeByte(mpu9150,MPU9150_ADDRESS, XA_OFFSET_H, data[0]);
  writeByte(mpu9150,MPU9150_ADDRESS, XA_OFFSET_L_TC, data[1]);
  writeByte(mpu9150,MPU9150_ADDRESS, YA_OFFSET_H, data[2]);
  writeByte(mpu9150,MPU9150_ADDRESS, YA_OFFSET_L_TC, data[3]);
  writeByte(mpu9150,MPU9150_ADDRESS, ZA_OFFSET_H, data[4]);
  writeByte(mpu9150,MPU9150_ADDRESS, ZA_OFFSET_L_TC, data[5]);

// Output scaled accelerometer biases for display in the main program
   dest2[0] = (float)accel_bias[0]/(float)accelsensitivity;
   dest2[1] = (float)accel_bias[1]/(float)accelsensitivity;
   dest2[2] = (float)accel_bias[2]/(float)accelsensitivity;
}


// I2C functions to get easier all values
bool waitForI2CBus(tSensors link)
{
while (true)
  {
    switch (nI2CStatus[link])
     {
            case NO_ERR:
              return true;
            case STAT_COMM_PENDING:
              break;
            case ERR_COMM_CHAN_NOT_READY:
              break;
            case ERR_COMM_BUS_ERR:
        return false;
    }
    EndTimeSlice();
  }
}

bool writeByte(tSensors link, ubyte DevAdd, ubyte RegAddr, ubyte Command)
{
   sOutput.nMsgSize = 3;
   sOutput.nDeviceAddress = DevAdd;
   sOutput.nLocationPtr = RegAddr;
   sOutput.nCommand = Command;
   sendI2CMsg(link, &sOutput.nMsgSize,0);
   if (waitForI2CBus(link))
      return true;
   else
     return false;
}

ubyte  readByte( tSensors link, ubyte DevAdd,ubyte RegAddr)
{
     ubyte buffer[1];
     sReadmsg.nMsgSize = 2;
     sReadmsg.nDeviceAddress = DevAdd;
     sReadmsg.nLocationPtr = RegAddr;

      sendI2CMsg(link,&sReadmsg.nMsgSize, 1 );
      if (waitForI2CBus(link))
       {
        readI2CReply(link,&buffer[0],1 );
        //nxtDisplayTextLine(6, "who:%d",buffer[0]);
       }
       return buffer[0];
}

void readBytes(tSensors link,ubyte DevAdd,ubyte RegAddr,ubyte count,ubyte *dest){
     ubyte buffer[6];
                 sReadmsg.nMsgSize = 2;
     sReadmsg.nDeviceAddress = DevAdd;
     sReadmsg.nLocationPtr = RegAddr;

     sendI2CMsg(link,&sReadmsg.nMsgSize,count);
      if (waitForI2CBus(link))
       {
        readI2CReply(link, &buffer[0],count);
       }
       for (ubyte i=0;i<count;i++){
         dest = buffer;}
}

出0入0汤圆

发表于 2014-7-29 14:58:44 | 显示全部楼层
BLACKBLUE007 发表于 2014-7-29 13:45
1,先校准你的传感器,然后用ACCEL和COMPASS求你当前位置的欧拉角,再由欧拉角求当前位置的四元素即是你 ...

你好,我刚接触这个东西,可以加个好友聊聊吗?

出0入0汤圆

 楼主| 发表于 2014-7-30 10:06:23 | 显示全部楼层
lianx325 发表于 2014-7-29 11:37
你初始化四元数了吗   怎么初始化

不是{1,0,0,0}吗?

出0入0汤圆

发表于 2014-8-28 10:32:57 | 显示全部楼层
BLACKBLUE007 发表于 2014-6-14 10:27
正好我也在试用这个算法,也是在ARDUINO上!

你的代码只是其中的一段,所以无从知道你的HALFT取值是多大?另 ...

楼主,,请问那个Halft到底是怎么算出来的呀??指的到底是什么的周期啊

出0入0汤圆

发表于 2014-8-28 18:31:34 | 显示全部楼层
我是来学习学习的

出0入0汤圆

发表于 2014-9-9 18:56:49 | 显示全部楼层
caiming1234567 发表于 2014-7-27 14:19
我程序里设置100HZ采样,halfT = 1/(2 * smaplefre) samplefre = 100.0f

我也大三了 0 0 话说做的怎样了~~~~~~

出0入0汤圆

发表于 2016-5-10 17:19:12 | 显示全部楼层
BLACKBLUE007 发表于 2014-7-29 13:45
1,先校准你的传感器,然后用ACCEL和COMPASS求你当前位置的欧拉角,再由欧拉角求当前位置的四元素即是你 ...

请问,你还有3D校准的程序吗? 我看你给出的程序是加速度计和陀螺仪的

出0入0汤圆

发表于 2018-3-13 16:41:24 | 显示全部楼层
加速度计+陀螺仪能得到欧拉角吗
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-28 00:34

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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