基于MPU9250的IMU库,可以测量pitch,roll,yaw,compass

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers imu.cpp Source File

imu.cpp

00001 #include "imu.h"
00002 
00003 I2C i2c(I2C_SDA,I2C_SCL);
00004 
00005 /**
00006   * @brief  invSqrt
00007   * @param  
00008   * @retval 
00009   */
00010 float IMU::invSqrt(float x) 
00011 {
00012     float halfx = 0.5f * x;
00013     float y = x;
00014     
00015     long i = *(long*)&y;                //get bits for floating value
00016     i = 0x5f3759df - (i >> 1);          //gives initial guss you
00017     y = *(float*)&i;                    //convert bits back to float
00018     y = y * (1.5f - (halfx * y * y));   //newtop step, repeating increases accuracy
00019     
00020     return y;
00021 }
00022 
00023 /**
00024   * @brief  initializes IMU
00025   * @param  None
00026   * @retval None
00027   */
00028 void IMU::IMU_Init()
00029 {    
00030     MPU9250_Init();
00031     BMP180_Init();
00032     
00033     q0 = 1.0f;  
00034     q1 = 0.0f;
00035     q2 = 0.0f;
00036     q3 = 0.0f;
00037 }
00038 
00039 /**
00040   * @brief  Updata attitude and heading 
00041   * @param  ax: accelerometer X
00042   * @param  ay: accelerometer Y
00043   * @param  az: accelerometer Z
00044   * @param  gx: gyroscopes X
00045   * @param  gy: gyroscopes Y
00046   * @param  gz: gyroscopes Z
00047   * @param  mx: magnetometer X
00048   * @param  my: magnetometer Y
00049   * @param  mz: magnetometer Z
00050   * @retval None
00051   */
00052 void IMU::IMU_AHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) 
00053 {
00054     float norm;
00055     float hx, hy, hz, bx, bz;
00056     float vx, vy, vz, wx, wy, wz;
00057     float exInt = 0.0, eyInt = 0.0, ezInt = 0.0;
00058     float ex, ey, ez, halfT = 0.024f;
00059 
00060     float q0q0 = q0 * q0;
00061     float q0q1 = q0 * q1;
00062     float q0q2 = q0 * q2;
00063     float q0q3 = q0 * q3;
00064     float q1q1 = q1 * q1;
00065     float q1q2 = q1 * q2;
00066     float q1q3 = q1 * q3;
00067     float q2q2 = q2 * q2;   
00068     float q2q3 = q2 * q3;
00069     float q3q3 = q3 * q3;          
00070 
00071     norm = invSqrt(ax * ax + ay * ay + az * az);       
00072     ax = ax * norm;
00073     ay = ay * norm;
00074     az = az * norm;
00075 
00076     norm = invSqrt(mx * mx + my * my + mz * mz);          
00077     mx = mx * norm;
00078     my = my * norm;
00079     mz = mz * norm;
00080 
00081     // compute reference direction of flux
00082     hx = 2 * mx * (0.5f - q2q2 - q3q3) + 2 * my * (q1q2 - q0q3) + 2 * mz * (q1q3 + q0q2);
00083     hy = 2 * mx * (q1q2 + q0q3) + 2 * my * (0.5f - q1q1 - q3q3) + 2 * mz * (q2q3 - q0q1);
00084     hz = 2 * mx * (q1q3 - q0q2) + 2 * my * (q2q3 + q0q1) + 2 * mz * (0.5f - q1q1 - q2q2);         
00085     bx = sqrt((hx * hx) + (hy * hy));
00086     bz = hz;     
00087 
00088     // estimated direction of gravity and flux (v and w)
00089     vx = 2 * (q1q3 - q0q2);
00090     vy = 2 * (q0q1 + q2q3);
00091     vz = q0q0 - q1q1 - q2q2 + q3q3;
00092     wx = 2 * bx * (0.5 - q2q2 - q3q3) + 2 * bz * (q1q3 - q0q2);
00093     wy = 2 * bx * (q1q2 - q0q3) + 2 * bz * (q0q1 + q2q3);
00094     wz = 2 * bx * (q0q2 + q1q3) + 2 * bz * (0.5 - q1q1 - q2q2);  
00095 
00096     // error is sum of cross product between reference direction of fields and direction measured by sensors
00097     ex = (ay * vz - az * vy) + (my * wz - mz * wy);
00098     ey = (az * vx - ax * vz) + (mz * wx - mx * wz);
00099     ez = (ax * vy - ay * vx) + (mx * wy - my * wx);
00100 
00101     if(ex != 0.0f && ey != 0.0f && ez != 0.0f)
00102     {
00103         exInt = exInt + ex * Ki * halfT;
00104         eyInt = eyInt + ey * Ki * halfT;    
00105         ezInt = ezInt + ez * Ki * halfT;
00106 
00107         gx = gx + Kp * ex + exInt;
00108         gy = gy + Kp * ey + eyInt;
00109         gz = gz + Kp * ez + ezInt;
00110     }
00111 
00112     q0 = q0 + (-q1 * gx - q2 * gy - q3 * gz) * halfT;
00113     q1 = q1 + (q0 * gx + q2 * gz - q3 * gy) * halfT;
00114     q2 = q2 + (q0 * gy - q1 * gz + q3 * gx) * halfT;
00115     q3 = q3 + (q0 * gz + q1 * gy - q2 * gx) * halfT;  
00116 
00117     norm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
00118     q0 = q0 * norm;
00119     q1 = q1 * norm;
00120     q2 = q2 * norm;
00121     q3 = q3 * norm;
00122 }
00123 
00124 /**
00125   * @brief  Get quaters
00126   * @param  None
00127   * @retval None
00128   */
00129 void IMU::IMU_GetQuater(void)
00130 {
00131     float MotionVal[9];
00132             
00133     MPU9250_READ_ACCEL();
00134     MPU9250_READ_GYRO();
00135     MPU9250_READ_MAG();
00136 
00137     MotionVal[0]=gyro[0]/32.8;
00138     MotionVal[1]=gyro[1]/32.8;
00139     MotionVal[2]=gyro[2]/32.8;
00140     MotionVal[3]=accel[0];
00141     MotionVal[4]=accel[1];
00142     MotionVal[5]=accel[2];
00143     MotionVal[6]=magn[0];
00144     MotionVal[7]=magn[1];
00145     MotionVal[8]=magn[2];
00146     
00147     IMU_AHRSupdate((float)MotionVal[0] * 0.0175, (float)MotionVal[1] * 0.0175, (float)MotionVal[2] * 0.0175,
00148     (float)MotionVal[3], (float)MotionVal[4], (float)MotionVal[5], (float)MotionVal[6], (float)MotionVal[7], MotionVal[8]);
00149 }
00150 
00151 /**
00152   * @brief  Get Yaw Pitch Roll
00153   * @param  None
00154   * @retval None
00155   */
00156 void IMU::IMU_GetYawPitchRoll(float *Angles) 
00157 {
00158     
00159     int x_tmp,y_tmp;
00160     
00161     IMU_GetQuater(); 
00162     
00163     x_tmp = magn[0];
00164     y_tmp = magn[1];
00165     if(x_tmp>0x7fff)x_tmp-=0xffff;    
00166     if(y_tmp>0x7fff)y_tmp-=0xffff;  
00167       
00168     Angles[1] = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch
00169     Angles[2] = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
00170     Angles[0] = atan2(-2 * q1 * q2 - 2 * q0 * q3, 2 * q2 * q2 + 2 * q3 * q3 - 1) * 57.3;   //Yaw
00171     Angles[3] = atan2((double)(y_tmp) , (double)(x_tmp)) * (180 / 3.14159265) + 180; // Compass angle in degrees
00172     
00173     
00174 }
00175 
00176 /************************************************************/
00177 //下面的代码是MPU9250的各种操作
00178 /************************************************************/
00179 void IMU::I2C_WriteOneByte(uint8_t DevAddr, uint8_t RegAddr, uint8_t Data)
00180 {
00181     char data_write[2];
00182     
00183     data_write[0] = RegAddr;
00184     data_write[1] = Data;
00185     
00186     i2c.write(DevAddr,data_write,2,0);
00187 }
00188 
00189 uint8_t IMU::I2C_ReadOneByte(uint8_t DevAddr, uint8_t RegAddr)
00190 {
00191     char data_write[2];
00192     char data_read[2];
00193     char data;
00194     
00195     data_write[0] = RegAddr;
00196     
00197     i2c.write(DevAddr,data_write,1,1);
00198     i2c.read(DevAddr,data_read,1,0);
00199     
00200     data = data_read[0];
00201     
00202     return data;
00203 }
00204 
00205 void IMU::BMP180_ReadReg(uint8_t RegAddr, uint8_t Num, char *pBuffer) 
00206 {
00207     char data_write[2];
00208     char DevAddr = BMP180_ADDR;
00209     
00210     data_write[0] = RegAddr;
00211     i2c.write(DevAddr, data_write, 1, 1);
00212     i2c.read(DevAddr, pBuffer, Num, 0);
00213 }
00214 /**
00215   * @brief  Initializes MPU9250
00216   * @param  None
00217   * @retval None
00218   */
00219 void IMU::MPU9250_Init()
00220 {
00221     I2C_WriteOneByte(GYRO_ADDRESS,PWR_MGMT_1, 0x00);
00222     I2C_WriteOneByte(GYRO_ADDRESS,SMPLRT_DIV, 0x07);
00223     I2C_WriteOneByte(GYRO_ADDRESS,CONFIG, 0x06);
00224     I2C_WriteOneByte(GYRO_ADDRESS,GYRO_CONFIG, 0x10);
00225     I2C_WriteOneByte(GYRO_ADDRESS,ACCEL_CONFIG, 0x01);
00226     
00227     Thread::wait(10);
00228     
00229     if(MPU9250_Check())
00230     {
00231         printf("\r\n MPU9255 Ready!\n");
00232     }
00233     else
00234     {
00235         printf("\r\n MPU9255 Erro!\n");
00236     }
00237     
00238     MPU9250_InitGyrOffset();
00239 }
00240 
00241 /**
00242   * @brief  Digital filter
00243   * @param *pIndex:
00244   * @param *pAvgBuffer:
00245   * @param InVal:
00246   * @param pOutVal:
00247   *
00248   * @retval None
00249   *               
00250   */
00251 void IMU::MPU9250_CalAvgValue(uint8_t *pIndex, int16_t *pAvgBuffer, int16_t InVal, int32_t *pOutVal)
00252 {   
00253     uint8_t i;
00254     
00255     *(pAvgBuffer + ((*pIndex) ++)) = InVal;
00256     *pIndex &= 0x07;
00257     
00258     *pOutVal = 0;
00259     for(i = 0; i < 8; i ++) 
00260     {
00261         *pOutVal += *(pAvgBuffer + i);
00262     }
00263     *pOutVal >>= 3;
00264 }
00265 
00266 /**
00267   * @brief Get accelerometer datas
00268   * @param  None
00269   * @retval None
00270   */
00271 void IMU::MPU9250_READ_ACCEL(void)
00272 { 
00273     uint8_t i;
00274     int16_t InBuffer[3] = {0}; 
00275     static int32_t OutBuffer[3] = {0};
00276     static MPU9250_AvgTypeDef MPU9250_Filter[3];
00277     
00278    BUF[0]=I2C_ReadOneByte(ACCEL_ADDRESS,ACCEL_XOUT_L); 
00279    BUF[1]=I2C_ReadOneByte(ACCEL_ADDRESS,ACCEL_XOUT_H);
00280    InBuffer[0]= (BUF[1]<<8)|BUF[0];
00281 
00282    BUF[2]=I2C_ReadOneByte(ACCEL_ADDRESS,ACCEL_YOUT_L);
00283    BUF[3]=I2C_ReadOneByte(ACCEL_ADDRESS,ACCEL_YOUT_H);
00284    InBuffer[1]= (BUF[3]<<8)|BUF[2];
00285                        
00286    BUF[4]=I2C_ReadOneByte(ACCEL_ADDRESS,ACCEL_ZOUT_L);
00287    BUF[5]=I2C_ReadOneByte(ACCEL_ADDRESS,ACCEL_ZOUT_H);
00288    InBuffer[2]= (BUF[5]<<8)|BUF[4];                
00289    
00290    for(i = 0; i < 3; i ++)  
00291    {
00292       MPU9250_CalAvgValue(&MPU9250_Filter[i].Index, MPU9250_Filter[i].AvgBuffer, InBuffer[i], OutBuffer + i);
00293    }
00294    accel[0] = *(OutBuffer + 0);
00295    accel[1] = *(OutBuffer + 1);
00296    accel[2] = *(OutBuffer + 2); 
00297 }
00298 
00299 /**
00300   * @brief Get gyroscopes datas
00301   * @param  None
00302   * @retval None
00303   */
00304 void IMU::MPU9250_READ_GYRO(void)
00305 { 
00306      uint8_t i;
00307      int16_t InBuffer[3] = {0}; 
00308      static int32_t OutBuffer[3] = {0};
00309      static MPU9250_AvgTypeDef MPU9250_Filter[3];
00310 
00311    BUF[0]=I2C_ReadOneByte(GYRO_ADDRESS,GYRO_XOUT_L); 
00312    BUF[1]=I2C_ReadOneByte(GYRO_ADDRESS,GYRO_XOUT_H);
00313    InBuffer[0]= (BUF[1]<<8)|BUF[0];
00314    
00315    BUF[2]=I2C_ReadOneByte(GYRO_ADDRESS,GYRO_YOUT_L);
00316    BUF[3]=I2C_ReadOneByte(GYRO_ADDRESS,GYRO_YOUT_H);
00317    InBuffer[1] = (BUF[3]<<8)|BUF[2];
00318     
00319    BUF[4]=I2C_ReadOneByte(GYRO_ADDRESS,GYRO_ZOUT_L);
00320    BUF[5]=I2C_ReadOneByte(GYRO_ADDRESS,GYRO_ZOUT_H);
00321    InBuffer[2] = (BUF[5]<<8)|BUF[4];    
00322 
00323    for(i = 0; i < 3; i ++)  
00324    {
00325       MPU9250_CalAvgValue(&MPU9250_Filter[i].Index, MPU9250_Filter[i].AvgBuffer, InBuffer[i], OutBuffer + i);
00326    }
00327    gyro[0] = *(OutBuffer + 0) - MPU9250_Offset.X;
00328    gyro[1] = *(OutBuffer + 1) - MPU9250_Offset.Y;
00329    gyro[2] = *(OutBuffer + 2) - MPU9250_Offset.Z;
00330 }
00331 
00332 /**
00333   * @brief Get compass datas
00334   * @param  None
00335   * @retval None
00336   */
00337 void IMU::MPU9250_READ_MAG(void)
00338 { 
00339      uint8_t i;
00340      int16_t InBuffer[3] = {0}; 
00341      static int32_t OutBuffer[3] = {0};
00342      static MPU9250_AvgTypeDef MPU9250_Filter[3];
00343 
00344     I2C_WriteOneByte(GYRO_ADDRESS,0x37,0x02);//turn on Bypass Mode 
00345     Thread::wait(10);
00346     I2C_WriteOneByte(MAG_ADDRESS,0x0A,0x01);    
00347     Thread::wait(10);
00348     BUF[0]=I2C_ReadOneByte (MAG_ADDRESS,MAG_XOUT_L);
00349     BUF[1]=I2C_ReadOneByte (MAG_ADDRESS,MAG_XOUT_H);
00350     InBuffer[1] =(BUF[1]<<8)|BUF[0];
00351 
00352     BUF[2]=I2C_ReadOneByte(MAG_ADDRESS,MAG_YOUT_L);
00353     BUF[3]=I2C_ReadOneByte(MAG_ADDRESS,MAG_YOUT_H);
00354     InBuffer[0] =   (BUF[3]<<8)|BUF[2];
00355     
00356     BUF[4]=I2C_ReadOneByte(MAG_ADDRESS,MAG_ZOUT_L);
00357     BUF[5]=I2C_ReadOneByte(MAG_ADDRESS,MAG_ZOUT_H);
00358     InBuffer[2] =   (BUF[5]<<8)|BUF[4]; 
00359     InBuffer[2] = -InBuffer[2];
00360      
00361    for(i = 0; i < 3; i ++)  
00362    {
00363       MPU9250_CalAvgValue(&MPU9250_Filter[i].Index, MPU9250_Filter[i].AvgBuffer, InBuffer[i], OutBuffer + i);
00364    } 
00365         magn[0] = *(OutBuffer + 0)-MPU9250_Magn_Offset.X_Off_Err;
00366         magn[1] = *(OutBuffer + 1)-MPU9250_Magn_Offset.Y_Off_Err;
00367         magn[2] = *(OutBuffer + 2)-MPU9250_Magn_Offset.Z_Off_Err;
00368 }
00369 
00370 /**
00371   * @brief  Check MPU9250,ensure communication succeed
00372   * @param  None
00373   * @retval true: communicate succeed
00374   *               false: communicate fualt 
00375   */
00376 bool IMU::MPU9250_Check(void) 
00377 {
00378     if(WHO_AM_I_VAL == I2C_ReadOneByte(DEFAULT_ADDRESS, WHO_AM_I))  
00379     {
00380         return true;
00381     }
00382     else 
00383     {
00384         return false;
00385     }   
00386 }
00387 
00388 /**
00389   * @brief  Initializes gyroscopes offset
00390   * @param  None
00391   * @retval None
00392   */
00393 void IMU::MPU9250_InitGyrOffset(void)
00394 {
00395     uint8_t i;
00396     int32_t TempGx = 0, TempGy = 0, TempGz = 0;
00397     
00398     for(i = 0; i < 32; i ++)
00399     {
00400         MPU9250_READ_GYRO();
00401         
00402         TempGx += gyro[0];
00403         TempGy += gyro[1];
00404         TempGz += gyro[2];
00405 
00406         Thread::wait(1);
00407     }
00408 
00409     MPU9250_Offset.X = TempGx >> 5;
00410     MPU9250_Offset.Y = TempGy >> 5;
00411     MPU9250_Offset.Z = TempGz >> 5;
00412 
00413 }
00414 
00415 //******************************************************
00416 //下面的代码是BMP180
00417 //******************************************************
00418 /**
00419   * @brief  Digital filter
00420   * @param *pIndex:
00421   * @param *pAvgBuffer:
00422   * @param InVal:
00423   * @param pOutVal:
00424   *
00425   * @retval None
00426   *               
00427   */
00428 void IMU::BMP180_CalAvgValue(uint8_t *pIndex, int32_t *pAvgBuffer, int32_t InVal, int32_t *pOutVal)
00429 {   
00430     uint8_t i;
00431     
00432     *(pAvgBuffer + ((*pIndex) ++)) = InVal;
00433     *pIndex &= 0x07;
00434     
00435     *pOutVal = 0;
00436     for(i = 0; i < 8; i ++) 
00437     {
00438         *pOutVal += *(pAvgBuffer + i);
00439     }
00440     *pOutVal >>= 3;
00441 }
00442 
00443 /**
00444   * @brief  Start temperature measurement
00445   * @param  None
00446   * @retval None
00447   */
00448 void IMU::BMP180_StartTemperatureMeasurement(void)
00449 {
00450     //BMP180_WriteReg(CONTROL, READ_TEMPERATURE); 
00451     I2C_WriteOneByte(BMP180_ADDR, CONTROL, READ_TEMPERATURE);
00452 }
00453 
00454 /**
00455   * @brief  Start pressure measurement
00456   * @param  None
00457   * @retval None
00458   */
00459 void IMU::BMP180_StartPressureMeasurement(void)
00460 {
00461     //BMP180_WriteReg(CONTROL, READ_PRESSURE + (_oss << 6)); 
00462     I2C_WriteOneByte(BMP180_ADDR, CONTROL, READ_PRESSURE + (_oss << 6));
00463 }
00464 
00465 /**
00466   * @brief  Read uncompensated temperature
00467   * @param  None
00468   * @retval None
00469   */
00470 void IMU::BMP180_ReadUncompensatedTemperature(void)
00471 {
00472     char RegBuff[2];
00473     BMP180_ReadReg(CONTROL_OUTPUT, 2, &RegBuff[0]); 
00474 
00475     UT = ((int32_t)RegBuff[0] << 8) + (int32_t)RegBuff[1]; 
00476 }
00477 
00478 /**
00479   * @brief  Read uncompensated pressure
00480   * @param  None
00481   * @retval None
00482   */
00483 void IMU::BMP180_ReadUncompensatedPressure(void)
00484 {
00485     char RegBuff[3];
00486     
00487     BMP180_ReadReg(CONTROL_OUTPUT, 3, &RegBuff[0]); 
00488     
00489     UP = (((int32_t)RegBuff[0] << 16) + ((int32_t)RegBuff[1] << 8) + ((int32_t)RegBuff[2])) >> (8 -_oss); // uncompensated pressure value
00490 }
00491 
00492 /**
00493   * @brief  Calculate true temperature
00494   * @param  *pTrueTemperature: true temperature 
00495   * @retval None
00496   */
00497 void IMU::BMP180_CalculateTrueTemperature(int32_t *pTrueTemperature)
00498 {
00499     int32_t X1, X2;
00500     
00501     X1 = ((UT - AC6) * AC5) >> 15;
00502     X2 = (MC << 11) / (X1 + MD);
00503     B5 = X1 + X2;
00504     *pTrueTemperature = (B5 + 8) >> 4;
00505 }
00506 
00507 /**
00508   * @brief  Calculate true pressure
00509   * @param  *pTruePressure: true pressure
00510   * @retval None
00511   */
00512 void IMU::BMP180_CalculateTruePressure(int32_t *pTruePressure)
00513 {
00514     int32_t X1, X2, X3, B3, B6, P, Temp;
00515     uint32_t  B4, B7;
00516     
00517     B6 = B5 - 4000;             
00518     X1 = (B2* ((B6 * B6) >> 12)) >> 11;
00519     X2 = AC2 * B6 >> 11;
00520     X3 = X1 + X2;
00521     Temp = (((int32_t)AC1 << 2) + X3) << _oss;
00522     B3 = (Temp + 2) >> 2;
00523     X1 = (AC3 * B6) >> 13;
00524     X2 = (B1 * (B6 * B6 >> 12)) >> 16;
00525     X3 = ((X1 + X2) + 2) >> 2;
00526     B4 = (AC4 * (uint32_t) (X3 + 32768)) >> 15;
00527     B7 = ((uint32_t)UP - B3) * (50000 >> _oss);
00528     if(B7 < 0x80000000)
00529     {
00530         P = (B7 << 1) / B4;
00531     }   
00532     else
00533     {
00534         P = (B7 / B4) << 1;
00535     }
00536 
00537     X1 = (P >> 8) * (P >> 8);
00538     X1 = (X1 * 3038) >> 16;
00539     X2 = (-7357 * P) >> 16;
00540     
00541     *pTruePressure = P + ((X1 + X2 + 3791) >> 4);
00542 }
00543 
00544 /**
00545   * @brief  Calculating average value of pressure
00546   * @param  *pVal: the average value of pressure
00547   * @retval None
00548   */
00549 void IMU::BMP180_LocalpressureAvg(int32_t *pVal)
00550 {
00551     uint8_t i;
00552     int32_t Sum = 0;
00553     
00554     for(i = 0; i < 5; i ++)
00555     {
00556         BMP180_StartTemperatureMeasurement();
00557         Thread::wait(5);//delay_ms(5); //4.5ms   324
00558         BMP180_ReadUncompensatedTemperature();
00559         BMP180_StartPressureMeasurement();
00560         Thread::wait(5);//delay_ms(8);//7.5ms    540
00561         BMP180_ReadUncompensatedPressure();
00562         BMP180_CalculateTruePressure(&PressureVal);
00563         BMP180_CalculateTrueTemperature(&TemperatureVal);
00564         
00565         if(i >= 2)
00566         {
00567             Sum += PressureVal;
00568         }
00569     }
00570     *pVal = Sum / 3;
00571 }
00572 
00573 /** 
00574   * @brief  Calculating pressure at sea level
00575   * @param  None
00576   * @retval None
00577   */
00578 void IMU::BMP180_PressureAtSeaLevel(void)
00579 {  
00580     float Temp = 0.0f;
00581     
00582     BMP180_LocalpressureAvg(&PressureVal);
00583     
00584     Temp = (float)LOCAL_ADS_ALTITUDE / 4433000;
00585     Temp = (float)pow((1 - Temp), 5.255f);
00586     Pressure0 = (PressureVal - PRESSURE_OFFSET) / Temp;//
00587 }
00588 
00589 /** 
00590   * @brief  Calculating absolute altitude
00591   * @param  *pAltitude: absolute altitude
00592   * @param  PressureVal: the pressure at the absolute altitude
00593   * @retval None
00594   */
00595 void IMU::BMP180_CalculateAbsoluteAltitude(int32_t *pAltitude, int32_t PressureVal)
00596 {
00597     *pAltitude = 4433000 * (1 - pow((float)(PressureVal / (float)Pressure0), 0.1903f)); 
00598 }
00599 
00600 /**
00601   * @brief  Read calibration data from the EEPROM of the BMP180
00602   * @param  None
00603   * @retval None
00604   */
00605 void IMU::BMP180_ReadCalibrationData(void) 
00606 {
00607     char RegBuff[2];
00608 
00609     BMP180_ReadReg(CAL_AC1, 2, RegBuff);
00610     AC1 = ((int16_t)RegBuff[0] <<8 | ((int16_t)RegBuff[1]));
00611     
00612     BMP180_ReadReg(CAL_AC2, 2, RegBuff);
00613     AC2 = ((int16_t)RegBuff[0] <<8 | ((int16_t)RegBuff[1]));
00614     
00615     BMP180_ReadReg(CAL_AC3, 2, RegBuff);
00616     AC3 = ((int16_t)RegBuff[0] <<8 | ((int16_t)RegBuff[1]));
00617     
00618     BMP180_ReadReg(CAL_AC4, 2, RegBuff);
00619     AC4 = ((uint16_t)RegBuff[0] <<8 | ((uint16_t)RegBuff[1]));
00620     
00621     BMP180_ReadReg(CAL_AC5, 2, RegBuff);
00622     AC5 = ((uint16_t)RegBuff[0] <<8 | ((uint16_t)RegBuff[1]));
00623     
00624     BMP180_ReadReg(CAL_AC6, 2, RegBuff);
00625     AC6 = ((uint16_t)RegBuff[0] <<8 | ((uint16_t)RegBuff[1])); 
00626     
00627     BMP180_ReadReg(CAL_B1, 2, RegBuff);
00628     B1 = ((int16_t)RegBuff[0] <<8 | ((int16_t)RegBuff[1])); 
00629     
00630     BMP180_ReadReg(CAL_B2, 2, RegBuff);
00631     B2 = ((int16_t)RegBuff[0] <<8 | ((int16_t)RegBuff[1]));
00632      
00633     BMP180_ReadReg(CAL_MB, 2, RegBuff);
00634     MB = ((int16_t)RegBuff[0] <<8 | ((int16_t)RegBuff[1]));
00635     
00636     BMP180_ReadReg(CAL_MC, 2, RegBuff);
00637     MC = ((int16_t)RegBuff[0] <<8 | ((int16_t)RegBuff[1]));
00638     
00639     BMP180_ReadReg(CAL_MD, 2, RegBuff);
00640     MD = ((int16_t)RegBuff[0] <<8 | ((int16_t)RegBuff[1])); 
00641 }
00642 
00643 /**
00644   * @brief  Configures hardware pressure sampling accuracy modes
00645   * @param  None
00646   * @retval None
00647   */
00648 void IMU::BMP180_SetOversample(void)
00649 {
00650     _oss = MODE_ULTRA_HIGHRES;
00651 }
00652 
00653 /**
00654   * @brief  initializes BMP180
00655   * @param  None
00656   * @retval None
00657   */
00658 void IMU::BMP180_Init(void) 
00659 {  
00660     BMP180_SetOversample();
00661     BMP180_ReadCalibrationData();
00662     //BMP180_PressureAtSeaLevel();
00663 }
00664 
00665 /**
00666   * @brief  Calculation of pressure and temperature and altitude for BMP180
00667   * @param  None
00668   * @retval None
00669   */
00670 void IMU::CalTemperatureAndPressureAndAltitude(void)
00671 {
00672     static uint8_t State = START_TEMPERATURE_MEASUREMENT;
00673     static BMP180_AvgTypeDef BMP180_Filter[3];
00674     int32_t PVal,AVal, TVal;
00675 
00676     switch(State)
00677     {
00678         case START_TEMPERATURE_MEASUREMENT:
00679             BMP180_StartTemperatureMeasurement();
00680             Thread::wait(5);//delay_ms(5); //4.5ms
00681             State = READ_UT_AND_START_PRESSURE_MEASUREMENT;
00682             break;
00683             
00684         case READ_UT_AND_START_PRESSURE_MEASUREMENT:
00685             BMP180_ReadUncompensatedTemperature();
00686             BMP180_StartPressureMeasurement();
00687             Thread::wait(10);//delay_ms(10);//7.5ms
00688             State = READ_UP_CAL_TRUE_PRESSURE_TEMPERATURE;
00689             break;
00690             
00691         case READ_UP_CAL_TRUE_PRESSURE_TEMPERATURE:
00692             BMP180_ReadUncompensatedPressure();
00693             BMP180_CalculateTruePressure(&PVal);
00694             BMP180_CalAvgValue(&BMP180_Filter[0].Index, BMP180_Filter[0].AvgBuffer, PVal - PRESSURE_OFFSET, &PressureVal);
00695 
00696             BMP180_CalculateAbsoluteAltitude(&AVal, PVal - PRESSURE_OFFSET);
00697             BMP180_CalAvgValue(&BMP180_Filter[1].Index, BMP180_Filter[1].AvgBuffer, AVal, &AltitudeVal);
00698 
00699             BMP180_CalculateTrueTemperature(&TVal);
00700             BMP180_CalAvgValue(&BMP180_Filter[2].Index, BMP180_Filter[2].AvgBuffer, TVal, &TemperatureVal);
00701 
00702             State = START_TEMPERATURE_MEASUREMENT;
00703             break;
00704 
00705         default:
00706             break;
00707     }   
00708 }