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