app_ImuCalibration - 副本.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. #include <math.h>
  2. #include "stdio.h"
  3. #include "ble_comm.h"
  4. #include "hal_flash.h"
  5. #include "hal_imu.h"
  6. #include "hal_step.h"
  7. #include "system.h"
  8. #include "bsp_time.h"
  9. #include "app_ImuCalibration.h"
  10. #include "app_charge.h"
  11. #include "hal_ble_client.h"
  12. #include "bmi160_support.h"
  13. #include "hal_attitude.h"
  14. #if CALIBRATION_ENANBLE
  15. enum{
  16. ImuCal_init,
  17. ImuCal_GetData,
  18. ImuCal_Analyze,
  19. ImuCal_finish,
  20. ImuCal_error,
  21. ImuCal_quiet,
  22. };
  23. char printfbuf[256];
  24. void send_ANO(unsigned char fun, unsigned char* p, int len);
  25. #define Mahony_PRINT(...) send_ANO(0,(unsigned char*)printfbuf,sprintf(printfbuf,__VA_ARGS__))
  26. #define ERROR_PIN_ON nrf_gpio_pin_write(PIN_LED_RUN,0);
  27. #define ERROR_PIN_OFF nrf_gpio_pin_write(PIN_LED_RUN,1);
  28. static float invSampleFreq = 0.010f; //采样率(Hz)
  29. //匿名四轴上位机api
  30. void send_ANO(unsigned char fun, unsigned char* p, int len){
  31. unsigned char buf[256];
  32. int L = 0;
  33. unsigned char ver = 0;
  34. buf[L] = 0xAA;
  35. ver += buf[L++];
  36. buf[L] = 0x05;
  37. ver += buf[L++];
  38. buf[L] = 0xAF;
  39. ver += buf[L++];
  40. buf[L] = fun;
  41. ver += buf[L++];
  42. buf[L] = len;
  43. ver += buf[L++];
  44. for (int i = 0; i < len; i++)
  45. {
  46. buf[L] = p[i];
  47. ver += buf[L++];
  48. }
  49. buf[L++] = ver;
  50. // extern void send_bytes_client(unsigned char* bytes, int len);
  51. send_bytes_client(buf, L);
  52. // SEGGER_RTT_Write(0,buf, L);
  53. // ESB_SendBuff(buf,L);
  54. }
  55. void send_ANO_Quaternion(float* Q){
  56. unsigned char buf[256];
  57. unsigned char L = 0;
  58. int quat[4];
  59. quat[0] = Q[0] * 10000;
  60. quat[1] = Q[1] * 10000;
  61. quat[2] = Q[2] * 10000;
  62. quat[3] = Q[3] * 10000;
  63. buf[L++] = (unsigned char)(quat[0] >> 24);
  64. buf[L++] = (unsigned char)(quat[0] >> 16);
  65. buf[L++] = (unsigned char)(quat[0] >> 8);
  66. buf[L++] = (unsigned char)(quat[0] >> 0);
  67. buf[L++] = (unsigned char)(quat[1] >> 24);
  68. buf[L++] = (unsigned char)(quat[1] >> 16);
  69. buf[L++] = (unsigned char)(quat[1] >> 8);
  70. buf[L++] = (unsigned char)(quat[1] >> 0);
  71. buf[L++] = (unsigned char)(quat[2] >> 24);
  72. buf[L++] = (unsigned char)(quat[2] >> 16);
  73. buf[L++] = (unsigned char)(quat[2] >> 8);
  74. buf[L++] = (unsigned char)(quat[2] >> 0);
  75. buf[L++] = (unsigned char)(quat[3] >> 24);
  76. buf[L++] = (unsigned char)(quat[3] >> 16);
  77. buf[L++] = (unsigned char)(quat[3] >> 8);
  78. buf[L++] = (unsigned char)(quat[3] >> 0);
  79. buf[L++] = 0;
  80. send_ANO(0x03, buf, L);
  81. }
  82. void send_ANO_STATUS(float _roll, float _pitch, float _yaw, float _posx, float _posy, float _posz){
  83. unsigned char buf[256];
  84. unsigned char L = 0;
  85. short roll = _roll * 100;
  86. short pitch = _pitch * 100;
  87. short yaw = _yaw * 100;
  88. short posx = _posx * 100;
  89. short posy = _posy * 100;
  90. short posz = _posz * 100;
  91. buf[L++] = (unsigned char)(roll >> 8);
  92. buf[L++] = (unsigned char)(roll >> 0);
  93. buf[L++] = (unsigned char)(pitch >> 8);
  94. buf[L++] = (unsigned char)(pitch >> 0);
  95. buf[L++] = (unsigned char)(yaw >> 8);
  96. buf[L++] = (unsigned char)(yaw >> 0);
  97. buf[L++] = (unsigned char)(posx >> 8);
  98. buf[L++] = (unsigned char)(posx >> 0);
  99. buf[L++] = (unsigned char)(posy >> 8);
  100. buf[L++] = (unsigned char)(posy >> 0);
  101. buf[L++] = (unsigned char)(posz >> 8);
  102. buf[L++] = (unsigned char)(posz >> 0);
  103. buf[L++] = 0;
  104. send_ANO(0x01, buf, L);
  105. }
  106. void send_ANO_SENSER(short gx, short gy, short gz, short ax, short ay, short az, short mx, short my, short mz){
  107. unsigned char buf[256];
  108. unsigned char L = 0;
  109. buf[L++] = (unsigned char)(ax >> 8);
  110. buf[L++] = (unsigned char)(ax >> 0);
  111. buf[L++] = (unsigned char)(ay >> 8);
  112. buf[L++] = (unsigned char)(ay >> 0);
  113. buf[L++] = (unsigned char)(az >> 8);
  114. buf[L++] = (unsigned char)(az >> 0);
  115. buf[L++] = (unsigned char)(gx >> 8);
  116. buf[L++] = (unsigned char)(gx >> 0);
  117. buf[L++] = (unsigned char)(gy >> 8);
  118. buf[L++] = (unsigned char)(gy >> 0);
  119. buf[L++] = (unsigned char)(gz >> 8);
  120. buf[L++] = (unsigned char)(gz >> 0);
  121. buf[L++] = (unsigned char)(mx >> 8);
  122. buf[L++] = (unsigned char)(mx >> 0);
  123. buf[L++] = (unsigned char)(my >> 8);
  124. buf[L++] = (unsigned char)(my >> 0);
  125. buf[L++] = (unsigned char)(mz >> 8);
  126. buf[L++] = (unsigned char)(mz >> 0);
  127. send_ANO(0x02, buf, L);
  128. }
  129. //LDLT分解法解线性方程组,和LDLTBKSB_6一起用
  130. char LDLTDCMP_6(int n, float (*a)[6]){
  131. int k;
  132. int m;
  133. int i;
  134. for (k = 0; k < n; k++){
  135. for (m = 0; m < k; m++){
  136. a[k][k] = a[k][k] - a[m][k] * a[k][m];
  137. }
  138. if (a[k][k] == 0){
  139. return 1;//error
  140. }
  141. for(i = k + 1; i < n; i++){
  142. for (m = 0; m < k; m++){
  143. a[k][i] = a[k][i] - a[m][i] * a[k][m];
  144. }
  145. a[i][k] = a[k][i] / a[k][k];
  146. }
  147. }
  148. return 0;
  149. }
  150. //LDLT分解法解线性方程组,和LDLTDCMP_6一起用
  151. void LDLTBKSB_6(int n, float (*a)[6], float* b)
  152. {
  153. int k;
  154. int i;
  155. for (i = 0; i < n; i++){
  156. for (k = 0; k < i; k++){
  157. b[i] = b[i] - a[i][k] * b[k];
  158. }
  159. }
  160. for (i = n - 1; i >= 0; i--){
  161. b[i] = b[i] / a[i][i];
  162. for (k = i + 1; k < n; k++){
  163. b[i] = b[i] - a[k][i] * b[k];
  164. }
  165. }
  166. }
  167. float Acc_static_calibration_b[6] = {0.0f};
  168. float Acc_static_calibration_D[6][6] = {0.0f};
  169. float Acc_static_calibration_out[6] = {1.000718f, 1.001100f, 0.988632f, 0.012943f, 0.006423f, 0.0034f}; //V1.3板
  170. void Ellipsoidfit_six_pram_update(float X, float Y, float Z, float* b, float (*D)[6]){
  171. float coft[6] = {0.0f};
  172. int r, j;
  173. coft[0] = X * X;
  174. coft[3] = 2.0f * X;
  175. coft[1] = Y * Y;
  176. coft[4] = 2.0f * Y;
  177. coft[2] = Z * Z;
  178. coft[5] = 2.0f * Z;
  179. for (j = 0; j < 6; j++){
  180. b[j] += coft[j];
  181. }
  182. for (r = 0; r < 6; r++){
  183. for (j = 0; j <= r; j++){
  184. D[r][j] += coft[r] * coft[j];
  185. }
  186. }
  187. for (r = 0; r < 6; r++){
  188. for (j = 5; j > r; j--){
  189. D[r][j] = D[j][r];
  190. }
  191. }
  192. }
  193. void Ellipsoidfit_six_pram_Solution(float* b, float (*D)[6], float* out)
  194. {
  195. float temp = 0;
  196. //解线性方程组,求解超定方程最小二乘解
  197. LDLTDCMP_6(6, D);
  198. LDLTBKSB_6(6, D, b);
  199. temp = b[1] * b[2] * b[3] * b[3] + b[0] * b[2] * b[4] * b[4] + b[0] * b[1] * b[5] * b[5];
  200. temp = 1.0f - (temp / (temp + (b[0] * b[1] * b[2])));
  201. out[0] = sqrtf(temp * b[0]);
  202. out[1] = sqrtf(temp * b[1]);
  203. out[2] = sqrtf(temp * b[2]);
  204. out[3] = b[3] * temp / out[0];
  205. out[4] = b[4] * temp / out[1];
  206. out[5] = b[5] * temp / out[2];
  207. }
  208. //需要200ms执行一次,开始信号检测,检测到返回1,否则返回0
  209. char begin_REC(float *acc)
  210. {
  211. static float Acc_before[3];
  212. static float accmod,accmodbef;
  213. static char cun=0;
  214. float gyrmod = acc[0]*Acc_before[0]+acc[1]*Acc_before[1]+acc[2]*Acc_before[2];
  215. accmod = sqrtf(acc[0] * acc[0] + acc[1] * acc[1] + acc[2] * acc[2]);
  216. gyrmod=gyrmod/(accmod*accmodbef);
  217. gyrmod=acos(gyrmod)*3.14;
  218. Acc_before[0]=acc[0];Acc_before[1]=acc[1];Acc_before[2]=acc[2];
  219. accmodbef=accmod;
  220. Mahony_PRINT("accmodbef:%f,gyrmod:%f,cun:%d\n",accmodbef,gyrmod,cun);
  221. if((gyrmod > 0.25f)&&(gyrmod < 0.75f))
  222. {
  223. cun++;
  224. }else cun=0;
  225. if(cun>=10){
  226. cun=0;
  227. return 1;
  228. }
  229. else return 0;
  230. }
  231. static uint8_t ImuCal_state = ImuCal_init;
  232. char Acc_static_calibration(float* Acc_in, float* Acc_out, const float* gyr)
  233. {
  234. static int temp = 0;
  235. static int overtime = 0;
  236. static int caiyingcun = 0;
  237. switch (ImuCal_state){
  238. case ImuCal_init:{//未校准状态
  239. if(begin_REC(Acc_in)){
  240. ImuCal_state = ImuCal_GetData;
  241. caiyingcun = 0;
  242. overtime = 0;
  243. for (int i = 0; i < 6; i++){
  244. Acc_static_calibration_b[i] = 0.0f;
  245. Acc_static_calibration_D[i][0] = 0.0f;
  246. Acc_static_calibration_D[i][1] = 0.0f;
  247. Acc_static_calibration_D[i][2] = 0.0f;
  248. Acc_static_calibration_D[i][3] = 0.0f;
  249. Acc_static_calibration_D[i][4] = 0.0f;
  250. Acc_static_calibration_D[i][5] = 0.0f;
  251. }
  252. ERROR_PIN_ON
  253. Mahony_PRINT("Acc_static_calibration -> start \r\n");
  254. temp = 0;
  255. }
  256. }
  257. break;
  258. case ImuCal_GetData:{//采集校准数据状态
  259. float gyrmod = sqrtf(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
  260. if (gyrmod < 18.27f){ //静止检测
  261. //采样数据
  262. if(((Acc_in[0]<2.0f)||(Acc_in[0]>-2.0f))&&((Acc_in[1]<2.0f)||(Acc_in[1]>-2.0f))&&((Acc_in[2]<2.0f)||(Acc_in[2]>-2.0f))){
  263. Ellipsoidfit_six_pram_update(Acc_in[0], Acc_in[1], Acc_in[2], Acc_static_calibration_b, Acc_static_calibration_D);
  264. caiyingcun++;
  265. send_ANO_SENSER(gyr[0] * 100, gyr[1] * 100, gyr[2] * 100, Acc_in[0] * 100, Acc_in[1] * 100, Acc_in[2] * 100, 0, 0, 0);
  266. }
  267. }
  268. //检测结束条件
  269. if ((gyrmod > 30.0f) && (gyrmod < 60.0f) && (caiyingcun > 20)){
  270. temp = temp + 1;
  271. }
  272. else{
  273. temp = 0;
  274. }
  275. if (temp * invSampleFreq > 2.0f){
  276. Ellipsoidfit_six_pram_Solution(Acc_static_calibration_b, Acc_static_calibration_D, Acc_static_calibration_out);
  277. ImuCal_state = ImuCal_Analyze;
  278. Mahony_PRINT("ImuCal_state ImuCal_GetData");
  279. }
  280. overtime++;
  281. if (overtime * invSampleFreq > 150.0f){
  282. ImuCal_state = ImuCal_error;
  283. Mahony_PRINT("ImuCal_state ImuCal_error");
  284. }
  285. }
  286. break;
  287. case ImuCal_Analyze:{//校准数据处理状态
  288. float gyrmod = sqrtf(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
  289. if (gyrmod < 18.27f){ //静止检测
  290. if (((Acc_static_calibration_out[0] > 0.85f) && (Acc_static_calibration_out[0] < 1.15f)) &&
  291. ((Acc_static_calibration_out[1] > 0.85f) && (Acc_static_calibration_out[1] < 1.15f)) &&
  292. ((Acc_static_calibration_out[2] > 0.85f) && (Acc_static_calibration_out[2] < 1.15f))){
  293. // Mahony_PRINT("out[%f,%f,%f,%f,%f,%f] \r\n", Acc_static_calibration_out[0], Acc_static_calibration_out[1], Acc_static_calibration_out[2], Acc_static_calibration_out[3], Acc_static_calibration_out[4], Acc_static_calibration_out[5]);
  294. Mahony_PRINT("ImuCal_state ImuCal_finish");
  295. temp = 0;
  296. ImuCal_state = ImuCal_finish;
  297. for(int a = 0; a < 6; a++){
  298. mBackup.cal[a] = Acc_static_calibration_out[a];
  299. }
  300. }
  301. else{
  302. ImuCal_state = ImuCal_quiet;
  303. }
  304. overtime = 0;
  305. }
  306. }
  307. break;
  308. // case ImuCal_finish:{//已经校准完状态
  309. // Mahony_PRINT("ImuCal_state ImuCal_init");
  310. // ImuCal_state = 0;
  311. // }
  312. // break;
  313. // case ImuCal_error:{//校准过程中断退出状态
  314. // Mahony_PRINT("ImuCal_state ImuCal_init");
  315. // ImuCal_state = 0;
  316. // Mahony_PRINT("ImuCal_state ImuCal_init");
  317. // }
  318. // break;
  319. // case ImuCal_quiet:{//校准过程中断退出状态
  320. // ImuCal_state = 0;
  321. // }
  322. // break;
  323. }
  324. return ImuCal_state;
  325. }
  326. void Mahony_imu_lbs(short* Acc_in, short* Gyr_in, short* Mag_in, float* Acc, float* Gyr, float* Mag)
  327. {
  328. float ACC_LBS = 32768.0f / 16.0f;
  329. float GYR_LBS = 32768.0f / 2000.0f;
  330. Acc[0] = Acc_in[0] / ACC_LBS;
  331. Acc[1] = Acc_in[1] / ACC_LBS;
  332. Acc[2] = Acc_in[2] / ACC_LBS;
  333. Gyr[0] = Gyr_in[0] / GYR_LBS;
  334. Gyr[1] = Gyr_in[1] / GYR_LBS;
  335. Gyr[2] = Gyr_in[2] / GYR_LBS;
  336. Mag[0] = Mag_in[0] / 1.0f;
  337. Mag[1] = Mag_in[1] / 1.0f;
  338. Mag[2] = Mag_in[2] / 1.0f;
  339. }
  340. static float acc[3], gyr[3], mag[3];
  341. static void ImuCalibration_pcs(short* Acc, short* Gyr, short* Mag)
  342. {
  343. Mahony_imu_lbs(Acc, Gyr, Mag, acc, gyr, mag); //转换IMU数据量程,加速度单位转换为G,陀螺仪单位转换为度每秒,磁力计不需要转换单位,后面会做归一化处理
  344. Acc_static_calibration(acc, NULL, gyr);
  345. }
  346. /***********************************
  347. *未校准:灭灯
  348. *校准中:指示灯常亮
  349. *校准完成:指示灯慢闪,亮10ms,灭灯2S
  350. *校准错误:指示灯快闪,亮10ms,灭灯100ms
  351. ************************************/
  352. static void app_ImuCalLed_process(void){
  353. nrf_gpio_pin_write(PIN_LED_RUN,0);
  354. nrf_delay_ms(10);
  355. nrf_gpio_pin_write(PIN_LED_RUN,1);
  356. char printdata[200]={0};
  357. sprintf(printdata,"caldata:%f,%f,%f,%f,%f,%f",mBackup.cal[0],mBackup.cal[1],mBackup.cal[2],mBackup.cal[3],mBackup.cal[4],mBackup.cal[5]);
  358. SEGGER_RTT_printf(0,"%s\n",printdata);
  359. Mahony_PRINT("caldata:%f,%f,%f,%f,%f,%f",mBackup.cal[0],mBackup.cal[1],mBackup.cal[2],mBackup.cal[3],mBackup.cal[4],mBackup.cal[5]);
  360. }
  361. uint8_t app_imucal_getstate(void){
  362. if(ImuCal_GetData == ImuCal_state || ImuCal_Analyze == ImuCal_state)return 1;
  363. else return 0;
  364. }
  365. static void app_cal_process(void){
  366. static uint8_t state =0;
  367. static uint8_t temp =0;
  368. int16_t Acc[3]={0};
  369. int16_t Gry[3]={0};
  370. int16_t Mag[3]={0};
  371. switch(state){
  372. case 0:
  373. IMU_GetAcc(Acc);
  374. IMU_GetGry(Gry);
  375. // SEGGER_RTT_printf(0,"h_ax=%d\r,h_ay=%d\r,h_az=%d\r\n",Acc[0],Acc[1],Acc[2]);
  376. // SEGGER_RTT_printf(0,"h_gx=%d\r,h_gy=%d\r,h_gz=%d\r\n",Gry[0],Gry[1],Gry[2]);
  377. ImuCalibration_pcs((short *)Acc,(short *)Gry,(short *)Mag);
  378. if(ImuCal_state == ImuCal_GetData){
  379. Process_UpdatePeroid(app_cal_process,10);
  380. Process_SetHoldOn(app_cal_process,1);
  381. nrf_gpio_pin_write(PIN_LED_RUN,0);
  382. hal_attitude_setMode(STANDARD_UI_IMU);
  383. state =1;
  384. temp=0;
  385. }
  386. break;
  387. case 1:
  388. if(1 == hal_attitude_GetMode(STANDARD_UI_IMU)){
  389. state =2;
  390. }else if(temp++ >=20)state =0;
  391. break;
  392. case 2:
  393. IMU_GetAcc(Acc);
  394. IMU_GetGry(Gry);
  395. ImuCalibration_pcs((short *)Acc,(short *)Gry,(short *)Mag);
  396. // SEGGER_RTT_printf(0,">>>>>>>22222\n");
  397. if(ImuCal_state == ImuCal_finish){
  398. Flash_SaveBackup();
  399. Mahony_PRINT("ImuCal_state ImuCal_finish");
  400. Process_Start(2000,"app_cal_process",app_ImuCalLed_process);
  401. Process_UpdatePeroid(app_ImuCalLed_process,2000);
  402. Process_UpdatePeroid(app_cal_process,200);
  403. Process_SetHoldOn(app_cal_process,0);
  404. hal_attitude_setMode(ACCEL_PEDOMETER_FIFO);
  405. state =3;
  406. }
  407. else if(ImuCal_state == ImuCal_error || ImuCal_state == ImuCal_quiet){
  408. Mahony_PRINT("ImuCal_state ImuCal_error");
  409. Process_Start(100,"app_cal_process",app_ImuCalLed_process);
  410. Process_UpdatePeroid(app_ImuCalLed_process,100);
  411. Process_UpdatePeroid(app_cal_process,200);
  412. Process_SetHoldOn(app_cal_process,1);
  413. hal_attitude_setMode(ACCEL_PEDOMETER_FIFO);
  414. state =3;
  415. }
  416. break;
  417. case 3:
  418. if(1 == hal_attitude_GetMode(ACCEL_PEDOMETER_FIFO)){
  419. state = 4;
  420. }
  421. else if(++temp>20){ temp = 0;
  422. state = 4;
  423. }
  424. break;
  425. case 4:
  426. if(app_charge_Getstate() == BLE_Client_T_CHARGE_INSERT || app_charge_Getstate() == BLE_Client_T_CHARGE_DONE){
  427. state =0;
  428. ImuCal_state = ImuCal_init;
  429. Process_Stop(app_ImuCalLed_process);
  430. nrf_gpio_pin_write(PIN_LED_RUN,1);
  431. }
  432. break;
  433. }
  434. }
  435. void app_ImuCalibration_init(void){
  436. Process_Start(200,"app_cal_process",app_cal_process);
  437. }
  438. #endif