PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NXPMotionSense.h 7.5KB

3 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #ifndef _NXP_Motion_Sensors_
  2. #define _NXP_Motion_Sensors_
  3. #include <Arduino.h>
  4. #include <Wire.h>
  5. #include <EEPROM.h>
  6. // TODO: move these inside class namespace
  7. #define G_PER_COUNT 0.0001220703125f // = 1/8192
  8. #define DEG_PER_SEC_PER_COUNT 0.0625f // = 1/16
  9. #define UT_PER_COUNT 0.1f
  10. class NXPMotionSense {
  11. public:
  12. bool begin();
  13. bool available() {
  14. update();
  15. if (newdata) return true;
  16. return false;
  17. }
  18. void readMotionSensor(int& ax, int& ay, int& az, int& gx, int& gy, int& gz) {
  19. if (!newdata) update();
  20. newdata = 0;
  21. ax = accel_mag_raw[0];
  22. ay = accel_mag_raw[1];
  23. az = accel_mag_raw[2];
  24. gx = gyro_raw[0];
  25. gy = gyro_raw[1];
  26. gz = gyro_raw[2];
  27. }
  28. void readMotionSensor(int& ax, int& ay, int& az, int& gx, int& gy, int& gz, int& mx, int& my, int& mz) {
  29. if (!newdata) update();
  30. newdata = 0;
  31. ax = accel_mag_raw[0];
  32. ay = accel_mag_raw[1];
  33. az = accel_mag_raw[2];
  34. mx = accel_mag_raw[3];
  35. my = accel_mag_raw[4];
  36. mz = accel_mag_raw[5];
  37. gx = gyro_raw[0];
  38. gy = gyro_raw[1];
  39. gz = gyro_raw[2];
  40. }
  41. void readMotionSensor(float& ax, float& ay, float& az, float& gx, float& gy, float& gz) {
  42. if (!newdata) update();
  43. newdata = 0;
  44. ax = (float)accel_mag_raw[0] * G_PER_COUNT;
  45. ay = (float)accel_mag_raw[1] * G_PER_COUNT;
  46. az = (float)accel_mag_raw[2] * G_PER_COUNT;
  47. gx = (float)gyro_raw[0] * DEG_PER_SEC_PER_COUNT;
  48. gy = (float)gyro_raw[1] * DEG_PER_SEC_PER_COUNT;
  49. gz = (float)gyro_raw[2] * DEG_PER_SEC_PER_COUNT;
  50. }
  51. void readMotionSensor(float& ax, float& ay, float& az, float& gx, float& gy, float& gz, float& mx, float& my, float& mz) {
  52. if (!newdata) update();
  53. newdata = 0;
  54. ax = (float)accel_mag_raw[0] * G_PER_COUNT - cal[0];
  55. ay = (float)accel_mag_raw[1] * G_PER_COUNT - cal[1];
  56. az = (float)accel_mag_raw[2] * G_PER_COUNT - cal[2];
  57. gx = (float)gyro_raw[0] * DEG_PER_SEC_PER_COUNT - cal[3];
  58. gy = (float)gyro_raw[1] * DEG_PER_SEC_PER_COUNT - cal[4];
  59. gz = (float)gyro_raw[2] * DEG_PER_SEC_PER_COUNT - cal[5];
  60. float x = (float)accel_mag_raw[3] * UT_PER_COUNT - cal[6];
  61. float y = (float)accel_mag_raw[4] * UT_PER_COUNT - cal[7];
  62. float z = (float)accel_mag_raw[5] * UT_PER_COUNT - cal[8];
  63. mx = x * cal[10] + y * cal[13] + z * cal[14];
  64. my = x * cal[13] + y * cal[11] + z * cal[15];
  65. mz = x * cal[14] + y * cal[15] + z * cal[12];
  66. }
  67. bool writeCalibration(const void *data);
  68. void getCalibration(float *offsets, float *softiron=NULL, float *fieldstrength=NULL) {
  69. if (offsets != NULL) {
  70. memcpy(offsets, cal, 36);
  71. }
  72. if (softiron != NULL) {
  73. *softiron++ = cal[10];
  74. *softiron++ = cal[13];
  75. *softiron++ = cal[14];
  76. *softiron++ = cal[13];
  77. *softiron++ = cal[11];
  78. *softiron++ = cal[15];
  79. *softiron++ = cal[14];
  80. *softiron++ = cal[15];
  81. *softiron++ = cal[12];
  82. }
  83. if (fieldstrength != NULL) *fieldstrength = cal[9];
  84. }
  85. private:
  86. void update();
  87. bool FXOS8700_begin();
  88. bool FXAS21002_begin();
  89. bool MPL3115_begin();
  90. bool FXOS8700_read(int16_t *data);
  91. bool FXAS21002_read(int16_t *data);
  92. bool MPL3115_read(int32_t *altitude, int16_t *temperature);
  93. float cal[16]; // 0-8=offsets, 9=field strength, 10-15=soft iron map
  94. int16_t accel_mag_raw[6];
  95. int16_t gyro_raw[3];
  96. int16_t temperature_raw;
  97. uint8_t newdata;
  98. };
  99. class NXPSensorFusion {
  100. public:
  101. void begin(float sampleRate=100.0f);
  102. void update(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);
  103. // TODO: these aren't the same ranges as Madgwick & Mahony... or are they??
  104. float getRoll() { return PhiPl; }
  105. float getPitch() { return ThePl; }
  106. float getYaw() { return PsiPl; }
  107. typedef struct {
  108. float q0; // w
  109. float q1; // x
  110. float q2; // y
  111. float q3; // z
  112. } Quaternion_t;
  113. // These are Madgwick & Mahony - extrinsic rotation reference (wrong!)
  114. //float getPitch() {return atan2f(2.0f * qPl.q2 * qPl.q3 - 2.0f * qPl.q0 * qPl.q1, 2.0f * qPl.q0 * qPl.q0 + 2.0f * qPl.q3 * qPl.q3 - 1.0f);};
  115. //float getRoll() {return -1.0f * asinf(2.0f * qPl.q1 * qPl.q3 + 2.0f * qPl.q0 * qPl.q2);};
  116. //float getYaw() {return atan2f(2.0f * qPl.q1 * qPl.q2 - 2.0f * qPl.q0 * qPl.q3, 2.0f * qPl.q0 * qPl.q0 + 2.0f * qPl.q1 * qPl.q1 - 1.0f);};
  117. private:
  118. float PhiPl; // roll (deg)
  119. float ThePl; // pitch (deg)
  120. float PsiPl; // yaw (deg)
  121. float RhoPl; // compass (deg)
  122. float ChiPl; // tilt from vertical (deg)
  123. // orientation matrix, quaternion and rotation vector
  124. float RPl[3][3]; // a posteriori orientation matrix
  125. Quaternion_t qPl; // a posteriori orientation quaternion
  126. float RVecPl[3]; // rotation vector
  127. // angular velocity
  128. float Omega[3]; // angular velocity (deg/s)
  129. // systick timer for benchmarking
  130. int32_t systick; // systick timer;
  131. // end: elements common to all motion state vectors
  132. // elements transmitted over bluetooth in kalman packet
  133. float bPl[3]; // gyro offset (deg/s)
  134. float ThErrPl[3]; // orientation error (deg)
  135. float bErrPl[3]; // gyro offset error (deg/s)
  136. // end elements transmitted in kalman packet
  137. float dErrGlPl[3]; // magnetic disturbance error (uT, global frame)
  138. float dErrSePl[3]; // magnetic disturbance error (uT, sensor frame)
  139. float aErrSePl[3]; // linear acceleration error (g, sensor frame)
  140. float aSeMi[3]; // linear acceleration (g, sensor frame)
  141. float DeltaPl; // inclination angle (deg)
  142. float aSePl[3]; // linear acceleration (g, sensor frame)
  143. float aGlPl[3]; // linear acceleration (g, global frame)
  144. float gErrSeMi[3]; // difference (g, sensor frame) of gravity vector (accel) and gravity vector (gyro)
  145. float mErrSeMi[3]; // difference (uT, sensor frame) of geomagnetic vector (magnetometer) and geomagnetic vector (gyro)
  146. float gSeGyMi[3]; // gravity vector (g, sensor frame) measurement from gyro
  147. float mSeGyMi[3]; // geomagnetic vector (uT, sensor frame) measurement from gyro
  148. float mGl[3]; // geomagnetic vector (uT, global frame)
  149. float QvAA; // accelerometer terms of Qv
  150. float QvMM; // magnetometer terms of Qv
  151. float PPlus12x12[12][12]; // covariance matrix P+
  152. float K12x6[12][6]; // kalman filter gain matrix K
  153. float Qw12x12[12][12]; // covariance matrix Qw
  154. float C6x12[6][12]; // measurement matrix C
  155. float RMi[3][3]; // a priori orientation matrix
  156. Quaternion_t Deltaq; // delta quaternion
  157. Quaternion_t qMi; // a priori orientation quaternion
  158. float casq; // FCA * FCA;
  159. float cdsq; // FCD * FCD;
  160. float Fastdeltat; // sensor sampling interval (s) = 1 / SENSORFS
  161. float deltat; // kalman filter sampling interval (s) = OVERSAMPLE_RATIO / SENSORFS
  162. float deltatsq; // fdeltat * fdeltat
  163. float QwbplusQvG; // FQWB + FQVG
  164. int8_t FirstOrientationLock; // denotes that 9DOF orientation has locked to 6DOF
  165. int8_t resetflag; // flag to request re-initialization on next pass
  166. };
  167. #undef G_PER_COUNT
  168. #undef DEG_PER_SEC_PER_COUNT
  169. #undef UT_PER_COUNT
  170. #endif