/Silverware/src/imu.c

https://github.com/silver13/Eachine-E011 · C · 213 lines · 130 code · 65 blank · 18 comment · 18 complexity · 42284c19fefbd96b99c0b0c39683e982 MD5 · raw file

  1. // library headers
  2. #include <stdbool.h>
  3. #include <inttypes.h>
  4. //#define _USE_MATH_DEFINES
  5. #include <math.h>
  6. #include "drv_time.h"
  7. #include "util.h"
  8. #include "sixaxis.h"
  9. #include "config.h"
  10. #include <stdlib.h>
  11. #ifdef DEBUG
  12. #include "debug.h"
  13. extern debug_type debug;
  14. #endif
  15. #define ACC_1G 1.0f
  16. // disable drift correction ( for testing)
  17. #define DISABLE_ACC 0
  18. // filter time in seconds
  19. // time to correct gyro readings using the accelerometer
  20. // 1-4 are generally good
  21. #define FILTERTIME 2.0
  22. // accel magnitude limits for drift correction
  23. #define ACC_MIN 0.7f
  24. #define ACC_MAX 1.3f
  25. float GEstG[3] = { 0, 0, ACC_1G };
  26. float attitude[3];
  27. extern float gyro[3];
  28. extern float accel[3];
  29. extern float accelcal[3];
  30. void imu_init(void)
  31. {
  32. // init the gravity vector with accel values
  33. for (int xx = 0; xx < 100; xx++)
  34. {
  35. sixaxis_read();
  36. for (int x = 0; x < 3; x++)
  37. {
  38. lpf(&GEstG[x], accel[x]* ( 1/ 2048.0f) , 0.85);
  39. }
  40. delay(1000);
  41. }
  42. }
  43. // from http://en.wikipedia.org/wiki/Fast_inverse_square_root
  44. // originally from quake3 code
  45. float Q_rsqrt( float number )
  46. {
  47. long i;
  48. float x2, y;
  49. const float threehalfs = 1.5F;
  50. x2 = number * 0.5F;
  51. y = number;
  52. i = * ( long * ) &y;
  53. i = 0x5f3759df - ( i >> 1 );
  54. y = * ( float * ) &i;
  55. y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
  56. y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
  57. // y = y * ( threehalfs - ( x2 * y * y ) ); // 3nd iteration, this can be removed
  58. return y;
  59. }
  60. void vectorcopy(float *vector1, float *vector2);
  61. float atan2approx(float y, float x);
  62. float calcmagnitude(float vector[3])
  63. {
  64. float accmag = 0;
  65. for (uint8_t axis = 0; axis < 3; axis++)
  66. {
  67. accmag += vector[axis] * vector[axis];
  68. }
  69. accmag = 1.0f/Q_rsqrt(accmag);
  70. return accmag;
  71. }
  72. void vectorcopy(float *vector1, float *vector2)
  73. {
  74. for (int axis = 0; axis < 3; axis++)
  75. {
  76. vector1[axis] = vector2[axis];
  77. }
  78. }
  79. extern float looptime;
  80. void imu_calc(void)
  81. {
  82. // remove bias
  83. accel[0] = accel[0] - accelcal[0];
  84. accel[1] = accel[1] - accelcal[1];
  85. // reduce to accel in G
  86. for (int i = 0; i < 3; i++)
  87. {
  88. accel[i] *= ( 1/ 2048.0f);
  89. }
  90. float deltaGyroAngle[3];
  91. for ( int i = 0 ; i < 3 ; i++)
  92. {
  93. deltaGyroAngle[i] = (gyro[i]) * looptime;
  94. }
  95. GEstG[2] = GEstG[2] - (deltaGyroAngle[0]) * GEstG[0];
  96. GEstG[0] = (deltaGyroAngle[0]) * GEstG[2] + GEstG[0];
  97. GEstG[1] = GEstG[1] + (deltaGyroAngle[1]) * GEstG[2];
  98. GEstG[2] = -(deltaGyroAngle[1]) * GEstG[1] + GEstG[2];
  99. GEstG[0] = GEstG[0] - (deltaGyroAngle[2]) * GEstG[1];
  100. GEstG[1] = (deltaGyroAngle[2]) * GEstG[0] + GEstG[1];
  101. // calc acc mag
  102. float accmag;
  103. accmag = calcmagnitude(&accel[0]);
  104. if ((accmag > ACC_MIN * ACC_1G) && (accmag < ACC_MAX * ACC_1G) && !DISABLE_ACC)
  105. {
  106. // normalize acc
  107. for (int axis = 0; axis < 3; axis++)
  108. {
  109. accel[axis] = accel[axis] * ( ACC_1G / accmag);
  110. }
  111. float filtcoeff = lpfcalc_hz( looptime, 1.0f/(float)FILTERTIME);
  112. for (int x = 0; x < 3; x++)
  113. {
  114. lpf(&GEstG[x], accel[x], filtcoeff);
  115. }
  116. }
  117. // vectorcopy(&GEstG[0], &EstG[0]);
  118. #ifdef DEBUG
  119. attitude[0] = atan2approx(EstG[0], EstG[2]) ;
  120. attitude[1] = atan2approx(EstG[1], EstG[2]) ;
  121. #endif
  122. }
  123. #define M_PI 3.14159265358979323846 /* pi */
  124. #define OCTANTIFY(_x, _y, _o) do { \
  125. float _t; \
  126. _o= 0; \
  127. if(_y< 0) { _x= -_x; _y= -_y; _o += 4; } \
  128. if(_x<= 0) { _t= _x; _x= _y; _y= -_t; _o += 2; } \
  129. if(_x<=_y) { _t= _y-_x; _x= _x+_y; _y= _t; _o += 1; } \
  130. } while(0);
  131. // +-0.09 deg error
  132. float atan2approx(float y, float x)
  133. {
  134. if (x == 0)
  135. x = 123e-15f;
  136. float phi = 0;
  137. float dphi;
  138. float t;
  139. OCTANTIFY(x, y, phi);
  140. t = (y / x);
  141. // atan function for 0 - 1 interval
  142. dphi = t*( ( M_PI/4 + 0.2447f ) + t *( ( -0.2447f + 0.0663f ) + t*( - 0.0663f)) );
  143. phi *= M_PI / 4;
  144. dphi = phi + dphi;
  145. if (dphi > (float) M_PI)
  146. dphi -= 2 * M_PI;
  147. return RADTODEG * dphi;
  148. }