Corrected header file include guards.
Fork of IMUdriver by
Embed:
(wiki syntax)
Show/hide line numbers
MPU6000.cpp
00001 /*CODED by Bruno Alfano on 07/03/2014 00002 www.xene.it 00003 */ 00004 00005 #include <mbed.h> 00006 #include "MPU6000.h" 00007 #include "float.h" 00008 00009 mpu6000_spi::mpu6000_spi(SPI& _spi, PinName _cs) : spi(_spi), cs(_cs), accFilterCurrent(0), accFilterPre(0), gyroFilterCurrent(0), gyroFliterPre(0) {} 00010 00011 /*----------------------------------------------------------------------------------------------- 00012 INITIALIZATION 00013 usage: call this function at startup, giving the sample rate divider (raging from 0 to 255) and 00014 low pass filter value; suitable values are: 00015 BITS_DLPF_CFG_256HZ_NOLPF2 00016 BITS_DLPF_CFG_188HZ 00017 BITS_DLPF_CFG_98HZ 00018 BITS_DLPF_CFG_42HZ 00019 BITS_DLPF_CFG_20HZ 00020 BITS_DLPF_CFG_10HZ 00021 BITS_DLPF_CFG_5HZ 00022 BITS_DLPF_CFG_2100HZ_NOLPF 00023 returns 1 if an error occurred 00024 -----------------------------------------------------------------------------------------------*/ 00025 bool mpu6000_spi::init(int sample_rate_div,int low_pass_filter) 00026 { 00027 unsigned int response; 00028 spi.format(8,0); 00029 spi.frequency(10000000); 00030 //FIRST OF ALL DISABLE I2C 00031 select(); 00032 response=spi.write(MPUREG_USER_CTRL); 00033 response=spi.write(BIT_I2C_IF_DIS); 00034 deselect(); 00035 //RESET CHIP 00036 select(); 00037 response=spi.write(MPUREG_PWR_MGMT_1); 00038 response=spi.write(BIT_H_RESET); 00039 deselect(); 00040 wait(0.15); 00041 //WAKE UP AND SET GYROZ CLOCK 00042 select(); 00043 response=spi.write(MPUREG_PWR_MGMT_1); 00044 response=spi.write(MPU_CLK_SEL_PLLGYROZ); 00045 deselect(); 00046 //DISABLE I2C 00047 select(); 00048 response=spi.write(MPUREG_USER_CTRL); 00049 response=spi.write(BIT_I2C_IF_DIS); 00050 deselect(); 00051 00052 //WHO AM I? 00053 // Begin transmission 00054 select(); 00055 // Bitwise OR of WHOAMI Register (default 0x68) and READ_FLAG 00056 response=spi.write(MPUREG_WHOAMI|READ_FLAG); 00057 response=spi.write(0x00); 00058 // end transmission 00059 deselect(); 00060 if(response<100) { 00061 return 0; //COULDN'T RECEIVE WHOAMI 00062 } 00063 00064 //SET SAMPLE RATE 00065 select(); 00066 response=spi.write(MPUREG_SMPLRT_DIV); 00067 response=spi.write(sample_rate_div); 00068 deselect(); 00069 // FS & DLPF 00070 select(); 00071 response=spi.write(MPUREG_CONFIG); 00072 response=spi.write(low_pass_filter); 00073 deselect(); 00074 //DISABLE INTERRUPTS 00075 select(); 00076 response=spi.write(MPUREG_INT_ENABLE); 00077 response=spi.write(0x00); 00078 deselect(); 00079 return 0; 00080 } 00081 00082 /*----------------------------------------------------------------------------------------------- 00083 ACCELEROMETER SCALE 00084 usage: call this function at startup, after initialization, to set the right range for the 00085 accelerometers. Suitable ranges are: 00086 BITS_FS_2G 00087 BITS_FS_4G 00088 BITS_FS_8G 00089 BITS_FS_16G 00090 returns the range set (2,4,8 or 16) 00091 -----------------------------------------------------------------------------------------------*/ 00092 unsigned int mpu6000_spi::set_acc_scale(int scale) 00093 { 00094 unsigned int temp_scale; 00095 select(); 00096 spi.write(MPUREG_ACCEL_CONFIG); 00097 spi.write(scale); 00098 deselect(); 00099 switch (scale) { 00100 case BITS_FS_2G: 00101 acc_divider=16384; 00102 break; 00103 case BITS_FS_4G: 00104 acc_divider=8192; 00105 break; 00106 case BITS_FS_8G: 00107 acc_divider=4096; 00108 break; 00109 case BITS_FS_16G: 00110 acc_divider=2048; 00111 break; 00112 } 00113 wait(0.01); 00114 select(); 00115 temp_scale=spi.write(MPUREG_ACCEL_CONFIG|READ_FLAG); 00116 temp_scale=spi.write(0x00); 00117 deselect(); 00118 switch (temp_scale) { 00119 case BITS_FS_2G: 00120 temp_scale=2; 00121 break; 00122 case BITS_FS_4G: 00123 temp_scale=4; 00124 break; 00125 case BITS_FS_8G: 00126 temp_scale=8; 00127 break; 00128 case BITS_FS_16G: 00129 temp_scale=16; 00130 break; 00131 } 00132 return temp_scale; 00133 } 00134 00135 00136 /*----------------------------------------------------------------------------------------------- 00137 GYROSCOPE SCALE 00138 usage: call this function at startup, after initialization, to set the right range for the 00139 gyroscopes. Suitable ranges are: 00140 BITS_FS_250DPS 00141 BITS_FS_500DPS 00142 BITS_FS_1000DPS 00143 BITS_FS_2000DPS 00144 returns the range set (250,500,1000 or 2000) 00145 -----------------------------------------------------------------------------------------------*/ 00146 unsigned int mpu6000_spi::set_gyro_scale(int scale) 00147 { 00148 unsigned int temp_scale; 00149 select(); 00150 spi.write(MPUREG_GYRO_CONFIG); 00151 spi.write(scale); 00152 deselect(); 00153 switch (scale) { 00154 case BITS_FS_250DPS: 00155 gyro_divider=131; 00156 break; 00157 case BITS_FS_500DPS: 00158 gyro_divider=65.5; 00159 break; 00160 case BITS_FS_1000DPS: 00161 gyro_divider=32.8; 00162 break; 00163 case BITS_FS_2000DPS: 00164 gyro_divider=16.4; 00165 break; 00166 } 00167 wait(0.01); 00168 select(); 00169 temp_scale=spi.write(MPUREG_GYRO_CONFIG|READ_FLAG); 00170 temp_scale=spi.write(0x00); 00171 deselect(); 00172 switch (temp_scale) { 00173 case BITS_FS_250DPS: 00174 temp_scale=250; 00175 break; 00176 case BITS_FS_500DPS: 00177 temp_scale=500; 00178 break; 00179 case BITS_FS_1000DPS: 00180 temp_scale=1000; 00181 break; 00182 case BITS_FS_2000DPS: 00183 temp_scale=2000; 00184 break; 00185 } 00186 return temp_scale; 00187 } 00188 00189 00190 /*----------------------------------------------------------------------------------------------- 00191 WHO AM I? 00192 usage: call this function to know if SPI is working correctly. It checks the I2C address of the 00193 mpu6000 which should be 104 when in SPI mode. 00194 returns the I2C address (104) 00195 -----------------------------------------------------------------------------------------------*/ 00196 unsigned int mpu6000_spi::whoami() 00197 { 00198 // create instance of response 00199 unsigned int response; 00200 00201 // Begin transmission 00202 select(); 00203 00204 // Bitwise OR of WHOAMI Register (default 0x68) and READ_FLAG 00205 response=spi.write(MPUREG_WHOAMI|READ_FLAG); 00206 response=spi.write(0x00); 00207 00208 // End transmission 00209 deselect(); 00210 00211 return response; 00212 } 00213 00214 /** High = Safe. Low = Unsafe */ 00215 int mpu6000_spi::whoamiCheck() 00216 { 00217 // mask whoami() against expected value 00218 return whoami()!=0x68; 00219 } 00220 00221 00222 // Get Tilt Angle from Accelerometer 00223 float mpu6000_spi::getAccTilt() 00224 { 00225 float Z,X; 00226 wait(0.0001); 00227 Z = read_acc(2); 00228 wait_us(10); 00229 X=read_acc(0); 00230 float temp=Z/X; 00231 if(temp !=temp) { 00232 if (X>=0 && Z>=0) { 00233 temp=FLT_MAX; 00234 } else { 00235 temp=FLT_MIN; 00236 } 00237 } 00238 00239 return atan(temp)*180/pi; 00240 00241 } 00242 00243 00244 /*----------------------------------------------------------------------------------------------- 00245 READ ACCELEROMETER 00246 usage: call this function to read accelerometer data. Axis represents selected axis: 00247 0 -> X axis 00248 1 -> Y axis 00249 2 -> Z axis 00250 returns the value in Gs 00251 -----------------------------------------------------------------------------------------------*/ 00252 float mpu6000_spi::read_acc(int axis) 00253 { 00254 uint8_t responseH,responseL; 00255 int16_t bit_data; 00256 float data; 00257 select(); 00258 switch (axis) { 00259 case 0: 00260 responseH=spi.write(MPUREG_ACCEL_XOUT_H | READ_FLAG); 00261 break; 00262 case 1: 00263 responseH=spi.write(MPUREG_ACCEL_YOUT_H | READ_FLAG); 00264 break; 00265 case 2: 00266 responseH=spi.write(MPUREG_ACCEL_ZOUT_H | READ_FLAG); 00267 break; 00268 } 00269 // wait(0.0001); 00270 responseH=spi.write(0x00); 00271 responseL=spi.write(0x00); 00272 bit_data=((int16_t)responseH<<8)|responseL; 00273 data=(float)bit_data; 00274 data = data/acc_divider; 00275 deselect(); 00276 //printf("data = %f\n\r",data); 00277 return data; 00278 } 00279 00280 /*----------------------------------------------------------------------------------------------- 00281 READ GYROSCOPE 00282 usage: call this function to read gyroscope data. Axis represents selected axis: 00283 0 -> X axis 00284 1 -> Y axis 00285 2 -> Z axis 00286 returns the value in Degrees per second 00287 -----------------------------------------------------------------------------------------------*/ 00288 float mpu6000_spi::read_rot(int axis) 00289 { 00290 uint8_t responseH,responseL; 00291 int16_t bit_data; 00292 float data; 00293 select(); 00294 switch (axis) { 00295 case 0: 00296 responseH=spi.write(MPUREG_GYRO_XOUT_H | READ_FLAG); 00297 break; 00298 case 1: 00299 responseH=spi.write(MPUREG_GYRO_YOUT_H | READ_FLAG); 00300 break; 00301 case 2: 00302 responseH=spi.write(MPUREG_GYRO_ZOUT_H | READ_FLAG); 00303 break; 00304 } 00305 wait(0.0001); 00306 responseH=spi.write(0x00); 00307 responseL=spi.write(0x00); 00308 bit_data=((int16_t)responseH<<8)|responseL; 00309 data=(float)bit_data; 00310 data=data/gyro_divider; 00311 deselect(); 00312 return data; 00313 } 00314 00315 /*----------------------------------------------------------------------------------------------- 00316 READ TEMPERATURE 00317 usage: call this function to read temperature data. 00318 returns the value in °C 00319 -----------------------------------------------------------------------------------------------*/ 00320 float mpu6000_spi::read_temp() 00321 { 00322 uint8_t responseH,responseL; 00323 int16_t bit_data; 00324 float data; 00325 select(); 00326 responseH=spi.write(MPUREG_TEMP_OUT_H | READ_FLAG); 00327 responseH=spi.write(0x00); 00328 responseL=spi.write(0x00); 00329 bit_data=((int16_t)responseH<<8)|responseL; 00330 data=(float)bit_data; 00331 data=(data/340)+36.53; 00332 deselect(); 00333 return data; 00334 } 00335 00336 /*----------------------------------------------------------------------------------------------- 00337 READ ACCELEROMETER CALIBRATION 00338 usage: call this function to read accelerometer data. Axis represents selected axis: 00339 0 -> X axis 00340 1 -> Y axis 00341 2 -> Z axis 00342 returns Factory Trim value 00343 -----------------------------------------------------------------------------------------------*/ 00344 int mpu6000_spi::calib_acc(int axis) 00345 { 00346 uint8_t responseH,responseL,calib_data; 00347 int temp_scale; 00348 //READ CURRENT ACC SCALE 00349 select(); 00350 responseH=spi.write(MPUREG_ACCEL_CONFIG|READ_FLAG); 00351 temp_scale=spi.write(0x00); 00352 deselect(); 00353 wait(0.01); 00354 set_acc_scale(BITS_FS_8G); 00355 wait(0.01); 00356 //ENABLE SELF TEST 00357 select(); 00358 responseH=spi.write(MPUREG_ACCEL_CONFIG); 00359 temp_scale=spi.write(0x80>>axis); 00360 deselect(); 00361 wait(0.01); 00362 select(); 00363 responseH=spi.write(MPUREG_SELF_TEST_X|READ_FLAG); 00364 switch(axis) { 00365 case 0: 00366 responseH=spi.write(0x00); 00367 responseL=spi.write(0x00); 00368 responseL=spi.write(0x00); 00369 responseL=spi.write(0x00); 00370 calib_data=((responseH&11100000)>>3)|((responseL&00110000)>>4); 00371 break; 00372 case 1: 00373 responseH=spi.write(0x00); 00374 responseH=spi.write(0x00); 00375 responseL=spi.write(0x00); 00376 responseL=spi.write(0x00); 00377 calib_data=((responseH&11100000)>>3)|((responseL&00001100)>>2); 00378 break; 00379 case 2: 00380 responseH=spi.write(0x00); 00381 responseH=spi.write(0x00); 00382 responseH=spi.write(0x00); 00383 responseL=spi.write(0x00); 00384 calib_data=((responseH&11100000)>>3)|((responseL&00000011)); 00385 break; 00386 } 00387 deselect(); 00388 wait(0.01); 00389 set_acc_scale(temp_scale); 00390 return calib_data; 00391 } 00392 00393 /*----------------------------------------------------------------------------------------------- 00394 SPI SELECT AND DESELECT 00395 usage: enable and disable mpu6000 communication bus 00396 -----------------------------------------------------------------------------------------------*/ 00397 void mpu6000_spi::select() 00398 { 00399 //Set CS low to start transmission (interrupts conversion) 00400 cs = 0; 00401 } 00402 void mpu6000_spi::deselect() 00403 { 00404 //Set CS high to stop transmission (restarts conversion) 00405 cs = 1; 00406 } 00407 00408 float mpu6000_spi::angle_y() 00409 { 00410 float gyro = read_rot(1); 00411 float acc = getAccTilt(); 00412 00413 // complementary filter 00414 accFilterCurrent = 0.8187*accFilterPre+0.1813*acc; 00415 gyroFilterCurrent = 0.8187*gyroFliterPre+0.0009063*gyro; 00416 00417 //pc.printf("\n\nWHOAMI=%u\n",imu.whoami()); //output the I2C address to know if SPI is working, it should be 104 00418 //pc.printf("acc=%f\n\r",acc); 00419 //pc.printf("GYRO=%f\n\r",gyro); 00420 accFilterPre = accFilterCurrent; 00421 gyroFliterPre = gyroFilterCurrent; 00422 return accFilterCurrent + gyroFilterCurrent; 00423 } 00424 00425 float mpu6000_spi::rereadAngle_y() 00426 { 00427 return accFilterCurrent + gyroFilterCurrent; 00428 }
Generated on Tue Jul 19 2022 11:37:55 by 1.7.2