ICM20600.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. #include "ICM20600.h"
  2. #include "ICM20600_i2c.h"
  3. #include "math.h"
  4. #include "var.h"
  5. float twoKp = 0.4, twoKi = 0.001, invSampleFreq = 0.005;
  6. float q0 = 1, q1 = 0, q2 = 0, q3 = 0;
  7. float integralFBx = 0, integralFBy = 0, integralFBz = 0;
  8. ICM20600_Data_typedef ICM20600Sensor;
  9. Bike_Attitude_typedef Bike_Attitude = {FALSE,FALSE,0,0,0,0};
  10. TrueOrFalse_Flag_Struct_t ICM20600_OK_Flag = FALSE;
  11. uint8_t ICM20600_getDeviceID( void )
  12. {
  13. uint8_t data=0;
  14. Sensors_I2C_ReadRegister(ICM20600_I2C_ADDR2,ICM20600_PWR_MGMT_1,1,&data);
  15. if(data != 0)
  16. {
  17. ICM20600_OK_Flag = TRUE;
  18. }
  19. return data;
  20. }
  21. void ICM20600_reset( void )
  22. {
  23. uint8_t data=0;
  24. Sensors_I2C_ReadRegister(ICM20600_I2C_ADDR2, ICM20600_USER_CTRL, 1, &data);
  25. data &= 0xfe; // ICM20600_USER_CTRL[0] 11111110
  26. data |= ICM20600_RESET_BIT;
  27. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_USER_CTRL, 1, &data);
  28. }
  29. void ICM20600_setPowerMode(icm20600_power_type_t mode)
  30. {
  31. uint8_t data_pwr1;
  32. uint8_t data_pwr2 = 0x00;
  33. uint8_t data_gyro_lp;
  34. Sensors_I2C_ReadRegister(ICM20600_I2C_ADDR2, ICM20600_PWR_MGMT_1, 1, &data_pwr1);
  35. data_pwr1 &= 0x8f; // 0b10001111
  36. Sensors_I2C_ReadRegister(ICM20600_I2C_ADDR2, ICM20600_GYRO_LP_MODE_CFG, 1, &data_gyro_lp);
  37. // When set to 1 low-power gyroscope mode is enabled. Default setting is 0
  38. data_gyro_lp &= 0x7f; // 0b01111111
  39. switch(mode)
  40. {
  41. case ICM_SLEEP_MODE:
  42. data_pwr1 |= 0x40; // set 0b01000000
  43. break;
  44. case ICM_STANDYBY_MODE:
  45. data_pwr1 |= 0x10; // set 0b00010000
  46. data_pwr2 = 0x38; // 0x00111000 disable acc
  47. break;
  48. case ICM_ACC_LOW_POWER:
  49. data_pwr1 |= 0x20; // set bit5 0b00100000
  50. data_pwr2 = 0x07; //0x00000111 disable gyro
  51. break;
  52. case ICM_ACC_LOW_NOISE:
  53. data_pwr1 |= 0x00;
  54. data_pwr2 = 0x07; //0x00000111 disable gyro
  55. break;
  56. case ICM_GYRO_LOW_POWER:
  57. data_pwr1 |= 0x00; // dont set bit5 0b00000000
  58. data_pwr2 = 0x38; // 0x00111000 disable acc
  59. data_gyro_lp |= 0x80;
  60. break;
  61. case ICM_GYRO_LOW_NOISE:
  62. data_pwr1 |= 0x00;
  63. data_pwr2 = 0x38; // 0x00111000 disable acc
  64. break;
  65. case ICM_6AXIS_LOW_POWER:
  66. data_pwr1 |= 0x00; // dont set bit5 0b00000000
  67. data_gyro_lp |= 0x80;
  68. break;
  69. case ICM_6AXIS_LOW_NOISE:
  70. data_pwr1 |= 0x00;
  71. break;
  72. default:
  73. break;
  74. }
  75. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_PWR_MGMT_1, 1, &data_pwr1);
  76. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_PWR_MGMT_2, 1, &data_pwr2);
  77. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_GYRO_LP_MODE_CFG, 1, &data_gyro_lp);
  78. }
  79. void ICM20600_setGyroScaleRange(gyro_scale_type_t range)
  80. {
  81. uint8_t data = 0;
  82. Sensors_I2C_ReadRegister(ICM20600_I2C_ADDR2, ICM20600_GYRO_CONFIG, 1, &data);
  83. data &= 0xe7; // 0b11100111
  84. switch(range)
  85. {
  86. case RANGE_250_DPS:
  87. data |= 0x00; // 0bxxx00xxx
  88. break;
  89. case RANGE_500_DPS:
  90. data |= 0x08; // 0bxxx00xxx
  91. break;
  92. case RANGE_1K_DPS:
  93. data |= 0x10; // 0bxxx10xxx
  94. break;
  95. case RANGE_2K_DPS:
  96. data |= 0x18; // 0bxxx11xxx
  97. break;
  98. default:
  99. break;
  100. }
  101. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_GYRO_CONFIG, 1, &data);
  102. }
  103. // for low power mode only
  104. void ICM20600_setGyroAverageSample(gyro_averaging_sample_type_t sample)
  105. {
  106. uint8_t data = 0;
  107. Sensors_I2C_ReadRegister(ICM20600_I2C_ADDR2, ICM20600_GYRO_LP_MODE_CFG, 1, &data);
  108. data &= 0x8f; // 0b10001111
  109. switch(sample)
  110. {
  111. case GYRO_AVERAGE_1:
  112. data |= 0x00; // 0bx000xxxx
  113. break;
  114. case GYRO_AVERAGE_2:
  115. data |= 0x10; // 0bx001xxxx
  116. break;
  117. case GYRO_AVERAGE_4:
  118. data |= 0x20; // 0bx010xxxx
  119. break;
  120. case GYRO_AVERAGE_8:
  121. data |= 0x30; // 0bx011xxxx
  122. break;
  123. case GYRO_AVERAGE_16:
  124. data |= 0x40; // 0bx100xxxx
  125. break;
  126. case GYRO_AVERAGE_32:
  127. data |= 0x50; // 0bx101xxxx
  128. break;
  129. case GYRO_AVERAGE_64:
  130. data |= 0x60;
  131. break;
  132. case GYRO_AVERAGE_128:
  133. data |= 0x70;
  134. break;
  135. default:
  136. break;
  137. }
  138. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_GYRO_LP_MODE_CFG, 1, &data);
  139. }
  140. void ICM20600_setGyroOutputDataRate(gyro_lownoise_odr_type_t odr)
  141. {
  142. uint8_t data;
  143. Sensors_I2C_ReadRegister(ICM20600_I2C_ADDR2, ICM20600_CONFIG, 1, &data);
  144. data &= 0xf8; // DLPF_CFG[2:0] 0b11111000
  145. switch(odr)
  146. {
  147. case GYRO_RATE_8K_BW_3281:
  148. data |= 0x07;
  149. break;
  150. case GYRO_RATE_8K_BW_250:
  151. data |= 0x00;
  152. break;
  153. case GYRO_RATE_1K_BW_176:
  154. data |= 0x01;
  155. break;
  156. case GYRO_RATE_1K_BW_92:
  157. data |= 0x02;
  158. break;
  159. case GYRO_RATE_1K_BW_41:
  160. data |= 0x03;
  161. break;
  162. case GYRO_RATE_1K_BW_20:
  163. data |= 0x04;
  164. break;
  165. case GYRO_RATE_1K_BW_10:
  166. data |= 0x05;
  167. break;
  168. case GYRO_RATE_1K_BW_5:
  169. data |= 0x06;
  170. break;
  171. }
  172. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_CONFIG, 1, &data);
  173. }
  174. void ICM20600_setAccScaleRange(acc_scale_type_t range)
  175. {
  176. uint8_t data;
  177. Sensors_I2C_ReadRegister(ICM20600_I2C_ADDR2, ICM20600_ACCEL_CONFIG, 1, &data);
  178. data &= 0xe7; // 0b 1110 0111
  179. switch(range)
  180. {
  181. case RANGE_2G:
  182. data |= 0x00; // 0bxxx00xxx
  183. break;
  184. case RANGE_4G:
  185. data |= 0x08; // 0bxxx01xxx
  186. break;
  187. case RANGE_8G:
  188. data |= 0x10; // 0bxxx10xxx
  189. break;
  190. case RANGE_16G:
  191. data |= 0x18; // 0bxxx11xxx
  192. break;
  193. default:
  194. break;
  195. }
  196. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_ACCEL_CONFIG, 1, &data);
  197. }
  198. // for low power mode only
  199. void ICM20600_setAccAverageSample(acc_averaging_sample_type_t sample)
  200. {
  201. uint8_t data = 0;
  202. Sensors_I2C_ReadRegister(ICM20600_I2C_ADDR2, ICM20600_ACCEL_CONFIG2, 1, &data);
  203. data &= 0xcf; // & 0b11001111
  204. switch(sample)
  205. {
  206. case ACC_AVERAGE_4:
  207. data |= 0x00; // 0bxx00xxxx
  208. break;
  209. case ACC_AVERAGE_8:
  210. data |= 0x10; // 0bxx01xxxx
  211. break;
  212. case ACC_AVERAGE_16:
  213. data |= 0x20; // 0bxx10xxxx
  214. break;
  215. case ACC_AVERAGE_32:
  216. data |= 0x30; // 0bxx11xxxx
  217. break;
  218. default:
  219. break;
  220. }
  221. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_ACCEL_CONFIG2, 1,&data);
  222. }
  223. void ICM20600_setAccOutputDataRate(acc_lownoise_odr_type_t odr)
  224. {
  225. uint8_t data;
  226. Sensors_I2C_ReadRegister(ICM20600_I2C_ADDR2, ICM20600_ACCEL_CONFIG2, 1, &data);
  227. data &= 0xf0; // 0b11110000
  228. switch(odr)
  229. {
  230. case ACC_RATE_4K_BW_1046:
  231. data |= 0x08;
  232. break;
  233. case ACC_RATE_1K_BW_420:
  234. data |= 0x07;
  235. break;
  236. case ACC_RATE_1K_BW_218:
  237. data |= 0x01;
  238. break;
  239. case ACC_RATE_1K_BW_99:
  240. data |= 0x02;
  241. break;
  242. case ACC_RATE_1K_BW_44:
  243. data |= 0x03;
  244. break;
  245. case ACC_RATE_1K_BW_21:
  246. data |= 0x04;
  247. break;
  248. case ACC_RATE_1K_BW_10:
  249. data |= 0x05;
  250. break;
  251. case ACC_RATE_1K_BW_5:
  252. data |= 0x06;
  253. break;
  254. default:
  255. break;
  256. }
  257. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_ACCEL_CONFIG2, 1, &data);
  258. }
  259. void ICM20600_initialize( void )
  260. {
  261. uint8_t data=0x00;
  262. //I2C初始化
  263. I2C_Bus_Init();
  264. //读取ID,检测是否正常
  265. ICM20600_getDeviceID();
  266. if(ICM20600_OK_Flag == FALSE)
  267. {
  268. return;
  269. }
  270. // configuration
  271. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_CONFIG, 1, &data);
  272. // disable fifo
  273. Sensors_I2C_WriteRegister(ICM20600_I2C_ADDR2, ICM20600_FIFO_EN, 1, &data);
  274. // set default power mode
  275. ICM20600_setPowerMode(ICM_6AXIS_LOW_POWER);
  276. // gyro config
  277. ICM20600_setGyroScaleRange(RANGE_250_DPS);
  278. ICM20600_setGyroOutputDataRate(GYRO_RATE_1K_BW_5);
  279. ICM20600_setGyroAverageSample(GYRO_AVERAGE_1);
  280. // accel config
  281. ICM20600_setAccScaleRange(RANGE_2G);
  282. ICM20600_setAccOutputDataRate(ACC_RATE_1K_BW_5);
  283. ICM20600_setAccAverageSample(ACC_AVERAGE_4);
  284. }
  285. void ICM20600_coefficientinitialize( gyro_scale_type_t gyro_scale, acc_scale_type_t acc_scale, ICM20600_Data_typedef *ICM20600Sensor_temp )
  286. {
  287. ICM20600Sensor_temp->GyroX.offset = 0;
  288. ICM20600Sensor_temp->GyroY.offset = 0;
  289. ICM20600Sensor_temp->GyroZ.offset = 0;
  290. ICM20600Sensor_temp->AcceX.offset = 0;
  291. ICM20600Sensor_temp->AcceY.offset = 0;
  292. ICM20600Sensor_temp->AcceZ.offset = 0;
  293. switch(gyro_scale)
  294. {
  295. case RANGE_250_DPS:
  296. ICM20600Sensor_temp->GyroX.coefficient = 131.07;
  297. ICM20600Sensor_temp->GyroY.coefficient = 131.07;
  298. ICM20600Sensor_temp->GyroZ.coefficient = 131.07;
  299. break;
  300. case RANGE_500_DPS:
  301. ICM20600Sensor_temp->GyroX.coefficient = 65.535;
  302. ICM20600Sensor_temp->GyroY.coefficient = 65.535;
  303. ICM20600Sensor_temp->GyroZ.coefficient = 65.535;
  304. break;
  305. case RANGE_1K_DPS:
  306. ICM20600Sensor_temp->GyroX.coefficient = 32.7675;
  307. ICM20600Sensor_temp->GyroY.coefficient = 32.7675;
  308. ICM20600Sensor_temp->GyroZ.coefficient = 32.7675;
  309. break;
  310. case RANGE_2K_DPS:
  311. ICM20600Sensor_temp->GyroX.coefficient = 16.38375;
  312. ICM20600Sensor_temp->GyroY.coefficient = 16.38375;
  313. ICM20600Sensor_temp->GyroZ.coefficient = 16.38375;
  314. break;
  315. default:
  316. break;
  317. }
  318. switch(acc_scale)
  319. {
  320. case RANGE_2G:
  321. ICM20600Sensor_temp->AcceX.coefficient = 16383.75;
  322. ICM20600Sensor_temp->AcceY.coefficient = 16383.75;
  323. ICM20600Sensor_temp->AcceZ.coefficient = 16383.75;
  324. break;
  325. case RANGE_4G:
  326. ICM20600Sensor_temp->AcceX.coefficient = 8191.875;
  327. ICM20600Sensor_temp->AcceY.coefficient = 8191.875;
  328. ICM20600Sensor_temp->AcceZ.coefficient = 8191.875;
  329. break;
  330. case RANGE_8G:
  331. ICM20600Sensor_temp->AcceX.coefficient = 4095.9375;
  332. ICM20600Sensor_temp->AcceY.coefficient = 4095.9375;
  333. ICM20600Sensor_temp->AcceZ.coefficient = 4095.9375;
  334. break;
  335. case RANGE_16G:
  336. ICM20600Sensor_temp->AcceX.coefficient = 2047.96875;
  337. ICM20600Sensor_temp->AcceY.coefficient = 2047.96875;
  338. ICM20600Sensor_temp->AcceZ.coefficient = 2047.96875;
  339. break;
  340. default:
  341. break;
  342. }
  343. }
  344. void ICM20600_getSensordata( ICM20600_Data_typedef *ICM20600Sensor_temp )
  345. {
  346. uint16_t temp1=0,temp2=0,temp3=0,temp4=0,temp5=0,temp6=0,temp7=0;
  347. Soft_DMP_I2C_Read(ICM20600_I2C_ADDR2,ICM20600_ACCEL_XOUT_H,14,ICM20600Sensor_temp->DataBuffer);
  348. temp1 = ((ICM20600Sensor_temp->DataBuffer[0])<<8) + ICM20600Sensor_temp->DataBuffer[1];
  349. ICM20600Sensor_temp->AcceX.data_raw = temp1;
  350. ICM20600Sensor_temp->AcceX.data_offset = ICM20600Sensor_temp->AcceX.data_raw - ICM20600Sensor_temp->AcceX.offset;
  351. ICM20600Sensor_temp->AcceX.data = (float)ICM20600Sensor_temp->AcceX.data_offset / ICM20600Sensor_temp->AcceX.coefficient;
  352. temp2 = ((ICM20600Sensor_temp->DataBuffer[2])<<8) + ICM20600Sensor_temp->DataBuffer[3];
  353. ICM20600Sensor_temp->AcceY.data_raw = temp2;
  354. ICM20600Sensor_temp->AcceY.data_offset = ICM20600Sensor_temp->AcceY.data_raw - ICM20600Sensor_temp->AcceY.offset;
  355. ICM20600Sensor_temp->AcceY.data = (float)ICM20600Sensor_temp->AcceY.data_offset / ICM20600Sensor_temp->AcceY.coefficient;
  356. temp3 = ((ICM20600Sensor_temp->DataBuffer[4])<<8) + ICM20600Sensor_temp->DataBuffer[5];
  357. ICM20600Sensor_temp->AcceZ.data_raw = temp3;
  358. ICM20600Sensor_temp->AcceZ.data_offset = ICM20600Sensor_temp->AcceZ.data_raw - ICM20600Sensor_temp->AcceZ.offset;
  359. ICM20600Sensor_temp->AcceZ.data = (float)(ICM20600Sensor_temp->AcceZ.data_raw - ICM20600Sensor_temp->AcceZ.offset) / ICM20600Sensor_temp->AcceZ.coefficient;
  360. temp4 = ((ICM20600Sensor_temp->DataBuffer[6])<<8) + ICM20600Sensor_temp->DataBuffer[7];
  361. ICM20600Sensor_temp->Temp.data_raw = temp4;
  362. ICM20600Sensor_temp->Temp.data = ((float)ICM20600Sensor_temp->Temp.data_raw / 326.8) + 25;
  363. temp5 = ((ICM20600Sensor_temp->DataBuffer[8])<<8) + ICM20600Sensor_temp->DataBuffer[9];
  364. ICM20600Sensor_temp->GyroX.data_raw = temp5;
  365. ICM20600Sensor_temp->GyroX.data_offset = ICM20600Sensor_temp->GyroX.data_raw - ICM20600Sensor_temp->GyroX.offset;
  366. ICM20600Sensor_temp->GyroX.data = (float)ICM20600Sensor_temp->GyroX.data_offset / ICM20600Sensor_temp->GyroX.coefficient;
  367. temp6 = ((ICM20600Sensor_temp->DataBuffer[10])<<8) + ICM20600Sensor_temp->DataBuffer[11];
  368. ICM20600Sensor_temp->GyroY.data_raw = temp6;
  369. ICM20600Sensor_temp->GyroY.data_offset = ICM20600Sensor_temp->GyroY.data_raw - ICM20600Sensor_temp->GyroY.offset;
  370. ICM20600Sensor_temp->GyroY.data = (float)ICM20600Sensor_temp->GyroY.data_offset / ICM20600Sensor_temp->GyroY.coefficient;
  371. temp7 = ((ICM20600Sensor_temp->DataBuffer[12])<<8) + ICM20600Sensor_temp->DataBuffer[13];
  372. ICM20600Sensor_temp->GyroZ.data_raw = temp7;
  373. ICM20600Sensor_temp->GyroZ.data_offset = ICM20600Sensor_temp->GyroZ.data_raw - ICM20600Sensor_temp->GyroZ.offset;
  374. ICM20600Sensor_temp->GyroZ.data = (float)ICM20600Sensor_temp->GyroZ.data_offset / ICM20600Sensor_temp->GyroZ.coefficient;
  375. }
  376. void ICM20600_computePitchAndRollAngle( ICM20600_Data_typedef *ICM20600Sensor_temp )
  377. {
  378. float PitchTemp=0.0,RollTemp=0.0;
  379. PitchTemp = asin(ICM20600Sensor_temp->AcceX.data);
  380. RollTemp = atan(0.0 - ICM20600Sensor_temp->AcceZ.data / ICM20600Sensor_temp->AcceY.data);
  381. ICM20600Sensor_temp->PitchAngle = PitchTemp * 57.3;
  382. ICM20600Sensor_temp->RollAngle = RollTemp * 57.3;
  383. }
  384. //-------------------------------------------------------------------------------------------
  385. // Fast inverse square-root
  386. // See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
  387. float invSqrt(float x)
  388. {
  389. float halfx = 0.5f * x;
  390. float y = x;
  391. long i = *(long*)&y;
  392. i = 0x5f3759df - (i>>1);
  393. y = *(float*)&i;
  394. y = y * (1.5f - (halfx * y * y));
  395. y = y * (1.5f - (halfx * y * y));
  396. return y;
  397. }
  398. //-------------------------------------------------------------------------------------------
  399. void ComputeAngles(void)
  400. {
  401. ICM20600Sensor.RollAngle = atan2f(q0*q1 + q2*q3, 0.5f - q1*q1 - q2*q2) * 57.29578f;
  402. ICM20600Sensor.PitchAngle = -asinf(-2.0f * (q1*q3 - q0*q2)) * 57.29578f;
  403. // yaw = atan2f(q1*q2 + q0*q3, 0.5f - q2*q2 - q3*q3);
  404. ICM20600Sensor.Pitch = (int16_t)(ICM20600Sensor.PitchAngle * 10);
  405. ICM20600Sensor.Roll = (int16_t)(ICM20600Sensor.RollAngle * 10);
  406. }
  407. void IMUupdate(float gx, float gy, float gz, float ax, float ay, float az)
  408. {
  409. float recipNorm;
  410. float halfvx, halfvy, halfvz;
  411. float halfex, halfey, halfez;
  412. float qa, qb, qc;
  413. // Convert gyroscope degrees/sec to radians/sec
  414. gx *= 0.0174533f;
  415. gy *= 0.0174533f;
  416. gz *= 0.0174533f;
  417. // Compute feedback only if accelerometer measurement valid
  418. // (avoids NaN in accelerometer normalisation)
  419. if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f)))
  420. {
  421. // Normalise accelerometer measurement
  422. recipNorm = invSqrt(ax * ax + ay * ay + az * az);
  423. ax *= recipNorm;
  424. ay *= recipNorm;
  425. az *= recipNorm;
  426. // Estimated direction of gravity
  427. halfvx = q1 * q3 - q0 * q2;
  428. halfvy = q0 * q1 + q2 * q3;
  429. halfvz = q0 * q0 - 0.5f + q3 * q3;
  430. // Error is sum of cross product between estimated
  431. // and measured direction of gravity
  432. halfex = (ay * halfvz - az * halfvy);
  433. halfey = (az * halfvx - ax * halfvz);
  434. halfez = (ax * halfvy - ay * halfvx);
  435. // Compute and apply integral feedback if enabled
  436. if(twoKi > 0.0f)
  437. {
  438. // integral error scaled by Ki
  439. integralFBx += twoKi * halfex * invSampleFreq;
  440. integralFBy += twoKi * halfey * invSampleFreq;
  441. integralFBz += twoKi * halfez * invSampleFreq;
  442. gx += integralFBx; // apply integral feedback
  443. gy += integralFBy;
  444. gz += integralFBz;
  445. }
  446. else
  447. {
  448. integralFBx = 0.0f; // prevent integral windup
  449. integralFBy = 0.0f;
  450. integralFBz = 0.0f;
  451. }
  452. // Apply proportional feedback
  453. gx += twoKp * halfex;
  454. gy += twoKp * halfey;
  455. gz += twoKp * halfez;
  456. }
  457. // Integrate rate of change of quaternion
  458. gx *= (0.5f * invSampleFreq); // pre-multiply common factors
  459. gy *= (0.5f * invSampleFreq);
  460. gz *= (0.5f * invSampleFreq);
  461. qa = q0;
  462. qb = q1;
  463. qc = q2;
  464. q0 += (-qb * gx - qc * gy - q3 * gz);
  465. q1 += (qa * gx + qc * gz - q3 * gy);
  466. q2 += (qa * gy - qb * gz + q3 * gx);
  467. q3 += (qa * gz + qb * gy - qc * gx);
  468. // Normalise quaternion
  469. recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
  470. q0 *= recipNorm;
  471. q1 *= recipNorm;
  472. q2 *= recipNorm;
  473. q3 *= recipNorm;
  474. }
  475. void BikeAttitude_Process(void)
  476. {
  477. if((ICM20600_OK_Flag == TRUE) && (MC_ConfigParam2.UseAttitudeAngle_Flag == MC_SUPPORT_ENABLE))
  478. {
  479. if(ICM20600Sensor.UpdateEn == ENABLE)/*计算一次5ms*/
  480. {
  481. ICM20600Sensor.UpdateEn = DISABLE;
  482. //计算姿态角度
  483. ICM20600Sensor.count++;
  484. if(ICM20600Sensor.count > 199)
  485. {
  486. ICM20600Sensor.count = 0;
  487. }
  488. ICM20600_getSensordata(&ICM20600Sensor);
  489. IMUupdate(ICM20600Sensor.GyroX.data, -ICM20600Sensor.GyroZ.data, ICM20600Sensor.GyroY.data,
  490. ICM20600Sensor.AcceX.data, -ICM20600Sensor.AcceZ.data, ICM20600Sensor.AcceY.data);
  491. ComputeAngles();
  492. MC_AttitudeAngle.Angle_Pitch_Absolute = ICM20600Sensor.Pitch;
  493. MC_AttitudeAngle.Angle_Pitch_Relative = MC_AttitudeAngle.Angle_Pitch_Absolute - MC_ConfigParam2.ZeroAngle_Pitch;
  494. MC_AttitudeAngle.Angle_Roll_Absolute = ICM20600Sensor.Roll;
  495. MC_AttitudeAngle.Angle_Roll_Relative = MC_AttitudeAngle.Angle_Roll_Absolute - MC_ConfigParam2.ZeroAngle_Roll;
  496. //判断是否处于爬坡状态
  497. if(MC_AttitudeAngle.Angle_Pitch_Relative > 40)
  498. {
  499. Bike_Attitude.UpWardSlope_True_Timecount++;
  500. Bike_Attitude.UpWardSlope_False_Timecount=0;
  501. if(Bike_Attitude.UpWardSlope_True_Timecount > 100)
  502. {
  503. Bike_Attitude.UpWardSlope_True_Timecount=0;
  504. Bike_Attitude.UpWardSlope_flag = TRUE;
  505. }
  506. }
  507. else
  508. {
  509. Bike_Attitude.UpWardSlope_True_Timecount=0;
  510. Bike_Attitude.UpWardSlope_False_Timecount++;
  511. if(Bike_Attitude.UpWardSlope_False_Timecount > 100)
  512. {
  513. Bike_Attitude.UpWardSlope_False_Timecount=0;
  514. Bike_Attitude.UpWardSlope_flag = FALSE;
  515. }
  516. }
  517. //判断车辆是否倒下
  518. if((MC_AttitudeAngle.Angle_Roll_Relative > 450) || (MC_AttitudeAngle.Angle_Roll_Relative < -450))
  519. {
  520. Bike_Attitude.FellDown_True_Timecount++;
  521. Bike_Attitude.FellDown_False_Timecount=0;
  522. if(Bike_Attitude.FellDown_True_Timecount > 100)
  523. {
  524. Bike_Attitude.FellDown_True_Timecount=0;
  525. Bike_Attitude.FellDown_flag = TRUE;
  526. }
  527. }
  528. else
  529. {
  530. Bike_Attitude.FellDown_True_Timecount=0;
  531. Bike_Attitude.FellDown_False_Timecount++;
  532. if(Bike_Attitude.FellDown_False_Timecount > 100)
  533. {
  534. Bike_Attitude.FellDown_False_Timecount=0;
  535. Bike_Attitude.FellDown_flag = FALSE;
  536. }
  537. }
  538. }
  539. }
  540. else
  541. {
  542. Bike_Attitude.UpWardSlope_flag = FALSE;
  543. Bike_Attitude.FellDown_flag = FALSE;
  544. }
  545. }