drv_calibration.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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 "system.h"
  7. #include "bsp_time.h"
  8. #include "drv_calibration.h"
  9. #include "app_charge.h"
  10. #include "hal_ble_client.h"
  11. char calibration_printfbuf[256];
  12. static float invSampleFreq = 0.010f; //采样率(Hz)
  13. #define ERROR_PIN_ON nrf_gpio_pin_write(PIN_LED_RUN,0);
  14. #define ERROR_PIN_OFF nrf_gpio_pin_write(PIN_LED_RUN,1);
  15. //匿名四轴上位机api
  16. void send_ANO(unsigned char fun, unsigned char* p, int len){
  17. unsigned char buf[256];
  18. int L = 0;
  19. unsigned char ver = 0;
  20. buf[L] = 0xAA;
  21. ver += buf[L++];
  22. buf[L] = 0x05;
  23. ver += buf[L++];
  24. buf[L] = 0xAF;
  25. ver += buf[L++];
  26. buf[L] = fun;
  27. ver += buf[L++];
  28. buf[L] = len;
  29. ver += buf[L++];
  30. for (int i = 0; i < len; i++)
  31. {
  32. buf[L] = p[i];
  33. ver += buf[L++];
  34. }
  35. buf[L++] = ver;
  36. // extern void send_bytes_client(unsigned char* bytes, int len);
  37. send_bytes_client(buf, L);
  38. // SEGGER_RTT_Write(0,buf, L);
  39. // ESB_SendBuff(buf,L);
  40. }
  41. void send_ANO_Quaternion(float* Q){
  42. unsigned char buf[256];
  43. unsigned char L = 0;
  44. int quat[4];
  45. quat[0] = Q[0] * 10000;
  46. quat[1] = Q[1] * 10000;
  47. quat[2] = Q[2] * 10000;
  48. quat[3] = Q[3] * 10000;
  49. buf[L++] = (unsigned char)(quat[0] >> 24);
  50. buf[L++] = (unsigned char)(quat[0] >> 16);
  51. buf[L++] = (unsigned char)(quat[0] >> 8);
  52. buf[L++] = (unsigned char)(quat[0] >> 0);
  53. buf[L++] = (unsigned char)(quat[1] >> 24);
  54. buf[L++] = (unsigned char)(quat[1] >> 16);
  55. buf[L++] = (unsigned char)(quat[1] >> 8);
  56. buf[L++] = (unsigned char)(quat[1] >> 0);
  57. buf[L++] = (unsigned char)(quat[2] >> 24);
  58. buf[L++] = (unsigned char)(quat[2] >> 16);
  59. buf[L++] = (unsigned char)(quat[2] >> 8);
  60. buf[L++] = (unsigned char)(quat[2] >> 0);
  61. buf[L++] = (unsigned char)(quat[3] >> 24);
  62. buf[L++] = (unsigned char)(quat[3] >> 16);
  63. buf[L++] = (unsigned char)(quat[3] >> 8);
  64. buf[L++] = (unsigned char)(quat[3] >> 0);
  65. buf[L++] = 0;
  66. send_ANO(0x03, buf, L);
  67. }
  68. void send_ANO_STATUS(float _roll, float _pitch, float _yaw, float _posx, float _posy, float _posz){
  69. unsigned char buf[256];
  70. unsigned char L = 0;
  71. short roll = _roll * 100;
  72. short pitch = _pitch * 100;
  73. short yaw = _yaw * 100;
  74. short posx = _posx * 100;
  75. short posy = _posy * 100;
  76. short posz = _posz * 100;
  77. buf[L++] = (unsigned char)(roll >> 8);
  78. buf[L++] = (unsigned char)(roll >> 0);
  79. buf[L++] = (unsigned char)(pitch >> 8);
  80. buf[L++] = (unsigned char)(pitch >> 0);
  81. buf[L++] = (unsigned char)(yaw >> 8);
  82. buf[L++] = (unsigned char)(yaw >> 0);
  83. buf[L++] = (unsigned char)(posx >> 8);
  84. buf[L++] = (unsigned char)(posx >> 0);
  85. buf[L++] = (unsigned char)(posy >> 8);
  86. buf[L++] = (unsigned char)(posy >> 0);
  87. buf[L++] = (unsigned char)(posz >> 8);
  88. buf[L++] = (unsigned char)(posz >> 0);
  89. buf[L++] = 0;
  90. send_ANO(0x01, buf, L);
  91. }
  92. void send_ANO_SENSER(short gx, short gy, short gz, short ax, short ay, short az, short mx, short my, short mz){
  93. unsigned char buf[256];
  94. unsigned char L = 0;
  95. buf[L++] = (unsigned char)(ax >> 8);
  96. buf[L++] = (unsigned char)(ax >> 0);
  97. buf[L++] = (unsigned char)(ay >> 8);
  98. buf[L++] = (unsigned char)(ay >> 0);
  99. buf[L++] = (unsigned char)(az >> 8);
  100. buf[L++] = (unsigned char)(az >> 0);
  101. buf[L++] = (unsigned char)(gx >> 8);
  102. buf[L++] = (unsigned char)(gx >> 0);
  103. buf[L++] = (unsigned char)(gy >> 8);
  104. buf[L++] = (unsigned char)(gy >> 0);
  105. buf[L++] = (unsigned char)(gz >> 8);
  106. buf[L++] = (unsigned char)(gz >> 0);
  107. buf[L++] = (unsigned char)(mx >> 8);
  108. buf[L++] = (unsigned char)(mx >> 0);
  109. buf[L++] = (unsigned char)(my >> 8);
  110. buf[L++] = (unsigned char)(my >> 0);
  111. buf[L++] = (unsigned char)(mz >> 8);
  112. buf[L++] = (unsigned char)(mz >> 0);
  113. send_ANO(0x02, buf, L);
  114. }
  115. //LDLT分解法解线性方程组,和LDLTBKSB_6一起用
  116. char LDLTDCMP_6(int n, float (*a)[6]){
  117. int k;
  118. int m;
  119. int i;
  120. for (k = 0; k < n; k++){
  121. for (m = 0; m < k; m++){
  122. a[k][k] = a[k][k] - a[m][k] * a[k][m];
  123. }
  124. if (a[k][k] == 0){
  125. return 1;//error
  126. }
  127. for(i = k + 1; i < n; i++){
  128. for (m = 0; m < k; m++){
  129. a[k][i] = a[k][i] - a[m][i] * a[k][m];
  130. }
  131. a[i][k] = a[k][i] / a[k][k];
  132. }
  133. }
  134. return 0;
  135. }
  136. //LDLT分解法解线性方程组,和LDLTDCMP_6一起用
  137. void LDLTBKSB_6(int n, float (*a)[6], float* b)
  138. {
  139. int k;
  140. int i;
  141. for (i = 0; i < n; i++){
  142. for (k = 0; k < i; k++){
  143. b[i] = b[i] - a[i][k] * b[k];
  144. }
  145. }
  146. for (i = n - 1; i >= 0; i--){
  147. b[i] = b[i] / a[i][i];
  148. for (k = i + 1; k < n; k++){
  149. b[i] = b[i] - a[k][i] * b[k];
  150. }
  151. }
  152. }
  153. float Acc_static_calibration_b[6] = {0.0f};
  154. float Acc_static_calibration_D[6][6] = {0.0f};
  155. float Acc_static_calibration_out[6] = {1.000718f, 1.001100f, 0.988632f, 0.012943f, 0.006423f, 0.0034f}; //V1.3板
  156. void Ellipsoidfit_six_pram_update(float X, float Y, float Z, float* b, float (*D)[6]){
  157. float coft[6] = {0.0f};
  158. int r, j;
  159. coft[0] = X * X;
  160. coft[3] = 2.0f * X;
  161. coft[1] = Y * Y;
  162. coft[4] = 2.0f * Y;
  163. coft[2] = Z * Z;
  164. coft[5] = 2.0f * Z;
  165. for (j = 0; j < 6; j++){
  166. b[j] += coft[j];
  167. }
  168. for (r = 0; r < 6; r++){
  169. for (j = 0; j <= r; j++){
  170. D[r][j] += coft[r] * coft[j];
  171. }
  172. }
  173. for (r = 0; r < 6; r++){
  174. for (j = 5; j > r; j--){
  175. D[r][j] = D[j][r];
  176. }
  177. }
  178. }
  179. void Ellipsoidfit_six_pram_Solution(float* b, float (*D)[6], float* out)
  180. {
  181. float temp = 0;
  182. //解线性方程组,求解超定方程最小二乘解
  183. LDLTDCMP_6(6, D);
  184. LDLTBKSB_6(6, D, b);
  185. 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];
  186. temp = 1.0f - (temp / (temp + (b[0] * b[1] * b[2])));
  187. out[0] = sqrtf(temp * b[0]);
  188. out[1] = sqrtf(temp * b[1]);
  189. out[2] = sqrtf(temp * b[2]);
  190. out[3] = b[3] * temp / out[0];
  191. out[4] = b[4] * temp / out[1];
  192. out[5] = b[5] * temp / out[2];
  193. }
  194. static float Acc_before[3];
  195. static float accmod=0,accmodbef=0;
  196. static char cun=0;
  197. static unsigned int timer_cli=0;
  198. //需要200ms执行一次,开始信号检测,检测到返回1,否则返回0
  199. char begin_REC(float *acccli)
  200. {
  201. float gyrmod = 0;
  202. gyrmod = (acccli[0]*Acc_before[0]) + (acccli[1]*Acc_before[1]) + (acccli[2]*Acc_before[2]);
  203. accmod = sqrtf(acccli[0] * acccli[0] + acccli[1] * acccli[1] + acccli[2] * acccli[2]);
  204. gyrmod = gyrmod/(accmod * accmodbef);
  205. gyrmod = acosf(gyrmod)*3.14f;
  206. Acc_before[0]=acccli[0];Acc_before[1]=acccli[1];Acc_before[2]=acccli[2];
  207. accmodbef=accmod;
  208. Mahony_PRINT("gyrmod:%f,timer:%d cun:%d %f\n",gyrmod,TIME_GetTicks()-timer_cli,cun,accmodbef);
  209. timer_cli=TIME_GetTicks();
  210. if((gyrmod > 0.25f)&&(gyrmod < 0.75f))
  211. {
  212. cun++;
  213. }else
  214. {
  215. // if(cun>=3)cun--;else
  216. cun=0;
  217. }
  218. if(cun>=10){
  219. cun=0;
  220. return 1;
  221. }
  222. else return 0;
  223. }
  224. static uint8_t ImuCal_state = ImuCal_init;
  225. char Acc_static_calibration(float* Acc_in, float* Acc_out, const float* gyr)
  226. {
  227. static int temp = 0;
  228. static int overtime = 0;
  229. static int caiyingcun = 0;
  230. switch (ImuCal_state){
  231. case ImuCal_init:{//未校准状态
  232. if(begin_REC(Acc_in)){
  233. ImuCal_state = ImuCal_GetData;
  234. caiyingcun = 0;
  235. overtime = 0;
  236. for (int i = 0; i < 6; i++){
  237. Acc_static_calibration_b[i] = 0.0f;
  238. Acc_static_calibration_D[i][0] = 0.0f;
  239. Acc_static_calibration_D[i][1] = 0.0f;
  240. Acc_static_calibration_D[i][2] = 0.0f;
  241. Acc_static_calibration_D[i][3] = 0.0f;
  242. Acc_static_calibration_D[i][4] = 0.0f;
  243. Acc_static_calibration_D[i][5] = 0.0f;
  244. }
  245. ERROR_PIN_ON
  246. Mahony_PRINT("Acc_static_calibration -> start \r\n");
  247. temp = 0;
  248. }
  249. }
  250. break;
  251. case ImuCal_GetData:{//采集校准数据状态
  252. float gyrmod = sqrtf(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
  253. if (gyrmod < 18.27f){ //静止检测
  254. //采样数据
  255. 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))){
  256. Ellipsoidfit_six_pram_update(Acc_in[0], Acc_in[1], Acc_in[2], Acc_static_calibration_b, Acc_static_calibration_D);
  257. caiyingcun++;
  258. 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);
  259. }
  260. }
  261. //检测结束条件
  262. if ((gyrmod > 25.0f) && (gyrmod < 60.0f) && (caiyingcun > 20)){
  263. temp = temp + 1;
  264. }
  265. else{
  266. if(temp>50)temp--;else temp = 0;
  267. }
  268. if (temp * invSampleFreq > 2.0f){
  269. Ellipsoidfit_six_pram_Solution(Acc_static_calibration_b, Acc_static_calibration_D, Acc_static_calibration_out);
  270. ImuCal_state = ImuCal_Analyze;
  271. Mahony_PRINT("ImuCal_GetData");
  272. }
  273. else
  274. {
  275. // Mahony_PRINT("ImuCal_GetData temp %d",temp);
  276. }
  277. overtime++;
  278. if (overtime * invSampleFreq > 300.0f){
  279. ImuCal_state = ImuCal_error;
  280. Mahony_PRINT("ImuCal overtime ImuCal_error");
  281. }
  282. }
  283. break;
  284. case ImuCal_Analyze:{//校准数据处理状态
  285. float gyrmod = sqrtf(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
  286. if (gyrmod < 18.27f){ //静止检测
  287. if (((Acc_static_calibration_out[0] > 0.85f) && (Acc_static_calibration_out[0] < 1.15f)) &&
  288. ((Acc_static_calibration_out[1] > 0.85f) && (Acc_static_calibration_out[1] < 1.15f)) &&
  289. ((Acc_static_calibration_out[2] > 0.85f) && (Acc_static_calibration_out[2] < 1.15f))){
  290. // 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]);
  291. Mahony_PRINT("ImuCal_state ImuCal_finish");
  292. temp = 0;
  293. ImuCal_state = ImuCal_finish;
  294. for(int a = 0; a < 6; a++){
  295. mBackup.cal[a] = Acc_static_calibration_out[a];
  296. }
  297. }
  298. else{
  299. ImuCal_state = ImuCal_quiet;
  300. }
  301. overtime = 0;
  302. }
  303. }
  304. break;
  305. // case ImuCal_finish:{//已经校准完状态
  306. // Mahony_PRINT("ImuCal_state ImuCal_init");
  307. // ImuCal_state = 0;
  308. // }
  309. // break;
  310. // case ImuCal_error:{//校准过程中断退出状态
  311. // Mahony_PRINT("ImuCal_state ImuCal_init");
  312. // ImuCal_state = 0;
  313. // Mahony_PRINT("ImuCal_state ImuCal_init");
  314. // }
  315. // break;
  316. // case ImuCal_quiet:{//校准过程中断退出状态
  317. // ImuCal_state = 0;
  318. // }
  319. // break;
  320. }
  321. return ImuCal_state;
  322. }
  323. void Mahony_imu_lbs(short* Acc_in, short* Gyr_in, short* Mag_in, float* Acc, float* Gyr, float* Mag)
  324. {
  325. float ACC_LBS = 32768.0f / 16.0f;
  326. float GYR_LBS = 32768.0f / 2000.0f;
  327. Acc[0] = Acc_in[0] / ACC_LBS;
  328. Acc[1] = Acc_in[1] / ACC_LBS;
  329. Acc[2] = Acc_in[2] / ACC_LBS;
  330. Gyr[0] = Gyr_in[0] / GYR_LBS;
  331. Gyr[1] = Gyr_in[1] / GYR_LBS;
  332. Gyr[2] = Gyr_in[2] / GYR_LBS;
  333. Mag[0] = Mag_in[0] / 1.0f;
  334. Mag[1] = Mag_in[1] / 1.0f;
  335. Mag[2] = Mag_in[2] / 1.0f;
  336. }
  337. static float acc[3], gyr[3], mag[3];
  338. void ImuCalibration_pcs(short* Acc, short* Gyr, short* Mag)
  339. {
  340. Mahony_imu_lbs(Acc, Gyr, Mag, acc, gyr, mag); //转换IMU数据量程,加速度单位转换为G,陀螺仪单位转换为度每秒,磁力计不需要转换单位,后面会做归一化处理
  341. Acc_static_calibration(acc, NULL, gyr);
  342. }
  343. uint8_t ImuCalibration_GetState(void)
  344. {
  345. return ImuCal_state;
  346. }
  347. void ImuCalibration_SetState(uint8_t _state)
  348. {
  349. ImuCal_state = _state;
  350. }