RT-AICHIP-sample
mpu9150.c
[詳解]
1 
8 #include "type.h"
9 #include "mpu9150.h"
10 #include "i2c.h"
11 #include "uart.h"
12 #include "SystemTickTimer.h"
13 #include "TinyMathFunction.h"
14 #include "debug.h"
15 
16 
17 //i2cの操作に必要なもの達のextern宣言. 実体はi2c.cにある
18 extern volatile uint8_t I2CMasterBuffer[BUFSIZE];
19 extern volatile uint8_t I2CSlaveBuffer[BUFSIZE];
20 extern volatile uint32_t I2CReadLength, I2CWriteLength;
21 
22 //MPU9150のi2cのアドレス
23 #define MPU6050_W 0xd0
24 #define MPU6050_R 0xd1
25 #define AK8975_W 0x18
26 #define AK8975_R 0x19
27 
28 static volatile uint8_t Asa[] = {0, 0, 0}; //AK8975の感度補正データ格納用(感度補正データは工場出荷時にICに書き込まれている)
29 
30 static volatile float omega_vec[] = {0.0, 0.0, 0.0}; //角速度5ベクトル (x,y,z)[rad]
31 static volatile float acc_vec[] = {0.0, 0.0, 0.0}; //加速度ベクトル (x,y,z) [1G]
32 static volatile float mag_vec[] = {0.0, 0.0, 0.0}; //地磁気ベクトル (x,y,z) [uT]
33 static volatile float temperature = 0.0; //MPU9150の温度[°C]
34 
35 static volatile float omega_LPF_vec[] = {0.0, 0.0, 0.0}; //軽めのローパスフィルタをかけた値
36 static volatile float acc_LPF_vec[] = {0.0, 0.0, 0.0};
37 static volatile float mag_LPF_vec[] = {0.0, 0.0, 0.0};
38 
39 static volatile float omega_str_LPF_vec[] = {0.0, 0.0, 0.0}; //強めのローパスフィルタをかけた値
40 static volatile float acc_str_LPF_vec[] = {0.0, 0.0, 0.0};
41 static volatile float mag_str_LPF_vec[] = {0.0, 0.0, 0.0};
42 
43 static volatile float omega_ref_vec[] = {0.0,0.0,0.0}; //静止時のジャイロリファレンス
44 
45 volatile float gain_LPF = 0.8; //ローパスフィルタのゲイン
46 volatile float gain_str_LPF = 0.1; //強めのローパスフィルタのゲイン
47 
54 void initMPU6050 (void)
55 {
56  I2CWriteLength = 3;
57  I2CReadLength = 0;
59  I2CMasterBuffer[1] = 0x6B; //Address start MPU9150
60  I2CMasterBuffer[2] = 0x00;
61  I2CEngine();
62 
63  wait1usec(100);
64 
65  I2CWriteLength = 3;
66  I2CReadLength = 0;
68  I2CMasterBuffer[1] = 0x37; //Address auxiliary I2C
69  I2CMasterBuffer[2] = 0x02;
70  I2CEngine();
71 
72  wait1usec(100);
73 
74  I2CWriteLength = 3;
75  I2CReadLength = 0;
77  I2CMasterBuffer[1] = 0x1A; //Address digital low pass filter
78  I2CMasterBuffer[2] = 0x02; //100Hz
79  I2CEngine();
80 
81  wait1usec(100);
82 
83  I2CWriteLength = 3;
84  I2CReadLength = 0;
86  I2CMasterBuffer[1] = 0x1B; //range ang
87  I2CMasterBuffer[2] = 0x18; //2000deg/s
88  I2CEngine();
89 
90  wait1usec(100);
91 
92  I2CWriteLength = 3;
93  I2CReadLength = 0;
95  I2CMasterBuffer[1] = 0x1C; //range acc
96  I2CMasterBuffer[2] = 0x18; //16g
97  I2CEngine();
98 }
99 
106 void initAK8975 (void)
107 {
108  volatile uint32_t i;
109 
110  I2CWriteLength = 2;
111  I2CReadLength = 3;
113  I2CMasterBuffer[1] = 0x10; //Address 3byte (adjust MagXYZ)
115  I2CEngine();
116 
117  for(i = 0;i < 3;i ++)
118  {
119  Asa[i] = I2CSlaveBuffer[i];
120  }
121 }
122 
147 void getDataFromMPU6050 (uint8_t *dest_array )
148 {
149  volatile uint32_t i;
150  volatile int32_t acc[3];
151  volatile uint16_t acc_temp[3]; //加速度の値計算の中間値
152  volatile int32_t omega[3];
153  volatile int32_t temp_; //温度
154 
155  I2CWriteLength = 2;
156  I2CReadLength = 14;
158  I2CMasterBuffer[1] = 0x3B; //Address 14byte (AccXYZ + GyroXYZ + temp)
160  I2CEngine();
161 
162  acc_temp[0] = (I2CSlaveBuffer[0]<<8) + I2CSlaveBuffer[1];
163  acc_temp[1] = (I2CSlaveBuffer[2]<<8) + I2CSlaveBuffer[3];
164  acc_temp[2] = (I2CSlaveBuffer[4]<<8) + I2CSlaveBuffer[5];
165 
166  acc_temp[0] = (~acc_temp[0]) + 1;
167  acc_temp[1] = (~acc_temp[1]) + 1;
168  acc_temp[2] = (~acc_temp[2]) + 1;
169 
170  //Acc
171  dest_array[0] = 0x00ff & acc_temp[0];
172  dest_array[1] = (0xff00 & acc_temp[0])>>8;
173  dest_array[2] = 0x00ff & acc_temp[1];
174  dest_array[3] = (0xff00 & acc_temp[1])>>8;
175  dest_array[4] = 0x00ff & acc_temp[2];
176  dest_array[5] = (0xff00 & acc_temp[2])>>8;
177  //temparature
178  dest_array[6] = I2CSlaveBuffer[7];
179  dest_array[7] = I2CSlaveBuffer[6];
180  //gyro
181  dest_array[8] = I2CSlaveBuffer[9];
182  dest_array[9] = I2CSlaveBuffer[8];
183  dest_array[10] = I2CSlaveBuffer[11];
184  dest_array[11] = I2CSlaveBuffer[10];
185  dest_array[12] = I2CSlaveBuffer[13];
186  dest_array[13] = I2CSlaveBuffer[12];
187 
188  for ( i = 0; i < BUFSIZE; i++ ) //clear I2CSlaveBuffer
189  {
190  I2CSlaveBuffer[i] = 0x00;
191  }
192 
193  //センサ値を物理量に変換
194 
195  acc[0] = dest_array[0] + (dest_array[1]<<8);
196  if(acc[0] >= 32767) acc[0] -= 65536;
197  acc_vec[0] = ((float)acc[0])/2048.0;
198 
199  acc[1] = dest_array[2] + (dest_array[3]<<8);
200  if(acc[1] >= 32767) acc[1] -= 65536;
201  acc_vec[1] = ((float)acc[1])/2048.0;
202 
203  acc[2] = dest_array[4] + (dest_array[5]<<8);
204  if(acc[2] >= 32767) acc[2] -= 65536;
205  acc_vec[2] = ((float)acc[2])/2048.0;
206 
207  omega[0] = dest_array[8] + (dest_array[9]<<8);
208  if(omega[0] >= 32767) omega[0] -= 65536;
209  omega_vec[0] = DEG2RAD( ((omega[0]) - (int32_t)(omega_ref_vec[0] + 0.5 ) )/16.4 );
210 
211  omega[1] = dest_array[10] + (dest_array[11]<<8);
212  if(omega[1] >= 32767) omega[1] -= 65536;
213  omega_vec[1] = DEG2RAD( ((omega[1]) - (int32_t)(omega_ref_vec[1] + 0.5 ) )/16.4 );
214 
215  omega[2] = dest_array[12] + (dest_array[13]<<8);
216  if(omega[2] >= 32767) omega[2] -= 65536;
217  omega_vec[2] = DEG2RAD( ((omega[2]) - (int32_t)(omega_ref_vec[2] + 0.5 ) )/16.4 );
218 
219  temp_ = dest_array[6] + (dest_array[7]<<8);
220  if(temp_ >= 32767) temp_ -= 65536;
221  temperature = (float)temp_/340.0 + 35.0;
222 
223  //加速度センサ値をLPFにかける
224  acc_LPF_vec[0] = gain_LPF * acc_LPF_vec[0] + (1.0-gain_LPF) * acc_vec[0];
225  acc_LPF_vec[1] = gain_LPF * acc_LPF_vec[1] + (1.0-gain_LPF) * acc_vec[1];
226  acc_LPF_vec[2] = gain_LPF * acc_LPF_vec[2] + (1.0-gain_LPF) * acc_vec[2];
227 
228  //角速度をLPFにかける
229  omega_LPF_vec[0] = gain_LPF * omega_LPF_vec[0] + (1.0-gain_LPF) * omega_vec[0];
230  omega_LPF_vec[1] = gain_LPF * omega_LPF_vec[1] + (1.0-gain_LPF) * omega_vec[1];
231  omega_LPF_vec[2] = gain_LPF * omega_LPF_vec[2] + (1.0-gain_LPF) * omega_vec[2];
232 
233  //加速度センサ値をLPFにかける
234  acc_str_LPF_vec[0] = gain_str_LPF * acc_LPF_vec[0] + (1.0-gain_str_LPF) * acc_vec[0];
235  acc_str_LPF_vec[1] = gain_str_LPF * acc_LPF_vec[1] + (1.0-gain_str_LPF) * acc_vec[1];
236  acc_str_LPF_vec[2] = gain_str_LPF * acc_LPF_vec[2] + (1.0-gain_str_LPF) * acc_vec[2];
237 
238  //角速度をLPFにかける
239  omega_str_LPF_vec[0] = gain_str_LPF * omega_str_LPF_vec[0] + (1.0-gain_str_LPF) * omega_vec[0];
240  omega_str_LPF_vec[1] = gain_str_LPF * omega_str_LPF_vec[1] + (1.0-gain_str_LPF) * omega_vec[1];
241  omega_str_LPF_vec[2] = gain_str_LPF * omega_str_LPF_vec[2] + (1.0-gain_str_LPF) * omega_vec[2];
242 }
243 
261 void getDataFromAK8975 (uint8_t *dest_array)
262 {
263  volatile int32_t mag[3];
264 
265  volatile uint32_t i;
266  volatile int16_t Mag[3];
267 
268  I2CWriteLength = 2;
269  I2CReadLength = 6;
271  I2CMasterBuffer[1] = 0x03; //Address 6byte (MagXYZ)
273  I2CEngine();
274 
275  for ( i = 0; i < 3; i++ )
276  {
277  Mag[i] = (uint16_t)I2CSlaveBuffer[i<<1] | (((uint16_t)I2CSlaveBuffer[(i<<1)+1])<<8);
278  Mag[i] = Mag[i]*(uint16_t)((((int8_t)Asa[i] - 128)/256) + 1);
279  }
280 
281  dest_array[0] = (uint8_t)Mag[1];
282  dest_array[1] = (uint8_t)(Mag[1]>>8);
283 
284  dest_array[2] = (uint8_t)Mag[0];
285  dest_array[3] = (uint8_t)(Mag[0]>>8);
286 
287  Mag[2] = (~Mag[2]) + 1; //地磁気センサのZ軸の取り方を下向きから上向きに変更
288  dest_array[4] = (uint8_t)Mag[2];
289  dest_array[5] = (uint8_t)(Mag[2]>>8);
290 
291  I2CWriteLength = 3;
292  I2CReadLength = 0;
294  I2CMasterBuffer[1] = 0x0A; //Address start MagXYZ ADC (need 7.2ms)
295  I2CMasterBuffer[2] = 0x01;
296  I2CEngine();
297 
298  for ( i = 0; i < BUFSIZE; i++ ) //clear I2CSlaveBuffer
299  {
300  I2CSlaveBuffer[i] = 0x00;
301  }
302 
303  //センサ値を地磁気ベクトルに変換
304  for( i=0;i<3;i++)
305  {
306  mag[i] = dest_array[i] + (dest_array[i+1]<<8);
307  if(mag[i] >= 32767) mag[i] -= 65535;
308  mag_vec[i] = (float)mag[i]*0.3;
309  }
310 }
311 
312 
319 void getOmega(float *vec)
320 {
321  uint8_t i;
322  for(i=0;i<3;i++) vec[i] = omega_vec[i];
323 };
324 
331 void getMag(float *vec)
332 {
333  uint8_t i;
334  for(i=0;i<3;i++) vec[i] = mag_vec[i];
335 };
336 
343 void getAcc(float *vec)
344 {
345  uint8_t i;
346  for(i=0;i<3;i++) vec[i] = acc_vec[i];
347 };
348 
355 void getTemp(float *temp)
356 {
357  *temp = temperature;
358 }
359 
367 {
368  uint32_t i = 0;
369  uint8_t data_array[14];
370  #define NUM_REF (100)
371 
372  int32_t omega_x[NUM_REF];
373  int32_t omega_y[NUM_REF];
374  int32_t omega_z[NUM_REF];
375 
376  float omega_x_sum = 0.0;
377  float omega_y_sum = 0.0;
378  float omega_z_sum = 0.0;
379 
380  for(i=0;i<3;i++)
381  {
382  omega_ref_vec[i] = 0.0;
383  }
384 
385  for(i=0;i<NUM_REF;i++)
386  {
387  getDataFromMPU6050(data_array);
388  omega_x[i] = data_array[8] + (data_array[9]<<8);
389  if(omega_x[i] >= 32767) omega_x[i] -= 65536;
390 
391  omega_y[i] = data_array[10] + (data_array[11]<<8);
392  if(omega_y[i] >= 32767) omega_y[i] -= 65536;
393 
394  omega_z[i] = data_array[12] + (data_array[13]<<8);
395  if(omega_z[i] >= 32767) omega_z[i] -= 65536;
396  wait1usec(10000);
397  }
398  quickSort(omega_x,0 ,NUM_REF -1);
399  quickSort(omega_y,0 ,NUM_REF -1);
400  quickSort(omega_z,0 ,NUM_REF -1);
401 
402  for(i=NUM_REF/4;i<(NUM_REF*3/4 +1) ;i++)
403  {
404  omega_x_sum += (float)(omega_x[i]);
405  omega_y_sum += (float)(omega_y[i]);
406  omega_z_sum += (float)(omega_z[i]);
407  }
408  omega_ref_vec[0] = omega_x_sum/(float)NUM_REF *2.0;
409  omega_ref_vec[1] = omega_y_sum/(float)NUM_REF *2.0;
410  omega_ref_vec[2] = omega_z_sum/(float)NUM_REF *2.0;
411 
412 }
413 
420 void getOmegaLPF(float *vec)
421 {
422  uint8_t i;
423  for(i=0;i<3;i++) vec[i] = omega_LPF_vec[i];
424 };
425 
432 void getMagLPF(float *vec)
433 {
434  uint8_t i;
435  for(i=0;i<3;i++) vec[i] = mag_LPF_vec[i];
436 };
437 
438 
445 void getAccLPF(float *vec)
446 {
447  uint8_t i;
448  for(i=0;i<3;i++) vec[i] = acc_LPF_vec[i];
449 };
450 
457 void getOmegaStrLPF(float *vec)
458 {
459  uint8_t i;
460  for(i=0;i<3;i++) vec[i] = omega_LPF_vec[i];
461 };
462 
469 void getMagStrLPF(float *vec)
470 {
471  uint8_t i;
472  for(i=0;i<3;i++) vec[i] = mag_LPF_vec[i];
473 };
474 
481 void getAccStrLPF(float *vec)
482 {
483  uint8_t i;
484  for(i=0;i<3;i++) vec[i] = acc_LPF_vec[i];
485 };
486 
493 float getOmegaRef(float *vec)
494 {
495  uint8_t i;
496  for(i=0;i<3;i++) vec[i] = omega_ref_vec[i];
497 }
498 
505 void setOmegaRef_x(float ref_x)
506 {
507  omega_ref_vec[0] = ref_x;
508 }
509 
516 void setOmegaRef_y(float ref_y)
517 {
518  omega_ref_vec[1] = ref_y;
519 }
520 
527 void setOmegaRef_z(float ref_z)
528 {
529  omega_ref_vec[2] = ref_z;
530 }
531 
538 void debugMPU9150(void)
539 {
540  myPrintfUART("########debug MPU9150#######\n");
541  myPrintfUART("acc : %f, %f, %f (x,y,z)[rad] \n",acc_vec[0], acc_vec[1],acc_vec[2]);
542  myPrintfUART("omega: %f, %f, %f (x,y,z) [1G] \n",omega_vec[0], omega_vec[1],omega_vec[2]);
543  myPrintfUART("mag : %f, %f, %f (x,y,z) [uT] \n",mag_vec[0], mag_vec[1],mag_vec[2]);
544  myPrintfUART("temp : %f [°C] \n", temperature);
545 }
546 
547 
void debugMPU9150(void)
Definition: mpu9150.c:538
uint32_t I2CEngine(void)
Definition: i2c.c:282
volatile uint32_t I2CReadLength
Definition: i2c.c:23
void getMagStrLPF(float *vec)
Definition: mpu9150.c:469
void getDataFromMPU6050(uint8_t *dest_array)
Definition: mpu9150.c:147
signed int int32_t
Definition: type.h:23
signed char int8_t
Definition: type.h:21
int myPrintfUART(const char *fmt,...)
Definition: debug.c:42
#define MPU6050_W
Definition: mpu9150.c:23
volatile uint8_t I2CSlaveBuffer[BUFSIZE]
Definition: i2c.c:21
#define AK8975_R
Definition: mpu9150.c:26
unsigned char uint8_t
Definition: type.h:27
void setOmegaRef_z(float ref_z)
Definition: mpu9150.c:527
void getAccLPF(float *vec)
Definition: mpu9150.c:445
void initMPU6050(void)
Definition: mpu9150.c:54
void getAccStrLPF(float *vec)
Definition: mpu9150.c:481
void getMagLPF(float *vec)
Definition: mpu9150.c:432
void initOmegaRef()
Definition: mpu9150.c:366
void quickSort(int numbers[], int left, int right)
#define MPU6050_R
Definition: mpu9150.c:24
void getOmegaLPF(float *vec)
Definition: mpu9150.c:420
void initAK8975(void)
Definition: mpu9150.c:106
void setOmegaRef_y(float ref_y)
Definition: mpu9150.c:516
void wait1usec(uint32_t wait_count)
void getDataFromAK8975(uint8_t *dest_array)
Definition: mpu9150.c:261
signed short int int16_t
Definition: type.h:22
void getAcc(float *vec)
Definition: mpu9150.c:343
volatile uint32_t I2CWriteLength
Definition: i2c.c:24
void getOmegaStrLPF(float *vec)
Definition: mpu9150.c:457
unsigned short int uint16_t
Definition: type.h:28
void getOmega(float *vec)
Definition: mpu9150.c:319
#define BUFSIZE
Definition: i2c.h:16
volatile uint8_t I2CMasterBuffer[BUFSIZE]
Definition: i2c.c:20
void getMag(float *vec)
Definition: mpu9150.c:331
#define NUM_REF
#define DEG2RAD(deg)
volatile float gain_str_LPF
Definition: mpu9150.c:46
void getTemp(float *temp)
Definition: mpu9150.c:355
void setOmegaRef_x(float ref_x)
Definition: mpu9150.c:505
volatile float gain_LPF
Definition: mpu9150.c:45
#define AK8975_W
Definition: mpu9150.c:25
float getOmegaRef(float *vec)
Definition: mpu9150.c:493
unsigned int uint32_t
Definition: type.h:29