test_code / Mbed OS test_icm20948
Committer:
eric11fr
Date:
Fri Mar 19 21:59:25 2021 +0000
Revision:
0:efb1550773f1
Child:
1:8459e28d77a1
to

Who changed what in which revision?

UserRevisionLine numberNew contents of line
eric11fr 0:efb1550773f1 1 /* ICM20948 Basic Example Code
eric11fr 0:efb1550773f1 2 by: Kris Winer
eric11fr 0:efb1550773f1 3 date: April 1, 2014
eric11fr 0:efb1550773f1 4 license: Beerware - Use this code however you'd like. If you
eric11fr 0:efb1550773f1 5 find it useful you can buy me a beer some time.
eric11fr 0:efb1550773f1 6 Modified by Brent Wilkins July 19, 2016
eric11fr 0:efb1550773f1 7 Demonstrate basic ICM20948 functionality including parameterizing the register
eric11fr 0:efb1550773f1 8 addresses, initializing the sensor, getting properly scaled accelerometer,
eric11fr 0:efb1550773f1 9 gyroscope, and magnetometer data out. Added display functions to allow display
eric11fr 0:efb1550773f1 10 to on breadboard monitor. Addition of 9 DoF sensor fusion using open source
eric11fr 0:efb1550773f1 11 Madgwick and Mahony filter algorithms. Sketch runs on the 3.3 V 8 MHz Pro Mini
eric11fr 0:efb1550773f1 12 and the Teensy 3.1.
eric11fr 0:efb1550773f1 13 SDA and SCL should have external pull-up resistors (to 3.3V).
eric11fr 0:efb1550773f1 14 10k resistors are on the EMSENSR-9250 breakout board.
eric11fr 0:efb1550773f1 15 Hardware setup:
eric11fr 0:efb1550773f1 16 ICM20948 Breakout --------- Arduino
eric11fr 0:efb1550773f1 17 VDD ---------------------- 3.3V
eric11fr 0:efb1550773f1 18 VDDI --------------------- 3.3V
eric11fr 0:efb1550773f1 19 SDA ----------------------- A4
eric11fr 0:efb1550773f1 20 SCL ----------------------- A5
eric11fr 0:efb1550773f1 21 GND ---------------------- GND
eric11fr 0:efb1550773f1 22 */
eric11fr 0:efb1550773f1 23
eric11fr 0:efb1550773f1 24 #include "AHRSAlgorithms.h"
eric11fr 0:efb1550773f1 25 #include "ICM20948.h"
eric11fr 0:efb1550773f1 26
eric11fr 0:efb1550773f1 27 #define AHRS false // Set to false for basic data read
eric11fr 0:efb1550773f1 28 #define SerialDebug true // Set to true to get Serial output for debugging
eric11fr 0:efb1550773f1 29
eric11fr 0:efb1550773f1 30
eric11fr 0:efb1550773f1 31 ICM20948 myIMU;
eric11fr 0:efb1550773f1 32
eric11fr 0:efb1550773f1 33 void setup()
eric11fr 0:efb1550773f1 34 {
eric11fr 0:efb1550773f1 35 Wire.begin();
eric11fr 0:efb1550773f1 36 // TWBR = 12; // 400 kbit/sec I2C speed
eric11fr 0:efb1550773f1 37 Serial.begin(115200);
eric11fr 0:efb1550773f1 38 while(!Serial) delay(10);
eric11fr 0:efb1550773f1 39
eric11fr 0:efb1550773f1 40 pinMode(myLed, OUTPUT);
eric11fr 0:efb1550773f1 41 digitalWrite(myLed, HIGH);
eric11fr 0:efb1550773f1 42
eric11fr 0:efb1550773f1 43 // Reset ICM20948
eric11fr 0:efb1550773f1 44 myIMU.writeByte(ICM20948_ADDRESS, PWR_MGMT_1, READ_FLAG);
eric11fr 0:efb1550773f1 45 delay(100);
eric11fr 0:efb1550773f1 46 myIMU.writeByte(ICM20948_ADDRESS, PWR_MGMT_1, 0x01);
eric11fr 0:efb1550773f1 47 delay(100);
eric11fr 0:efb1550773f1 48
eric11fr 0:efb1550773f1 49 // Read the WHO_AM_I register, this is a good test of communication
eric11fr 0:efb1550773f1 50 byte c = myIMU.readByte(ICM20948_ADDRESS, WHO_AM_I_ICM20948);
eric11fr 0:efb1550773f1 51 Serial.print(F("ICM20948 I AM 0x"));
eric11fr 0:efb1550773f1 52 Serial.print(c, HEX);
eric11fr 0:efb1550773f1 53 Serial.print(F(" I should be 0x"));
eric11fr 0:efb1550773f1 54 Serial.println(0xEA, HEX);
eric11fr 0:efb1550773f1 55
eric11fr 0:efb1550773f1 56 if (c == 0xEA) // WHO_AM_I should always be 0x71
eric11fr 0:efb1550773f1 57 {
eric11fr 0:efb1550773f1 58 Serial.println(F("ICM20948 is online..."));
eric11fr 0:efb1550773f1 59
eric11fr 0:efb1550773f1 60 // Start by performing self test and reporting values
eric11fr 0:efb1550773f1 61 myIMU.ICM20948SelfTest(myIMU.selfTest);
eric11fr 0:efb1550773f1 62 Serial.print(F("x-axis self test: acceleration trim within : "));
eric11fr 0:efb1550773f1 63 Serial.print(myIMU.selfTest[0],1); Serial.println("% of factory value");
eric11fr 0:efb1550773f1 64 Serial.print(F("y-axis self test: acceleration trim within : "));
eric11fr 0:efb1550773f1 65 Serial.print(myIMU.selfTest[1],1); Serial.println("% of factory value");
eric11fr 0:efb1550773f1 66 Serial.print(F("z-axis self test: acceleration trim within : "));
eric11fr 0:efb1550773f1 67 Serial.print(myIMU.selfTest[2],1); Serial.println("% of factory value");
eric11fr 0:efb1550773f1 68 Serial.print(F("x-axis self test: gyration trim within : "));
eric11fr 0:efb1550773f1 69 Serial.print(myIMU.selfTest[3],1); Serial.println("% of factory value");
eric11fr 0:efb1550773f1 70 Serial.print(F("y-axis self test: gyration trim within : "));
eric11fr 0:efb1550773f1 71 Serial.print(myIMU.selfTest[4],1); Serial.println("% of factory value");
eric11fr 0:efb1550773f1 72 Serial.print(F("z-axis self test: gyration trim within : "));
eric11fr 0:efb1550773f1 73 Serial.print(myIMU.selfTest[5],1); Serial.println("% of factory value");
eric11fr 0:efb1550773f1 74
eric11fr 0:efb1550773f1 75 // Calibrate gyro and accelerometers, load biases in bias registers
eric11fr 0:efb1550773f1 76 myIMU.calibrateICM20948(myIMU.gyroBias, myIMU.accelBias);
eric11fr 0:efb1550773f1 77
eric11fr 0:efb1550773f1 78 myIMU.initICM20948();
eric11fr 0:efb1550773f1 79 // Initialize device for active mode read of acclerometer, gyroscope, and
eric11fr 0:efb1550773f1 80 // temperature
eric11fr 0:efb1550773f1 81 Serial.println("ICM20948 initialized for active data mode....");
eric11fr 0:efb1550773f1 82
eric11fr 0:efb1550773f1 83 // Read the WHO_AM_I register of the magnetometer, this is a good test of
eric11fr 0:efb1550773f1 84 // communication
eric11fr 0:efb1550773f1 85 byte d = myIMU.readByte(AK09916_ADDRESS, WHO_AM_I_AK09916);
eric11fr 0:efb1550773f1 86 Serial.print("AK8963 ");
eric11fr 0:efb1550773f1 87 Serial.print("I AM 0x");
eric11fr 0:efb1550773f1 88 Serial.print(d, HEX);
eric11fr 0:efb1550773f1 89 Serial.print(" I should be 0x");
eric11fr 0:efb1550773f1 90 Serial.println(0x09, HEX);
eric11fr 0:efb1550773f1 91
eric11fr 0:efb1550773f1 92 if (d != 0x09)
eric11fr 0:efb1550773f1 93 {
eric11fr 0:efb1550773f1 94 // Communication failed, stop here
eric11fr 0:efb1550773f1 95 Serial.println(F("Communication with magnetometer failed, abort!"));
eric11fr 0:efb1550773f1 96 Serial.flush();
eric11fr 0:efb1550773f1 97 abort();
eric11fr 0:efb1550773f1 98 }
eric11fr 0:efb1550773f1 99
eric11fr 0:efb1550773f1 100 // Get magnetometer calibration from AK8963 ROM
eric11fr 0:efb1550773f1 101 myIMU.initAK09916();
eric11fr 0:efb1550773f1 102 // Initialize device for active mode read of magnetometer
eric11fr 0:efb1550773f1 103 Serial.println("AK09916 initialized for active data mode....");
eric11fr 0:efb1550773f1 104
eric11fr 0:efb1550773f1 105 /*
eric11fr 0:efb1550773f1 106 if (SerialDebug)
eric11fr 0:efb1550773f1 107 {
eric11fr 0:efb1550773f1 108 // Serial.println("Calibration values: ");
eric11fr 0:efb1550773f1 109 Serial.print("X-Axis factory sensitivity adjustment value ");
eric11fr 0:efb1550773f1 110 Serial.println(myIMU.factoryMagCalibration[0], 2);
eric11fr 0:efb1550773f1 111 Serial.print("Y-Axis factory sensitivity adjustment value ");
eric11fr 0:efb1550773f1 112 Serial.println(myIMU.factoryMagCalibration[1], 2);
eric11fr 0:efb1550773f1 113 Serial.print("Z-Axis factory sensitivity adjustment value ");
eric11fr 0:efb1550773f1 114 Serial.println(myIMU.factoryMagCalibration[2], 2);
eric11fr 0:efb1550773f1 115 }
eric11fr 0:efb1550773f1 116 */
eric11fr 0:efb1550773f1 117
eric11fr 0:efb1550773f1 118 // Get sensor resolutions, only need to do this once
eric11fr 0:efb1550773f1 119 myIMU.getAres();
eric11fr 0:efb1550773f1 120 myIMU.getGres();
eric11fr 0:efb1550773f1 121 myIMU.getMres();
eric11fr 0:efb1550773f1 122
eric11fr 0:efb1550773f1 123 // The next call delays for 4 seconds, and then records about 15 seconds of
eric11fr 0:efb1550773f1 124 // data to calculate bias and scale.
eric11fr 0:efb1550773f1 125 myIMU.magCalICM20948(myIMU.magBias, myIMU.magScale);
eric11fr 0:efb1550773f1 126 Serial.println("AK09916 mag biases (mG)");
eric11fr 0:efb1550773f1 127 Serial.println(myIMU.magBias[0]);
eric11fr 0:efb1550773f1 128 Serial.println(myIMU.magBias[1]);
eric11fr 0:efb1550773f1 129 Serial.println(myIMU.magBias[2]);
eric11fr 0:efb1550773f1 130
eric11fr 0:efb1550773f1 131 Serial.println("AK09916 mag scale (mG)");
eric11fr 0:efb1550773f1 132 Serial.println(myIMU.magScale[0]);
eric11fr 0:efb1550773f1 133 Serial.println(myIMU.magScale[1]);
eric11fr 0:efb1550773f1 134 Serial.println(myIMU.magScale[2]);
eric11fr 0:efb1550773f1 135 delay(2000); // Add delay to see results before serial spew of data
eric11fr 0:efb1550773f1 136 } // if (c == 0x71)
eric11fr 0:efb1550773f1 137 else
eric11fr 0:efb1550773f1 138 {
eric11fr 0:efb1550773f1 139 Serial.print("Could not connect to ICM20948: 0x");
eric11fr 0:efb1550773f1 140 Serial.println(c, HEX);
eric11fr 0:efb1550773f1 141
eric11fr 0:efb1550773f1 142 // Communication failed, stop here
eric11fr 0:efb1550773f1 143 Serial.println(F("Communication failed, abort!"));
eric11fr 0:efb1550773f1 144 Serial.flush();
eric11fr 0:efb1550773f1 145 abort();
eric11fr 0:efb1550773f1 146 }
eric11fr 0:efb1550773f1 147 }
eric11fr 0:efb1550773f1 148
eric11fr 0:efb1550773f1 149 void loop()
eric11fr 0:efb1550773f1 150 {
eric11fr 0:efb1550773f1 151 // If intPin goes high, all data registers have new data
eric11fr 0:efb1550773f1 152 // On interrupt, check if data ready interrupt
eric11fr 0:efb1550773f1 153 if (myIMU.readByte(ICM20948_ADDRESS, INT_STATUS_1) & 0x01)
eric11fr 0:efb1550773f1 154 {
eric11fr 0:efb1550773f1 155 myIMU.readAccelData(myIMU.accelCount); // Read the x/y/z adc values
eric11fr 0:efb1550773f1 156
eric11fr 0:efb1550773f1 157 // Now we'll calculate the accleration value into actual g's
eric11fr 0:efb1550773f1 158 // This depends on scale being set
eric11fr 0:efb1550773f1 159 myIMU.ax = (float)myIMU.accelCount[0] * myIMU.aRes; // - myIMU.accelBias[0];
eric11fr 0:efb1550773f1 160 myIMU.ay = (float)myIMU.accelCount[1] * myIMU.aRes; // - myIMU.accelBias[1];
eric11fr 0:efb1550773f1 161 myIMU.az = (float)myIMU.accelCount[2] * myIMU.aRes; // - myIMU.accelBias[2];
eric11fr 0:efb1550773f1 162
eric11fr 0:efb1550773f1 163 myIMU.readGyroData(myIMU.gyroCount); // Read the x/y/z adc values
eric11fr 0:efb1550773f1 164
eric11fr 0:efb1550773f1 165 // Calculate the gyro value into actual degrees per second
eric11fr 0:efb1550773f1 166 // This depends on scale being set
eric11fr 0:efb1550773f1 167 myIMU.gx = (float)myIMU.gyroCount[0] * myIMU.gRes;
eric11fr 0:efb1550773f1 168 myIMU.gy = (float)myIMU.gyroCount[1] * myIMU.gRes;
eric11fr 0:efb1550773f1 169 myIMU.gz = (float)myIMU.gyroCount[2] * myIMU.gRes;
eric11fr 0:efb1550773f1 170
eric11fr 0:efb1550773f1 171 myIMU.readMagData(myIMU.magCount); // Read the x/y/z adc values
eric11fr 0:efb1550773f1 172
eric11fr 0:efb1550773f1 173 // Calculate the magnetometer values in milliGauss
eric11fr 0:efb1550773f1 174 // Include factory calibration per data sheet and user environmental
eric11fr 0:efb1550773f1 175 // corrections
eric11fr 0:efb1550773f1 176 // Get actual magnetometer value, this depends on scale being set
eric11fr 0:efb1550773f1 177 myIMU.mx = (float)myIMU.magCount[0] * myIMU.mRes - myIMU.magBias[0];
eric11fr 0:efb1550773f1 178 myIMU.my = (float)myIMU.magCount[1] * myIMU.mRes - myIMU.magBias[1];
eric11fr 0:efb1550773f1 179 myIMU.mz = (float)myIMU.magCount[2] * myIMU.mRes - myIMU.magBias[2];
eric11fr 0:efb1550773f1 180 } // if (readByte(ICM20948_ADDRESS, INT_STATUS) & 0x01)
eric11fr 0:efb1550773f1 181
eric11fr 0:efb1550773f1 182 // Must be called before updating quaternions!
eric11fr 0:efb1550773f1 183 myIMU.updateTime();
eric11fr 0:efb1550773f1 184
eric11fr 0:efb1550773f1 185 // Sensors x (y)-axis of the accelerometer is aligned with the y (x)-axis of
eric11fr 0:efb1550773f1 186 // the magnetometer; the magnetometer z-axis (+ down) is opposite to z-axis
eric11fr 0:efb1550773f1 187 // (+ up) of accelerometer and gyro! We have to make some allowance for this
eric11fr 0:efb1550773f1 188 // orientationmismatch in feeding the output to the quaternion filter. For the
eric11fr 0:efb1550773f1 189 // ICM20948, we have chosen a magnetic rotation that keeps the sensor forward
eric11fr 0:efb1550773f1 190 // along the x-axis just like in the LSM9DS0 sensor. This rotation can be
eric11fr 0:efb1550773f1 191 // modified to allow any convenient orientation convention. This is ok by
eric11fr 0:efb1550773f1 192 // aircraft orientation standards! Pass gyro rate as rad/s
eric11fr 0:efb1550773f1 193 MahonyQuaternionUpdate(myIMU.ax, myIMU.ay, myIMU.az, myIMU.gx * DEG_TO_RAD,
eric11fr 0:efb1550773f1 194 myIMU.gy * DEG_TO_RAD, myIMU.gz * DEG_TO_RAD, myIMU.my,
eric11fr 0:efb1550773f1 195 myIMU.mx, myIMU.mz, myIMU.deltat);
eric11fr 0:efb1550773f1 196
eric11fr 0:efb1550773f1 197 if (!AHRS)
eric11fr 0:efb1550773f1 198 {
eric11fr 0:efb1550773f1 199 myIMU.delt_t = millis() - myIMU.count;
eric11fr 0:efb1550773f1 200 if (myIMU.delt_t > 500)
eric11fr 0:efb1550773f1 201 {
eric11fr 0:efb1550773f1 202 if(SerialDebug)
eric11fr 0:efb1550773f1 203 {
eric11fr 0:efb1550773f1 204 // Print acceleration values in milligs!
eric11fr 0:efb1550773f1 205 Serial.print("X-acceleration: "); Serial.print(1000 * myIMU.ax);
eric11fr 0:efb1550773f1 206 Serial.print(" mg ");
eric11fr 0:efb1550773f1 207 Serial.print("Y-acceleration: "); Serial.print(1000 * myIMU.ay);
eric11fr 0:efb1550773f1 208 Serial.print(" mg ");
eric11fr 0:efb1550773f1 209 Serial.print("Z-acceleration: "); Serial.print(1000 * myIMU.az);
eric11fr 0:efb1550773f1 210 Serial.println(" mg ");
eric11fr 0:efb1550773f1 211
eric11fr 0:efb1550773f1 212 // Print gyro values in degree/sec
eric11fr 0:efb1550773f1 213 Serial.print("X-gyro rate: "); Serial.print(myIMU.gx, 3);
eric11fr 0:efb1550773f1 214 Serial.print(" degrees/sec ");
eric11fr 0:efb1550773f1 215 Serial.print("Y-gyro rate: "); Serial.print(myIMU.gy, 3);
eric11fr 0:efb1550773f1 216 Serial.print(" degrees/sec ");
eric11fr 0:efb1550773f1 217 Serial.print("Z-gyro rate: "); Serial.print(myIMU.gz, 3);
eric11fr 0:efb1550773f1 218 Serial.println(" degrees/sec");
eric11fr 0:efb1550773f1 219
eric11fr 0:efb1550773f1 220 // Print mag values in degree/sec
eric11fr 0:efb1550773f1 221 Serial.print("X-mag field: "); Serial.print(myIMU.mx);
eric11fr 0:efb1550773f1 222 Serial.print(" mG ");
eric11fr 0:efb1550773f1 223 Serial.print("Y-mag field: "); Serial.print(myIMU.my);
eric11fr 0:efb1550773f1 224 Serial.print(" mG ");
eric11fr 0:efb1550773f1 225 Serial.print("Z-mag field: "); Serial.print(myIMU.mz);
eric11fr 0:efb1550773f1 226 Serial.println(" mG");
eric11fr 0:efb1550773f1 227
eric11fr 0:efb1550773f1 228 myIMU.tempCount = myIMU.readTempData(); // Read the adc values
eric11fr 0:efb1550773f1 229 // Temperature in degrees Centigrade
eric11fr 0:efb1550773f1 230 myIMU.temperature = ((float) myIMU.tempCount) / 333.87 + 21.0;
eric11fr 0:efb1550773f1 231 // Print temperature in degrees Centigrade
eric11fr 0:efb1550773f1 232 Serial.print("Temperature is "); Serial.print(myIMU.temperature, 1);
eric11fr 0:efb1550773f1 233 Serial.println(" degrees C");
eric11fr 0:efb1550773f1 234 }
eric11fr 0:efb1550773f1 235
eric11fr 0:efb1550773f1 236 myIMU.count = millis();
eric11fr 0:efb1550773f1 237 digitalWrite(myLed, !digitalRead(myLed)); // toggle led
eric11fr 0:efb1550773f1 238 } // if (myIMU.delt_t > 500)
eric11fr 0:efb1550773f1 239 } // if (!AHRS)
eric11fr 0:efb1550773f1 240 else
eric11fr 0:efb1550773f1 241 {
eric11fr 0:efb1550773f1 242 // Serial print and/or display at 0.5 s rate independent of data rates
eric11fr 0:efb1550773f1 243 myIMU.delt_t = millis() - myIMU.count;
eric11fr 0:efb1550773f1 244
eric11fr 0:efb1550773f1 245 // update LCD once per half-second independent of read rate
eric11fr 0:efb1550773f1 246 if (myIMU.delt_t > 500)
eric11fr 0:efb1550773f1 247 {
eric11fr 0:efb1550773f1 248 if(SerialDebug)
eric11fr 0:efb1550773f1 249 {
eric11fr 0:efb1550773f1 250 Serial.print("ax = "); Serial.print((int)1000 * myIMU.ax);
eric11fr 0:efb1550773f1 251 Serial.print(" ay = "); Serial.print((int)1000 * myIMU.ay);
eric11fr 0:efb1550773f1 252 Serial.print(" az = "); Serial.print((int)1000 * myIMU.az);
eric11fr 0:efb1550773f1 253 Serial.println(" mg");
eric11fr 0:efb1550773f1 254
eric11fr 0:efb1550773f1 255 Serial.print("gx = "); Serial.print(myIMU.gx, 2);
eric11fr 0:efb1550773f1 256 Serial.print(" gy = "); Serial.print(myIMU.gy, 2);
eric11fr 0:efb1550773f1 257 Serial.print(" gz = "); Serial.print(myIMU.gz, 2);
eric11fr 0:efb1550773f1 258 Serial.println(" deg/s");
eric11fr 0:efb1550773f1 259
eric11fr 0:efb1550773f1 260 Serial.print("mx = "); Serial.print((int)myIMU.mx);
eric11fr 0:efb1550773f1 261 Serial.print(" my = "); Serial.print((int)myIMU.my);
eric11fr 0:efb1550773f1 262 Serial.print(" mz = "); Serial.print((int)myIMU.mz);
eric11fr 0:efb1550773f1 263 Serial.println(" mG");
eric11fr 0:efb1550773f1 264
eric11fr 0:efb1550773f1 265 Serial.print("q0 = "); Serial.print(*getQ());
eric11fr 0:efb1550773f1 266 Serial.print(" qx = "); Serial.print(*(getQ() + 1));
eric11fr 0:efb1550773f1 267 Serial.print(" qy = "); Serial.print(*(getQ() + 2));
eric11fr 0:efb1550773f1 268 Serial.print(" qz = "); Serial.println(*(getQ() + 3));
eric11fr 0:efb1550773f1 269 }
eric11fr 0:efb1550773f1 270
eric11fr 0:efb1550773f1 271 // Define output variables from updated quaternion---these are Tait-Bryan
eric11fr 0:efb1550773f1 272 // angles, commonly used in aircraft orientation. In this coordinate system,
eric11fr 0:efb1550773f1 273 // the positive z-axis is down toward Earth. Yaw is the angle between Sensor
eric11fr 0:efb1550773f1 274 // x-axis and Earth magnetic North (or true North if corrected for local
eric11fr 0:efb1550773f1 275 // declination, looking down on the sensor positive yaw is counterclockwise.
eric11fr 0:efb1550773f1 276 // Pitch is angle between sensor x-axis and Earth ground plane, toward the
eric11fr 0:efb1550773f1 277 // Earth is positive, up toward the sky is negative. Roll is angle between
eric11fr 0:efb1550773f1 278 // sensor y-axis and Earth ground plane, y-axis up is positive roll. These
eric11fr 0:efb1550773f1 279 // arise from the definition of the homogeneous rotation matrix constructed
eric11fr 0:efb1550773f1 280 // from quaternions. Tait-Bryan angles as well as Euler angles are
eric11fr 0:efb1550773f1 281 // non-commutative; that is, the get the correct orientation the rotations
eric11fr 0:efb1550773f1 282 // must be applied in the correct order which for this configuration is yaw,
eric11fr 0:efb1550773f1 283 // pitch, and then roll.
eric11fr 0:efb1550773f1 284 // For more see
eric11fr 0:efb1550773f1 285 // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
eric11fr 0:efb1550773f1 286 // which has additional links.
eric11fr 0:efb1550773f1 287 myIMU.yaw = atan2(2.0f * (*(getQ()+1) * *(getQ()+2) + *getQ()
eric11fr 0:efb1550773f1 288 * *(getQ()+3)), *getQ() * *getQ() + *(getQ()+1)
eric11fr 0:efb1550773f1 289 * *(getQ()+1) - *(getQ()+2) * *(getQ()+2) - *(getQ()+3)
eric11fr 0:efb1550773f1 290 * *(getQ()+3));
eric11fr 0:efb1550773f1 291 myIMU.pitch = -asin(2.0f * (*(getQ()+1) * *(getQ()+3) - *getQ()
eric11fr 0:efb1550773f1 292 * *(getQ()+2)));
eric11fr 0:efb1550773f1 293 myIMU.roll = atan2(2.0f * (*getQ() * *(getQ()+1) + *(getQ()+2)
eric11fr 0:efb1550773f1 294 * *(getQ()+3)), *getQ() * *getQ() - *(getQ()+1)
eric11fr 0:efb1550773f1 295 * *(getQ()+1) - *(getQ()+2) * *(getQ()+2) + *(getQ()+3)
eric11fr 0:efb1550773f1 296 * *(getQ()+3));
eric11fr 0:efb1550773f1 297 myIMU.pitch *= RAD_TO_DEG;
eric11fr 0:efb1550773f1 298 myIMU.yaw *= RAD_TO_DEG;
eric11fr 0:efb1550773f1 299
eric11fr 0:efb1550773f1 300 // Declination of SparkFun Electronics (40°05'26.6"N 105°11'05.9"W) is
eric11fr 0:efb1550773f1 301 // 8° 30' E ± 0° 21' (or 8.5°) on 2016-07-19
eric11fr 0:efb1550773f1 302 // - http://www.ngdc.noaa.gov/geomag-web/#declination
eric11fr 0:efb1550773f1 303 myIMU.yaw -= 8.5;
eric11fr 0:efb1550773f1 304 myIMU.roll *= RAD_TO_DEG;
eric11fr 0:efb1550773f1 305
eric11fr 0:efb1550773f1 306 if(SerialDebug)
eric11fr 0:efb1550773f1 307 {
eric11fr 0:efb1550773f1 308 Serial.print("Yaw, Pitch, Roll: ");
eric11fr 0:efb1550773f1 309 Serial.print(myIMU.yaw, 2);
eric11fr 0:efb1550773f1 310 Serial.print(", ");
eric11fr 0:efb1550773f1 311 Serial.print(myIMU.pitch, 2);
eric11fr 0:efb1550773f1 312 Serial.print(", ");
eric11fr 0:efb1550773f1 313 Serial.println(myIMU.roll, 2);
eric11fr 0:efb1550773f1 314
eric11fr 0:efb1550773f1 315 Serial.print("rate = ");
eric11fr 0:efb1550773f1 316 Serial.print((float)myIMU.sumCount / myIMU.sum, 2);
eric11fr 0:efb1550773f1 317 Serial.println(" Hz");
eric11fr 0:efb1550773f1 318 }
eric11fr 0:efb1550773f1 319
eric11fr 0:efb1550773f1 320 myIMU.count = millis();
eric11fr 0:efb1550773f1 321 myIMU.sumCount = 0;
eric11fr 0:efb1550773f1 322 myIMU.sum = 0;
eric11fr 0:efb1550773f1 323 } // if (myIMU.delt_t > 500)
eric11fr 0:efb1550773f1 324 } // if (AHRS)
eric11fr 0:efb1550773f1 325 }