Port of http://dev.qu.tu-berlin.de/projects/sf-razor-9dof-ahrs to an mbed, tested with a 9DOF Sensor Stick, SEN-10724

Dependencies:   mbed

Committer:
lpetre
Date:
Tue Dec 27 17:20:06 2011 +0000
Revision:
0:9a72d42c0da3
Child:
1:e27c4c0b71d8

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lpetre 0:9a72d42c0da3 1 /***************************************************************************************************************
lpetre 0:9a72d42c0da3 2 * Razor AHRS Firmware v1.4.0
lpetre 0:9a72d42c0da3 3 * 9 Degree of Measurement Attitude and Heading Reference System
lpetre 0:9a72d42c0da3 4 * for Sparkfun "9DOF Razor IMU" (SEN-10125 and SEN-10736)
lpetre 0:9a72d42c0da3 5 * and "9DOF Sensor Stick" (SEN-10183, 10321 and SEN-10724)
lpetre 0:9a72d42c0da3 6 *
lpetre 0:9a72d42c0da3 7 * Released under GNU GPL (General Public License) v3.0
lpetre 0:9a72d42c0da3 8 * Copyright (C) 2011 Quality & Usability Lab, Deutsche Telekom Laboratories, TU Berlin
lpetre 0:9a72d42c0da3 9 *
lpetre 0:9a72d42c0da3 10 * Infos, updates, bug reports and feedback:
lpetre 0:9a72d42c0da3 11 * http://dev.qu.tu-berlin.de/projects/sf-razor-9dof-ahrs
lpetre 0:9a72d42c0da3 12 *
lpetre 0:9a72d42c0da3 13 *
lpetre 0:9a72d42c0da3 14 * History:
lpetre 0:9a72d42c0da3 15 * * Original code (http://code.google.com/p/sf9domahrs/) by Doug Weibel and Jose Julio,
lpetre 0:9a72d42c0da3 16 * based on ArduIMU v1.5 by Jordi Munoz and William Premerlani, Jose Julio and Doug Weibel. Thank you!
lpetre 0:9a72d42c0da3 17 *
lpetre 0:9a72d42c0da3 18 * * Updated code (http://groups.google.com/group/sf_9dof_ahrs_update) by David Malik (david.zsolt.malik@gmail.com)
lpetre 0:9a72d42c0da3 19 * for new Sparkfun 9DOF Razor hardware (SEN-10125).
lpetre 0:9a72d42c0da3 20 *
lpetre 0:9a72d42c0da3 21 * * Updated and extended by Peter Bartz (peter-bartz@gmx.de):
lpetre 0:9a72d42c0da3 22 * * v1.3.0
lpetre 0:9a72d42c0da3 23 * * Cleaned up, streamlined and restructured most of the code to make it more comprehensible.
lpetre 0:9a72d42c0da3 24 * * Added sensor calibration (improves precision and responsiveness a lot!).
lpetre 0:9a72d42c0da3 25 * * Added binary yaw/pitch/roll output.
lpetre 0:9a72d42c0da3 26 * * Added basic serial command interface to set output modes/calibrate sensors/synch stream/etc.
lpetre 0:9a72d42c0da3 27 * * Added support to synch automatically when using Rovering Networks Bluetooth modules (and compatible).
lpetre 0:9a72d42c0da3 28 * * Wrote new easier to use test program (using Processing).
lpetre 0:9a72d42c0da3 29 * * Added support for new version of "9DOF Razor IMU": SEN-10736.
lpetre 0:9a72d42c0da3 30 * --> The output of this code is not compatible with the older versions!
lpetre 0:9a72d42c0da3 31 * --> A Processing sketch to test the tracker is available.
lpetre 0:9a72d42c0da3 32 * * v1.3.1
lpetre 0:9a72d42c0da3 33 * * Initializing rotation matrix based on start-up sensor readings -> orientation OK right away.
lpetre 0:9a72d42c0da3 34 * * Adjusted gyro low-pass filter and output rate settings.
lpetre 0:9a72d42c0da3 35 * * v1.3.2
lpetre 0:9a72d42c0da3 36 * * Adapted code to work with new Arduino 1.0 (and older versions still).
lpetre 0:9a72d42c0da3 37 * * v1.3.3
lpetre 0:9a72d42c0da3 38 * * Improved synching.
lpetre 0:9a72d42c0da3 39 * * v1.4.0
lpetre 0:9a72d42c0da3 40 * * Added support for SparkFun "9DOF Sensor Stick" (versions SEN-10183, SEN-10321 and SEN-10724).
lpetre 0:9a72d42c0da3 41 *
lpetre 0:9a72d42c0da3 42 * TODOs:
lpetre 0:9a72d42c0da3 43 * * Allow optional use of EEPROM for storing and reading calibration values.
lpetre 0:9a72d42c0da3 44 * * Use self-test and temperature-compensation features of the sensors.
lpetre 0:9a72d42c0da3 45 * * Add binary output of unfused sensor data for all 9 axes.
lpetre 0:9a72d42c0da3 46 ***************************************************************************************************************/
lpetre 0:9a72d42c0da3 47
lpetre 0:9a72d42c0da3 48 /*
lpetre 0:9a72d42c0da3 49 "9DOF Razor IMU" hardware versions: SEN-10125 and SEN-10736
lpetre 0:9a72d42c0da3 50
lpetre 0:9a72d42c0da3 51 ATMega328@3.3V, 8MHz
lpetre 0:9a72d42c0da3 52
lpetre 0:9a72d42c0da3 53 ADXL345 : Accelerometer
lpetre 0:9a72d42c0da3 54 HMC5843 : Magnetometer on SEN-10125
lpetre 0:9a72d42c0da3 55 HMC5883L : Magnetometer on SEN-10736
lpetre 0:9a72d42c0da3 56 ITG-3200 : Gyro
lpetre 0:9a72d42c0da3 57
lpetre 0:9a72d42c0da3 58 Arduino IDE : Select board "Arduino Pro or Pro Mini (3.3v, 8Mhz) w/ATmega328"
lpetre 0:9a72d42c0da3 59 */
lpetre 0:9a72d42c0da3 60
lpetre 0:9a72d42c0da3 61 /*
lpetre 0:9a72d42c0da3 62 "9DOF Sensor Stick" hardware versions: SEN-10183, SEN-10321 and SEN-10724
lpetre 0:9a72d42c0da3 63
lpetre 0:9a72d42c0da3 64 ADXL345 : Accelerometer
lpetre 0:9a72d42c0da3 65 HMC5843 : Magnetometer on SEN-10183 and SEN-10321
lpetre 0:9a72d42c0da3 66 HMC5883L : Magnetometer on SEN-10724
lpetre 0:9a72d42c0da3 67 ITG-3200 : Gyro
lpetre 0:9a72d42c0da3 68 */
lpetre 0:9a72d42c0da3 69
lpetre 0:9a72d42c0da3 70 /*
lpetre 0:9a72d42c0da3 71 Axis definition (differs from definition printed on the board!):
lpetre 0:9a72d42c0da3 72 X axis pointing forward (towards the short edge with the connector holes)
lpetre 0:9a72d42c0da3 73 Y axis pointing to the right
lpetre 0:9a72d42c0da3 74 and Z axis pointing down.
lpetre 0:9a72d42c0da3 75
lpetre 0:9a72d42c0da3 76 Positive yaw : clockwise
lpetre 0:9a72d42c0da3 77 Positive roll : right wing down
lpetre 0:9a72d42c0da3 78 Positive pitch : nose up
lpetre 0:9a72d42c0da3 79
lpetre 0:9a72d42c0da3 80 Transformation order: first yaw then pitch then roll.
lpetre 0:9a72d42c0da3 81 */
lpetre 0:9a72d42c0da3 82
lpetre 0:9a72d42c0da3 83 /*
lpetre 0:9a72d42c0da3 84 Commands that the firmware understands:
lpetre 0:9a72d42c0da3 85
lpetre 0:9a72d42c0da3 86 "#o<param>" - Set output parameter. The available options are:
lpetre 0:9a72d42c0da3 87 "#o0" - Disable continuous streaming output.
lpetre 0:9a72d42c0da3 88 "#o1" - Enable continuous streaming output.
lpetre 0:9a72d42c0da3 89 "#ob" - Output angles in binary format (yaw/pitch/roll as binary float, so one output frame
lpetre 0:9a72d42c0da3 90 is 3x4 = 12 bytes long).
lpetre 0:9a72d42c0da3 91 "#ot" - Output angles in text format (Output frames have form like "#YPR=-142.28,-5.38,33.52",
lpetre 0:9a72d42c0da3 92 followed by carriage return and line feed [\r\n]).
lpetre 0:9a72d42c0da3 93 "#os" - Output (calibrated) sensor data of all 9 axes in text format. One frame consist of
lpetre 0:9a72d42c0da3 94 three lines - one for each sensor.
lpetre 0:9a72d42c0da3 95 "#oc" - Go to calibration output mode.
lpetre 0:9a72d42c0da3 96 "#on" - When in calibration mode, go on to calibrate next sensor.
lpetre 0:9a72d42c0da3 97 "#oe0" - Disable error message output.
lpetre 0:9a72d42c0da3 98 "#oe1" - Enable error message output.
lpetre 0:9a72d42c0da3 99
lpetre 0:9a72d42c0da3 100 "#f" - Request one output frame - useful when continuous output is disabled and updates are
lpetre 0:9a72d42c0da3 101 required in larger intervals only.
lpetre 0:9a72d42c0da3 102 "#s<xy>" - Request synch token - useful to find out where the frame boundaries are in a continuous
lpetre 0:9a72d42c0da3 103 binary stream or to see if tracker is present and answering. The tracker will send
lpetre 0:9a72d42c0da3 104 "#SYNCH<xy>\r\n" in response (so it's possible to read using a readLine() function).
lpetre 0:9a72d42c0da3 105 x and y are two mandatory but arbitrary bytes that can be used to find out which request
lpetre 0:9a72d42c0da3 106 the answer belongs to.
lpetre 0:9a72d42c0da3 107
lpetre 0:9a72d42c0da3 108 ("#C" and "#D" - Reserved for communication with optional Bluetooth module.)
lpetre 0:9a72d42c0da3 109
lpetre 0:9a72d42c0da3 110 Newline characters are not required. So you could send "#ob#o1#s", which
lpetre 0:9a72d42c0da3 111 would set binary output mode, enable continuous streaming output and request
lpetre 0:9a72d42c0da3 112 a synch token all at once.
lpetre 0:9a72d42c0da3 113
lpetre 0:9a72d42c0da3 114 The status LED will be on if streaming output is enabled and off otherwise.
lpetre 0:9a72d42c0da3 115
lpetre 0:9a72d42c0da3 116 Byte order of binary output is little-endian: least significant byte comes first.
lpetre 0:9a72d42c0da3 117 */
lpetre 0:9a72d42c0da3 118 #include <mbed.h>
lpetre 0:9a72d42c0da3 119 #include <MODSERIAL.h>
lpetre 0:9a72d42c0da3 120
lpetre 0:9a72d42c0da3 121
lpetre 0:9a72d42c0da3 122 /*****************************************************************/
lpetre 0:9a72d42c0da3 123 /*********** USER SETUP AREA! Set your options here! *************/
lpetre 0:9a72d42c0da3 124 /*****************************************************************/
lpetre 0:9a72d42c0da3 125
lpetre 0:9a72d42c0da3 126 // HARDWARE OPTIONS
lpetre 0:9a72d42c0da3 127 /*****************************************************************/
lpetre 0:9a72d42c0da3 128 // Select your hardware here by uncommenting one line!
lpetre 0:9a72d42c0da3 129 //#define HW__VERSION_CODE 10125 // SparkFun "9DOF Razor IMU" version "SEN-10125" (HMC5843 magnetometer)
lpetre 0:9a72d42c0da3 130 #define HW__VERSION_CODE 10736 // SparkFun "9DOF Razor IMU" version "SEN-10736" (HMC5883L magnetometer)
lpetre 0:9a72d42c0da3 131 //#define HW__VERSION_CODE 10183 // SparkFun "9DOF Sensor Stick" version "SEN-10183" (HMC5843 magnetometer)
lpetre 0:9a72d42c0da3 132 //#define HW__VERSION_CODE 10321 // SparkFun "9DOF Sensor Stick" version "SEN-10321" (HMC5843 magnetometer)
lpetre 0:9a72d42c0da3 133 //#define HW__VERSION_CODE 10724 // SparkFun "9DOF Sensor Stick" version "SEN-10724" (HMC5883L magnetometer)
lpetre 0:9a72d42c0da3 134
lpetre 0:9a72d42c0da3 135
lpetre 0:9a72d42c0da3 136 // OUTPUT OPTIONS
lpetre 0:9a72d42c0da3 137 /*****************************************************************/
lpetre 0:9a72d42c0da3 138 // Set your serial port baud rate used to send out data here!
lpetre 0:9a72d42c0da3 139 #define OUTPUT__BAUD_RATE 57600
lpetre 0:9a72d42c0da3 140
lpetre 0:9a72d42c0da3 141 // Sensor data output interval in milliseconds
lpetre 0:9a72d42c0da3 142 // This may not work, if faster than 20ms (=50Hz)
lpetre 0:9a72d42c0da3 143 // Code is tuned for 20ms, so better leave it like that
lpetre 0:9a72d42c0da3 144 #define OUTPUT__DATA_INTERVAL 20 // in milliseconds
lpetre 0:9a72d42c0da3 145
lpetre 0:9a72d42c0da3 146 // Output mode
lpetre 0:9a72d42c0da3 147 #define OUTPUT__MODE_CALIBRATE_SENSORS 0 // Outputs sensor min/max values as text for manual calibration
lpetre 0:9a72d42c0da3 148 #define OUTPUT__MODE_ANGLES_TEXT 1 // Outputs yaw/pitch/roll in degrees as text
lpetre 0:9a72d42c0da3 149 #define OUTPUT__MODE_ANGLES_BINARY 2 // Outputs yaw/pitch/roll in degrees as binary float
lpetre 0:9a72d42c0da3 150 #define OUTPUT__MODE_SENSORS_TEXT 3 // Outputs (calibrated) sensor values for all 9 axes as text
lpetre 0:9a72d42c0da3 151
lpetre 0:9a72d42c0da3 152 // Select if serial continuous streaming output is enabled per default on startup.
lpetre 0:9a72d42c0da3 153 #define OUTPUT__STARTUP_STREAM_ON false // true or false
lpetre 0:9a72d42c0da3 154
lpetre 0:9a72d42c0da3 155 // Bluetooth
lpetre 0:9a72d42c0da3 156 // You can set this to true, if you have a Rovering Networks Bluetooth Module attached.
lpetre 0:9a72d42c0da3 157 // The connect/disconnect message prefix of the module has to be set to "#".
lpetre 0:9a72d42c0da3 158 // (Refer to manual, it can be set like this: SO,#)
lpetre 0:9a72d42c0da3 159 // When using this, streaming output will only be enabled as long as we're connected. That way
lpetre 0:9a72d42c0da3 160 // receiver and sender are synchronzed easily just by connecting/disconnecting.
lpetre 0:9a72d42c0da3 161 // It is not necessary to set this! It just makes life easier when writing code for
lpetre 0:9a72d42c0da3 162 // the receiving side. The Processing test sketch also works without setting this.
lpetre 0:9a72d42c0da3 163 // NOTE: When using this, OUTPUT__STARTUP_STREAM_ON has no effect!
lpetre 0:9a72d42c0da3 164 #define OUTPUT__HAS_RN_BLUETOOTH false // true or false
lpetre 0:9a72d42c0da3 165
lpetre 0:9a72d42c0da3 166
lpetre 0:9a72d42c0da3 167 // SENSOR CALIBRATION
lpetre 0:9a72d42c0da3 168 /*****************************************************************/
lpetre 0:9a72d42c0da3 169 // How to calibrate? Read the tutorial at http://dev.qu.tu-berlin.de/projects/sf-razor-9dof-ahrs
lpetre 0:9a72d42c0da3 170 // Put MIN/MAX and OFFSET readings for your board here!
lpetre 0:9a72d42c0da3 171 // Accelerometer
lpetre 0:9a72d42c0da3 172 // "accel x,y,z (min/max) = X_MIN/X_MAX Y_MIN/Y_MAX Z_MIN/Z_MAX"
lpetre 0:9a72d42c0da3 173 #define ACCEL_X_MIN ((float) -250)
lpetre 0:9a72d42c0da3 174 #define ACCEL_X_MAX ((float) 250)
lpetre 0:9a72d42c0da3 175 #define ACCEL_Y_MIN ((float) -250)
lpetre 0:9a72d42c0da3 176 #define ACCEL_Y_MAX ((float) 250)
lpetre 0:9a72d42c0da3 177 #define ACCEL_Z_MIN ((float) -250)
lpetre 0:9a72d42c0da3 178 #define ACCEL_Z_MAX ((float) 250)
lpetre 0:9a72d42c0da3 179
lpetre 0:9a72d42c0da3 180 // Magnetometer
lpetre 0:9a72d42c0da3 181 // "magn x,y,z (min/max) = X_MIN/X_MAX Y_MIN/Y_MAX Z_MIN/Z_MAX"
lpetre 0:9a72d42c0da3 182 #define MAGN_X_MIN ((float) -600)
lpetre 0:9a72d42c0da3 183 #define MAGN_X_MAX ((float) 600)
lpetre 0:9a72d42c0da3 184 #define MAGN_Y_MIN ((float) -600)
lpetre 0:9a72d42c0da3 185 #define MAGN_Y_MAX ((float) 600)
lpetre 0:9a72d42c0da3 186 #define MAGN_Z_MIN ((float) -600)
lpetre 0:9a72d42c0da3 187 #define MAGN_Z_MAX ((float) 600)
lpetre 0:9a72d42c0da3 188
lpetre 0:9a72d42c0da3 189 // Gyroscope
lpetre 0:9a72d42c0da3 190 // "gyro x,y,z (current/average) = .../OFFSET_X .../OFFSET_Y .../OFFSET_Z
lpetre 0:9a72d42c0da3 191 #define GYRO_AVERAGE_OFFSET_X ((float) 0.0)
lpetre 0:9a72d42c0da3 192 #define GYRO_AVERAGE_OFFSET_Y ((float) 0.0)
lpetre 0:9a72d42c0da3 193 #define GYRO_AVERAGE_OFFSET_Z ((float) 0.0)
lpetre 0:9a72d42c0da3 194
lpetre 0:9a72d42c0da3 195 /*
lpetre 0:9a72d42c0da3 196 // Calibration example:
lpetre 0:9a72d42c0da3 197 // "accel x,y,z (min/max) = -278.00/270.00 -254.00/284.00 -294.00/235.00"
lpetre 0:9a72d42c0da3 198 #define ACCEL_X_MIN ((float) -278)
lpetre 0:9a72d42c0da3 199 #define ACCEL_X_MAX ((float) 270)
lpetre 0:9a72d42c0da3 200 #define ACCEL_Y_MIN ((float) -254)
lpetre 0:9a72d42c0da3 201 #define ACCEL_Y_MAX ((float) 284)
lpetre 0:9a72d42c0da3 202 #define ACCEL_Z_MIN ((float) -294)
lpetre 0:9a72d42c0da3 203 #define ACCEL_Z_MAX ((float) 235)
lpetre 0:9a72d42c0da3 204
lpetre 0:9a72d42c0da3 205 // "magn x,y,z (min/max) = -511.00/581.00 -516.00/568.00 -489.00/486.00"
lpetre 0:9a72d42c0da3 206 #define MAGN_X_MIN ((float) -511)
lpetre 0:9a72d42c0da3 207 #define MAGN_X_MAX ((float) 581)
lpetre 0:9a72d42c0da3 208 #define MAGN_Y_MIN ((float) -516)
lpetre 0:9a72d42c0da3 209 #define MAGN_Y_MAX ((float) 568)
lpetre 0:9a72d42c0da3 210 #define MAGN_Z_MIN ((float) -489)
lpetre 0:9a72d42c0da3 211 #define MAGN_Z_MAX ((float) 486)
lpetre 0:9a72d42c0da3 212
lpetre 0:9a72d42c0da3 213 //"gyro x,y,z (current/average) = -32.00/-34.82 102.00/100.41 -16.00/-16.38"
lpetre 0:9a72d42c0da3 214 #define GYRO_AVERAGE_OFFSET_X ((float) -34.82)
lpetre 0:9a72d42c0da3 215 #define GYRO_AVERAGE_OFFSET_Y ((float) 100.41)
lpetre 0:9a72d42c0da3 216 #define GYRO_AVERAGE_OFFSET_Z ((float) -16.38)
lpetre 0:9a72d42c0da3 217 */
lpetre 0:9a72d42c0da3 218
lpetre 0:9a72d42c0da3 219
lpetre 0:9a72d42c0da3 220 // DEBUG OPTIONS
lpetre 0:9a72d42c0da3 221 /*****************************************************************/
lpetre 0:9a72d42c0da3 222 // When set to true, gyro drift correction will not be applied
lpetre 0:9a72d42c0da3 223 #define DEBUG__NO_DRIFT_CORRECTION false
lpetre 0:9a72d42c0da3 224 // Print elapsed time after each I/O loop
lpetre 0:9a72d42c0da3 225 #define DEBUG__PRINT_LOOP_TIME false
lpetre 0:9a72d42c0da3 226
lpetre 0:9a72d42c0da3 227
lpetre 0:9a72d42c0da3 228 /*****************************************************************/
lpetre 0:9a72d42c0da3 229 /****************** END OF USER SETUP AREA! *********************/
lpetre 0:9a72d42c0da3 230 /*****************************************************************/
lpetre 0:9a72d42c0da3 231
lpetre 0:9a72d42c0da3 232
lpetre 0:9a72d42c0da3 233 // Check if hardware version code is defined
lpetre 0:9a72d42c0da3 234 #ifndef HW__VERSION_CODE
lpetre 0:9a72d42c0da3 235 // Generate compile error
lpetre 0:9a72d42c0da3 236 #error YOU HAVE TO SELECT THE HARDWARE YOU ARE USING! See "HARDWARE OPTIONS" in "USER SETUP AREA" at top of Razor_AHRS.pde!
lpetre 0:9a72d42c0da3 237 #endif
lpetre 0:9a72d42c0da3 238
lpetre 0:9a72d42c0da3 239 //#include <Wire.h>
lpetre 0:9a72d42c0da3 240
lpetre 0:9a72d42c0da3 241 // Sensor calibration scale and offset values
lpetre 0:9a72d42c0da3 242 #define ACCEL_X_OFFSET ((ACCEL_X_MIN + ACCEL_X_MAX) / 2.0f)
lpetre 0:9a72d42c0da3 243 #define ACCEL_Y_OFFSET ((ACCEL_Y_MIN + ACCEL_Y_MAX) / 2.0f)
lpetre 0:9a72d42c0da3 244 #define ACCEL_Z_OFFSET ((ACCEL_Z_MIN + ACCEL_Z_MAX) / 2.0f)
lpetre 0:9a72d42c0da3 245 #define ACCEL_X_SCALE (GRAVITY / (ACCEL_X_MAX - ACCEL_X_OFFSET))
lpetre 0:9a72d42c0da3 246 #define ACCEL_Y_SCALE (GRAVITY / (ACCEL_Y_MAX - ACCEL_Y_OFFSET))
lpetre 0:9a72d42c0da3 247 #define ACCEL_Z_SCALE (GRAVITY / (ACCEL_Z_MAX - ACCEL_Z_OFFSET))
lpetre 0:9a72d42c0da3 248
lpetre 0:9a72d42c0da3 249 #define MAGN_X_OFFSET ((MAGN_X_MIN + MAGN_X_MAX) / 2.0f)
lpetre 0:9a72d42c0da3 250 #define MAGN_Y_OFFSET ((MAGN_Y_MIN + MAGN_Y_MAX) / 2.0f)
lpetre 0:9a72d42c0da3 251 #define MAGN_Z_OFFSET ((MAGN_Z_MIN + MAGN_Z_MAX) / 2.0f)
lpetre 0:9a72d42c0da3 252 #define MAGN_X_SCALE (100.0f / (MAGN_X_MAX - MAGN_X_OFFSET))
lpetre 0:9a72d42c0da3 253 #define MAGN_Y_SCALE (100.0f / (MAGN_Y_MAX - MAGN_Y_OFFSET))
lpetre 0:9a72d42c0da3 254 #define MAGN_Z_SCALE (100.0f / (MAGN_Z_MAX - MAGN_Z_OFFSET))
lpetre 0:9a72d42c0da3 255
lpetre 0:9a72d42c0da3 256
lpetre 0:9a72d42c0da3 257 // Gain for gyroscope (ITG-3200)
lpetre 0:9a72d42c0da3 258 #define GYRO_GAIN 0.06957 // Same gain on all axes
lpetre 0:9a72d42c0da3 259 #define GYRO_SCALED_RAD(x) (x * TO_RAD(GYRO_GAIN)) // Calculate the scaled gyro readings in radians per second
lpetre 0:9a72d42c0da3 260
lpetre 0:9a72d42c0da3 261 // DCM parameters
lpetre 0:9a72d42c0da3 262 #define Kp_ROLLPITCH 0.02f
lpetre 0:9a72d42c0da3 263 #define Ki_ROLLPITCH 0.00002f
lpetre 0:9a72d42c0da3 264 #define Kp_YAW 1.2f
lpetre 0:9a72d42c0da3 265 #define Ki_YAW 0.00002f
lpetre 0:9a72d42c0da3 266
lpetre 0:9a72d42c0da3 267 // Stuff
lpetre 0:9a72d42c0da3 268 #define GRAVITY 256.0f // "1G reference" used for DCM filter and accelerometer calibration
lpetre 0:9a72d42c0da3 269 #define TO_RAD(x) (x * 0.01745329252) // *pi/180
lpetre 0:9a72d42c0da3 270 #define TO_DEG(x) (x * 57.2957795131) // *180/pi
lpetre 0:9a72d42c0da3 271 #define NEW_LINE "\r\n"
lpetre 0:9a72d42c0da3 272
lpetre 0:9a72d42c0da3 273 class IMU {
lpetre 0:9a72d42c0da3 274 public:
lpetre 0:9a72d42c0da3 275 // Sensor variables
lpetre 0:9a72d42c0da3 276 int16_t accel[3]; // Actually stores the NEGATED acceleration (equals gravity, if board not moving).
lpetre 0:9a72d42c0da3 277 int16_t accel_min[3];
lpetre 0:9a72d42c0da3 278 int16_t accel_max[3];
lpetre 0:9a72d42c0da3 279
lpetre 0:9a72d42c0da3 280 int16_t magnetom[3];
lpetre 0:9a72d42c0da3 281 int16_t magnetom_min[3];
lpetre 0:9a72d42c0da3 282 int16_t magnetom_max[3];
lpetre 0:9a72d42c0da3 283
lpetre 0:9a72d42c0da3 284 int16_t gyro[3];
lpetre 0:9a72d42c0da3 285 int16_t gyro_average[3];
lpetre 0:9a72d42c0da3 286 int gyro_num_samples;
lpetre 0:9a72d42c0da3 287
lpetre 0:9a72d42c0da3 288 // Euler angles
lpetre 0:9a72d42c0da3 289 float yaw;
lpetre 0:9a72d42c0da3 290 float pitch;
lpetre 0:9a72d42c0da3 291 float roll;
lpetre 0:9a72d42c0da3 292
lpetre 0:9a72d42c0da3 293 // DCM variables
lpetre 0:9a72d42c0da3 294 float MAG_Heading;
lpetre 0:9a72d42c0da3 295 float Accel_Vector[3]; // Store the acceleration in a vector
lpetre 0:9a72d42c0da3 296 float Gyro_Vector[3]; // Store the gyros turn rate in a vector
lpetre 0:9a72d42c0da3 297 float Omega_Vector[3]; // Corrected Gyro_Vector data
lpetre 0:9a72d42c0da3 298 float Omega_P[3];//= {0, 0, 0}; // Omega Proportional correction
lpetre 0:9a72d42c0da3 299 float Omega_I[3];//= {0, 0, 0}; // Omega Integrator
lpetre 0:9a72d42c0da3 300 float Omega[3];//= {0, 0, 0};
lpetre 0:9a72d42c0da3 301 float errorRollPitch[3];// = {0, 0, 0};
lpetre 0:9a72d42c0da3 302 float errorYaw[3];// = {0, 0, 0};
lpetre 0:9a72d42c0da3 303 float DCM_Matrix[3][3];// = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
lpetre 0:9a72d42c0da3 304 float Update_Matrix[3][3];// = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
lpetre 0:9a72d42c0da3 305 float Temporary_Matrix[3][3];// = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
lpetre 0:9a72d42c0da3 306
lpetre 0:9a72d42c0da3 307 // DCM timing in the main loop
lpetre 0:9a72d42c0da3 308 long timestamp;
lpetre 0:9a72d42c0da3 309 long timestamp_old;
lpetre 0:9a72d42c0da3 310 float G_Dt; // Integration time for DCM algorithm
lpetre 0:9a72d42c0da3 311
lpetre 0:9a72d42c0da3 312 // More output-state variables
lpetre 0:9a72d42c0da3 313 int output_mode;
lpetre 0:9a72d42c0da3 314 bool output_stream_on;
lpetre 0:9a72d42c0da3 315 bool output_single_on;
lpetre 0:9a72d42c0da3 316 int curr_calibration_sensor;
lpetre 0:9a72d42c0da3 317 bool reset_calibration_session_flag;
lpetre 0:9a72d42c0da3 318 int num_accel_errors;
lpetre 0:9a72d42c0da3 319 int num_magn_errors;
lpetre 0:9a72d42c0da3 320 int num_gyro_errors;
lpetre 0:9a72d42c0da3 321
lpetre 0:9a72d42c0da3 322 // If set true, an error message will be output if we fail to read sensor data.
lpetre 0:9a72d42c0da3 323 // Message format: "!ERR: reading <sensor>", followed by "\r\n".
lpetre 0:9a72d42c0da3 324 bool output_errors;
lpetre 0:9a72d42c0da3 325
lpetre 0:9a72d42c0da3 326 DigitalOut statusLed;
lpetre 0:9a72d42c0da3 327 MODSERIAL pc;
lpetre 0:9a72d42c0da3 328 I2C Wire;
lpetre 0:9a72d42c0da3 329 Timer timer;
lpetre 0:9a72d42c0da3 330
lpetre 0:9a72d42c0da3 331 public:
lpetre 0:9a72d42c0da3 332 IMU()
lpetre 0:9a72d42c0da3 333 : gyro_num_samples(0)
lpetre 0:9a72d42c0da3 334 , yaw(0)
lpetre 0:9a72d42c0da3 335 , pitch(0)
lpetre 0:9a72d42c0da3 336 , roll(0)
lpetre 0:9a72d42c0da3 337 , MAG_Heading(0)
lpetre 0:9a72d42c0da3 338 , timestamp(0)
lpetre 0:9a72d42c0da3 339 , timestamp_old(0)
lpetre 0:9a72d42c0da3 340 , G_Dt(0)
lpetre 0:9a72d42c0da3 341 , output_mode(-1) // Select your startup output mode here!// Select your startup output mode here!
lpetre 0:9a72d42c0da3 342 , output_stream_on(false)
lpetre 0:9a72d42c0da3 343 , output_single_on(true)
lpetre 0:9a72d42c0da3 344 , curr_calibration_sensor(0)
lpetre 0:9a72d42c0da3 345 , reset_calibration_session_flag(true)
lpetre 0:9a72d42c0da3 346 , num_accel_errors(0)
lpetre 0:9a72d42c0da3 347 , num_magn_errors(0)
lpetre 0:9a72d42c0da3 348 , num_gyro_errors(0)
lpetre 0:9a72d42c0da3 349 , output_errors(true)
lpetre 0:9a72d42c0da3 350 , statusLed(LED1)
lpetre 0:9a72d42c0da3 351 , pc(USBTX, USBRX)
lpetre 0:9a72d42c0da3 352 , Wire(p28, p27)
lpetre 0:9a72d42c0da3 353 {
lpetre 0:9a72d42c0da3 354 accel[0] = accel_min[0] = accel_max[0] = magnetom[0] = magnetom_min[0] = magnetom_max[0] = gyro[0] = gyro_average[0] = 0;
lpetre 0:9a72d42c0da3 355 accel[1] = accel_min[1] = accel_max[1] = magnetom[1] = magnetom_min[1] = magnetom_max[1] = gyro[1] = gyro_average[1] = 0;
lpetre 0:9a72d42c0da3 356 accel[2] = accel_min[2] = accel_max[2] = magnetom[2] = magnetom_min[2] = magnetom_max[2] = gyro[2] = gyro_average[2] = 0;
lpetre 0:9a72d42c0da3 357
lpetre 0:9a72d42c0da3 358 Accel_Vector[0] = Gyro_Vector[0] = Omega_Vector[0] = Omega_P[0] = Omega_I[0] = Omega[0] = errorRollPitch[0] = errorYaw[0] = 0;
lpetre 0:9a72d42c0da3 359 Accel_Vector[1] = Gyro_Vector[1] = Omega_Vector[1] = Omega_P[1] = Omega_I[1] = Omega[1] = errorRollPitch[1] = errorYaw[1] = 0;
lpetre 0:9a72d42c0da3 360 Accel_Vector[2] = Gyro_Vector[2] = Omega_Vector[2] = Omega_P[2] = Omega_I[2] = Omega[2] = errorRollPitch[2] = errorYaw[2] = 0;
lpetre 0:9a72d42c0da3 361
lpetre 0:9a72d42c0da3 362 DCM_Matrix[0][0] = 1; DCM_Matrix[0][1] = 0; DCM_Matrix[0][2] = 0;
lpetre 0:9a72d42c0da3 363 DCM_Matrix[1][0] = 0; DCM_Matrix[1][1] = 1; DCM_Matrix[1][2] = 0;
lpetre 0:9a72d42c0da3 364 DCM_Matrix[2][0] = 0; DCM_Matrix[2][1] = 0; DCM_Matrix[2][2] = 1;
lpetre 0:9a72d42c0da3 365
lpetre 0:9a72d42c0da3 366 Update_Matrix[0][0] = 0; Update_Matrix[0][1] = 1; Update_Matrix[0][2] = 2;
lpetre 0:9a72d42c0da3 367 Update_Matrix[1][0] = 3; Update_Matrix[1][1] = 4; Update_Matrix[1][2] = 5;
lpetre 0:9a72d42c0da3 368 Update_Matrix[2][0] = 6; Update_Matrix[2][1] = 7; Update_Matrix[2][2] = 8;
lpetre 0:9a72d42c0da3 369
lpetre 0:9a72d42c0da3 370 Temporary_Matrix[0][0] = 0; Temporary_Matrix[0][1] = 0; Temporary_Matrix[0][2] = 0;
lpetre 0:9a72d42c0da3 371 Temporary_Matrix[1][0] = 0; Temporary_Matrix[1][1] = 0; Temporary_Matrix[1][2] = 0;
lpetre 0:9a72d42c0da3 372 Temporary_Matrix[2][0] = 0; Temporary_Matrix[2][1] = 0; Temporary_Matrix[2][2] = 0;
lpetre 0:9a72d42c0da3 373 }
lpetre 0:9a72d42c0da3 374
lpetre 0:9a72d42c0da3 375 // Compass.cpp
lpetre 0:9a72d42c0da3 376 void Compass_Heading();
lpetre 0:9a72d42c0da3 377
lpetre 0:9a72d42c0da3 378 // DCM.cpp
lpetre 0:9a72d42c0da3 379 void Normalize();
lpetre 0:9a72d42c0da3 380 void Drift_correction();
lpetre 0:9a72d42c0da3 381 void Matrix_update();
lpetre 0:9a72d42c0da3 382 void Euler_angles();
lpetre 0:9a72d42c0da3 383
lpetre 0:9a72d42c0da3 384 // Output.cpp
lpetre 0:9a72d42c0da3 385 void output_angles();
lpetre 0:9a72d42c0da3 386 void output_calibration(int calibration_sensor);
lpetre 0:9a72d42c0da3 387 void output_sensors();
lpetre 0:9a72d42c0da3 388
lpetre 0:9a72d42c0da3 389
lpetre 0:9a72d42c0da3 390 // Razor_AHRS.cpp
lpetre 0:9a72d42c0da3 391 void read_sensors();
lpetre 0:9a72d42c0da3 392 void reset_sensor_fusion();
lpetre 0:9a72d42c0da3 393 void compensate_sensor_errors();
lpetre 0:9a72d42c0da3 394 void check_reset_calibration_session();
lpetre 0:9a72d42c0da3 395 void turn_output_stream_on();
lpetre 0:9a72d42c0da3 396 void turn_output_stream_off();
lpetre 0:9a72d42c0da3 397 char readChar();
lpetre 0:9a72d42c0da3 398 void setup();
lpetre 0:9a72d42c0da3 399 void loop();
lpetre 0:9a72d42c0da3 400
lpetre 0:9a72d42c0da3 401
lpetre 0:9a72d42c0da3 402 // Sensors.cpp
lpetre 0:9a72d42c0da3 403 void I2C_Init();
lpetre 0:9a72d42c0da3 404 void Accel_Init();
lpetre 0:9a72d42c0da3 405 void Read_Accel();
lpetre 0:9a72d42c0da3 406 void Magn_Init();
lpetre 0:9a72d42c0da3 407 void Read_Magn();
lpetre 0:9a72d42c0da3 408 void Gyro_Init();
lpetre 0:9a72d42c0da3 409 void Read_Gyro();
lpetre 0:9a72d42c0da3 410
lpetre 0:9a72d42c0da3 411 };
lpetre 0:9a72d42c0da3 412
lpetre 0:9a72d42c0da3 413 float Vector_Dot_Product(float vector1[3], float vector2[3]);
lpetre 0:9a72d42c0da3 414 void Vector_Cross_Product(float vectorOut[3], float v1[3], float v2[3]);
lpetre 0:9a72d42c0da3 415 void Vector_Scale(float vectorOut[3], float vectorIn[3], float scale2);
lpetre 0:9a72d42c0da3 416 void Vector_Add(float vectorOut[3], float vectorIn1[3], float vectorIn2[3]);
lpetre 0:9a72d42c0da3 417 void Matrix_Multiply(float a[3][3], float b[3][3],float mat[3][3]);
lpetre 0:9a72d42c0da3 418 void init_rotation_matrix(float m[3][3], float yaw, float pitch, float roll);
lpetre 0:9a72d42c0da3 419 float constrain(float in, float min, float max);
lpetre 0:9a72d42c0da3 420