Advertisement
Guest User

Untitled

a guest
Jun 20th, 2012
28
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 21.23 KB | None | 0 0
  1. /***************************************************************************************************************
  2.  * Razor AHRS Firmware v1.4.0
  3.  * 9 Degree of Measurement Attitude and Heading Reference System
  4.  * for Sparkfun "9DOF Razor IMU" (SEN-10125 and SEN-10736)
  5.  * and "9DOF Sensor Stick" (SEN-10183, 10321 and SEN-10724)
  6.  *
  7.  * Released under GNU GPL (General Public License) v3.0
  8.  * Copyright (C) 2011 Quality & Usability Lab, Deutsche Telekom Laboratories, TU Berlin
  9.  *
  10.  * Infos, updates, bug reports and feedback:
  11.  *     http://dev.qu.tu-berlin.de/projects/sf-razor-9dof-ahrs
  12.  *
  13.  *
  14.  * History:
  15.  *   * Original code (http://code.google.com/p/sf9domahrs/) by Doug Weibel and Jose Julio,
  16.  *     based on ArduIMU v1.5 by Jordi Munoz and William Premerlani, Jose Julio and Doug Weibel. Thank you!
  17.  *
  18.  *   * Updated code (http://groups.google.com/group/sf_9dof_ahrs_update) by David Malik (david.zsolt.malik@gmail.com)
  19.  *     for new Sparkfun 9DOF Razor hardware (SEN-10125).
  20.  *
  21.  *   * Updated and extended by Peter Bartz (peter-bartz@gmx.de):
  22.  *     * v1.3.0
  23.  *       * Cleaned up, streamlined and restructured most of the code to make it more comprehensible.
  24.  *       * Added sensor calibration (improves precision and responsiveness a lot!).
  25.  *       * Added binary yaw/pitch/roll output.
  26.  *       * Added basic serial command interface to set output modes/calibrate sensors/synch stream/etc.
  27.  *       * Added support to synch automatically when using Rovering Networks Bluetooth modules (and compatible).
  28.  *       * Wrote new easier to use test program (using Processing).
  29.  *       * Added support for new version of "9DOF Razor IMU": SEN-10736.
  30.  *       --> The output of this code is not compatible with the older versions!
  31.  *       --> A Processing sketch to test the tracker is available.
  32.  *     * v1.3.1
  33.  *       * Initializing rotation matrix based on start-up sensor readings -> orientation OK right away.
  34.  *       * Adjusted gyro low-pass filter and output rate settings.
  35.  *     * v1.3.2
  36.  *       * Adapted code to work with new Arduino 1.0 (and older versions still).
  37.  *     * v1.3.3
  38.  *       * Improved synching.
  39.  *     * v1.4.0
  40.  *       * Added support for SparkFun "9DOF Sensor Stick" (versions SEN-10183, SEN-10321 and SEN-10724).
  41.  *
  42.  * TODOs:
  43.  *   * Allow optional use of EEPROM for storing and reading calibration values.
  44.  *   * Use self-test and temperature-compensation features of the sensors.
  45.  *   * Add binary output of unfused sensor data for all 9 axes.
  46.  ***************************************************************************************************************/
  47.  
  48. /*
  49.   "9DOF Razor IMU" hardware versions: SEN-10125 and SEN-10736
  50.  
  51.  ATMega328@3.3V, 8MHz
  52.  
  53.  ADXL345  : Accelerometer
  54.  HMC5843  : Magnetometer on SEN-10125
  55.  HMC5883L : Magnetometer on SEN-10736
  56.  ITG-3200 : Gyro
  57.  
  58.  Arduino IDE : Select board "Arduino Pro or Pro Mini (3.3v, 8Mhz) w/ATmega328"
  59.  */
  60.  
  61. /*
  62.   "9DOF Sensor Stick" hardware versions: SEN-10183, SEN-10321 and SEN-10724
  63.  
  64.  ADXL345  : Accelerometer
  65.  HMC5843  : Magnetometer on SEN-10183 and SEN-10321
  66.  HMC5883L : Magnetometer on SEN-10724
  67.  ITG-3200 : Gyro
  68.  */
  69.  
  70. /*
  71.   Axis definition (differs from definition printed on the board!):
  72.  X axis pointing forward (towards the short edge with the connector holes)
  73.  Y axis pointing to the right
  74.  and Z axis pointing down.
  75.  
  76.  Positive yaw   : clockwise
  77.  Positive roll  : right wing down
  78.  Positive pitch : nose up
  79.  
  80.  Transformation order: first yaw then pitch then roll.
  81.  */
  82.  
  83. /*
  84.   Commands that the firmware understands:
  85.  
  86.  "#o<param>" - Set output parameter. The available options are:
  87.  "#o0" - Disable continuous streaming output.
  88.  "#o1" - Enable continuous streaming output.
  89.  "#ob" - Output angles in binary format (yaw/pitch/roll as binary float, so one output frame
  90.  is 3x4 = 12 bytes long).
  91.  "#ot" - Output angles in text format (Output frames have form like "#YPR=-142.28,-5.38,33.52",
  92.  followed by carriage return and line feed [\r\n]).
  93.  "#os" - Output (calibrated) sensor data of all 9 axes in text format. One frame consist of
  94.  three lines - one for each sensor.
  95.  "#oc" - Go to calibration output mode.
  96.  "#on" - When in calibration mode, go on to calibrate next sensor.
  97.  "#oe0" - Disable error message output.
  98.  "#oe1" - Enable error message output.
  99.  
  100.  "#f" - Request one output frame - useful when continuous output is disabled and updates are
  101.  required in larger intervals only.
  102.  "#s<xy>" - Request synch token - useful to find out where the frame boundaries are in a continuous
  103.  binary stream or to see if tracker is present and answering. The tracker will send
  104.  "#SYNCH<xy>\r\n" in response (so it's possible to read using a readLine() function).
  105.  x and y are two mandatory but arbitrary bytes that can be used to find out which request
  106.  the answer belongs to.
  107.  
  108.  ("#C" and "#D" - Reserved for communication with optional Bluetooth module.)
  109.  
  110.  Newline characters are not required. So you could send "#ob#o1#s", which
  111.  would set binary output mode, enable continuous streaming output and request
  112.  a synch token all at once.
  113.  
  114.  The status LED will be on if streaming output is enabled and off otherwise.
  115.  
  116.  Byte order of binary output is little-endian: least significant byte comes first.
  117.  */
  118.  
  119.  
  120.  
  121. /*****************************************************************/
  122. /*********** USER SETUP AREA! Set your options heredall! *************/
  123. /*****************************************************************/
  124.  
  125. // HARDWARE OPTIONS
  126. /*****************************************************************/
  127. // Select your hardware here by uncommenting one line!
  128. //#define HW__VERSION_CODE 10125 // SparkFun "9DOF Razor IMU" version "SEN-10125" (HMC5843 magnetometer)
  129. //#define HW__VERSION_CODE 10736 // SparkFun "9DOF Razor IMU" version "SEN-10736" (HMC5883L magnetometer)
  130. //#define HW__VERSION_CODE 10183 // SparkFun "9DOF Sensor Stick" version "SEN-10183" (HMC5843 magnetometer)
  131. //#define HW__VERSION_CODE 10321 // SparkFun "9DOF Sensor Stick" version "SEN-10321" (HMC5843 magnetometer)
  132. #define HW__VERSION_CODE 10724 // SparkFun "9DOF Sensor Stick" version "SEN-10724" (HMC5883L magnetometer)
  133.  
  134.  
  135. // OUTPUT OPTIONS
  136. /*****************************************************************/
  137. // Set your serial port baud rate used to send out data here!
  138. #define OUTPUT__BAUD_RATE 115200
  139.  
  140. // Sensor data output interval in milliseconds
  141. // This may not work, if faster than 20ms (=50Hz)
  142. // Code is tuned for 20ms, so better leave it like that
  143. #define OUTPUT__DATA_INTERVAL 20  // in milliseconds
  144.  
  145. // Output mode
  146. #define OUTPUT__MODE_CALIBRATE_SENSORS 0 // Outputs sensor min/max values as text for manual calibration
  147. #define OUTPUT__MODE_ANGLES_TEXT 1 // Outputs yaw/pitch/roll in degrees as text
  148. #define OUTPUT__MODE_ANGLES_BINARY 2 // Outputs yaw/pitch/roll in degrees as binary float
  149. #define OUTPUT__MODE_SENSORS_TEXT 3 // Outputs (calibrated) sensor values for all 9 axes as text
  150. // Select your startup output mode here!
  151. int output_mode = OUTPUT__MODE_ANGLES_TEXT;
  152.  
  153. // Select if serial continuous streaming output is enabled per default on startup.
  154. #define OUTPUT__STARTUP_STREAM_ON true  // true or false
  155.  
  156. // If set true, an error message will be output if we fail to read sensor data.
  157. // Message format: "!ERR: reading <sensor>", followed by "\r\n".
  158. boolean output_errors = false;  // true or false
  159.  
  160. // Bluetooth
  161. // You can set this to true, if you have a Rovering Networks Bluetooth Module attached.
  162. // The connect/disconnect message prefix of the module has to be set to "#".
  163. // (Refer to manual, it can be set like this: SO,#)
  164. // When using this, streaming output will only be enabled as long as we're connected. That way
  165. // receiver and sender are synchronzed easily just by connecting/disconnecting.
  166. // It is not necessary to set this! It just makes life easier when writing code for
  167. // the receiving side. The Processing test sketch also works without setting this.
  168. // NOTE: When using this, OUTPUT__STARTUP_STREAM_ON has no effect!
  169. #define OUTPUT__HAS_RN_BLUETOOTH false  // true or false
  170.  
  171.  
  172. // SENSOR CALIBRATION
  173. /*****************************************************************/
  174. // How to calibrate? Read the tutorial at http://dev.qu.tu-berlin.de/projects/sf-razor-9dof-ahrs
  175. // Put MIN/MAX and OFFSET readings for your board here!
  176. // Accelerometer
  177. // "accel x,y,z (min/max) = X_MIN/X_MAX  Y_MIN/Y_MAX  Z_MIN/Z_MAX"
  178. #define ACCEL_X_MIN ((float) -275)
  179. #define ACCEL_X_MAX ((float) 320)
  180. #define ACCEL_Y_MIN ((float) -265)
  181. #define ACCEL_Y_MAX ((float) 320)
  182. #define ACCEL_Z_MIN ((float) -300)
  183. #define ACCEL_Z_MAX ((float) 260)
  184.  
  185. // Magnetometer
  186. // "magn x,y,z (min/max) = X_MIN/X_MAX  Y_MIN/Y_MAX  Z_MIN/Z_MAX"
  187. #define MAGN_X_MIN ((float) -475)
  188. #define MAGN_X_MAX ((float) 565)
  189. #define MAGN_Y_MIN ((float) -288)
  190. #define MAGN_Y_MAX ((float) 786)
  191. #define MAGN_Z_MIN ((float) -511)
  192. #define MAGN_Z_MAX ((float) 510)
  193.  
  194. // Gyroscope
  195. // "gyro x,y,z (current/average) = .../OFFSET_X  .../OFFSET_Y  .../OFFSET_Z
  196. #define GYRO_AVERAGE_OFFSET_X ((float) 7.13)
  197. #define GYRO_AVERAGE_OFFSET_Y ((float) 25.78)
  198. #define GYRO_AVERAGE_OFFSET_Z ((float) 19.54)
  199.  
  200. /*
  201. // Calibration example:
  202.  // "accel x,y,z (min/max) = -278.00/270.00  -254.00/284.00  -294.00/235.00"
  203.  #define ACCEL_X_MIN ((float) -278)
  204.  #define ACCEL_X_MAX ((float) 270)
  205.  #define ACCEL_Y_MIN ((float) -254)
  206.  #define ACCEL_Y_MAX ((float) 284)
  207.  #define ACCEL_Z_MIN ((float) -294)
  208.  #define ACCEL_Z_MAX ((float) 235)
  209.  
  210.  // "magn x,y,z (min/max) = -511.00/581.00  -516.00/568.00  -489.00/486.00"
  211.  #define MAGN_X_MIN ((float) -511)
  212.  #define MAGN_X_MAX ((float) 581)
  213.  #define MAGN_Y_MIN ((float) -516)
  214.  #define MAGN_Y_MAX ((float) 568)
  215.  #define MAGN_Z_MIN ((float) -489)
  216.  #define MAGN_Z_MAX ((float) 486)
  217.  
  218.  //"gyro x,y,z (current/average) = -32.00/-34.82  102.00/100.41  -16.00/-16.38"
  219.  #define GYRO_AVERAGE_OFFSET_X ((float) -34.82)
  220.  #define GYRO_AVERAGE_OFFSET_Y ((float) 100.41)
  221.  #define GYRO_AVERAGE_OFFSET_Z ((float) -16.38)
  222.  */
  223.  
  224.  
  225. // DEBUG OPTIONS
  226. /*****************************************************************/
  227. // When set to true, gyro drift correction will not be applied
  228. #define DEBUG__NO_DRIFT_CORRECTION false
  229. // Print elapsed time after each I/O loop
  230. #define DEBUG__PRINT_LOOP_TIME false
  231.  
  232.  
  233. /*****************************************************************/
  234. /****************** END OF USER SETUP AREA!  *********************/
  235. /*****************************************************************/
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246. // Check if hardware version code is defined
  247. #ifndef HW__VERSION_CODE
  248. // Generate compile error
  249. #error YOU HAVE TO SELECT THE HARDWARE YOU ARE USING! See "HARDWARE OPTIONS" in "USER SETUP AREA" at top of Razor_AHRS.pde!
  250. #endif
  251.  
  252. #include <Wire.h>
  253.  
  254. // Sensor calibration scale and offset values
  255. #define ACCEL_X_OFFSET ((ACCEL_X_MIN + ACCEL_X_MAX) / 2.0f)
  256. #define ACCEL_Y_OFFSET ((ACCEL_Y_MIN + ACCEL_Y_MAX) / 2.0f)
  257. #define ACCEL_Z_OFFSET ((ACCEL_Z_MIN + ACCEL_Z_MAX) / 2.0f)
  258. #define ACCEL_X_SCALE (GRAVITY / (ACCEL_X_MAX - ACCEL_X_OFFSET))
  259. #define ACCEL_Y_SCALE (GRAVITY / (ACCEL_Y_MAX - ACCEL_Y_OFFSET))
  260. #define ACCEL_Z_SCALE (GRAVITY / (ACCEL_Z_MAX - ACCEL_Z_OFFSET))
  261.  
  262. #define MAGN_X_OFFSET ((MAGN_X_MIN + MAGN_X_MAX) / 2.0f)
  263. #define MAGN_Y_OFFSET ((MAGN_Y_MIN + MAGN_Y_MAX) / 2.0f)
  264. #define MAGN_Z_OFFSET ((MAGN_Z_MIN + MAGN_Z_MAX) / 2.0f)
  265. #define MAGN_X_SCALE (100.0f / (MAGN_X_MAX - MAGN_X_OFFSET))
  266. #define MAGN_Y_SCALE (100.0f / (MAGN_Y_MAX - MAGN_Y_OFFSET))
  267. #define MAGN_Z_SCALE (100.0f / (MAGN_Z_MAX - MAGN_Z_OFFSET))
  268.  
  269.  
  270. // Gain for gyroscope (ITG-3200)
  271. #define GYRO_GAIN 0.06957 // Same gain on all axes
  272. #define GYRO_SCALED_RAD(x) (x * TO_RAD(GYRO_GAIN)) // Calculate the scaled gyro readings in radians per second
  273.  
  274. // DCM parameters
  275. #define Kp_ROLLPITCH 0.02f
  276. #define Ki_ROLLPITCH 0.00002f
  277. #define Kp_YAW 1.2f
  278. #define Ki_YAW 0.00002f
  279.  
  280. // Stuff
  281. #define STATUS_LED_PIN 13  // Pin number of status LED
  282. #define GRAVITY 256.0f // "1G reference" used for DCM filter and accelerometer calibration
  283. #define TO_RAD(x) (x * 0.01745329252)  // *pi/180
  284. #define TO_DEG(x) (x * 57.2957795131)  // *180/pi
  285.  
  286. // Sensor variables
  287. float accel[3];  // Actually stores the NEGATED acceleration (equals gravity, if board not moving).
  288. float accel_min[3];
  289. float accel_max[3];
  290.  
  291. float magnetom[3];
  292. float magnetom_min[3];
  293. float magnetom_max[3];
  294.  
  295. float gyro[3];
  296. float gyro_average[3];
  297. int gyro_num_samples = 0;
  298.  
  299. // DCM variables
  300. float MAG_Heading;
  301. float Accel_Vector[3]= {
  302.   0, 0, 0}; // Store the acceleration in a vector
  303. float Gyro_Vector[3]= {
  304.   0, 0, 0}; // Store the gyros turn rate in a vector
  305. float Omega_Vector[3]= {
  306.   0, 0, 0}; // Corrected Gyro_Vector data
  307. float Omega_P[3]= {
  308.   0, 0, 0}; // Omega Proportional correction
  309. float Omega_I[3]= {
  310.   0, 0, 0}; // Omega Integrator
  311. float Omega[3]= {
  312.   0, 0, 0};
  313. float errorRollPitch[3] = {
  314.   0, 0, 0};
  315. float errorYaw[3] = {
  316.   0, 0, 0};
  317. float DCM_Matrix[3][3] = {
  318.   {
  319.     1, 0, 0  }
  320.   , {
  321.     0, 1, 0  }
  322.   , {
  323.     0, 0, 1  }
  324. };
  325. float Update_Matrix[3][3] = {
  326.   {
  327.     0, 1, 2  }
  328.   , {
  329.     3, 4, 5  }
  330.   , {
  331.     6, 7, 8  }
  332. };
  333. float Temporary_Matrix[3][3] = {
  334.   {
  335.     0, 0, 0  }
  336.   , {
  337.     0, 0, 0  }
  338.   , {
  339.     0, 0, 0  }
  340. };
  341.  
  342. // Euler angles
  343. float yaw;
  344. float pitch;
  345. float roll;
  346.  
  347. // DCM timing in the main loop
  348. long timestamp;
  349. long timestamp_old;
  350. float G_Dt; // Integration time for DCM algorithm
  351.  
  352. // More output-state variables
  353. boolean output_stream_on;
  354. boolean output_single_on;
  355. int curr_calibration_sensor = 0;
  356. boolean reset_calibration_session_flag = true;
  357. int num_accel_errors = 0;
  358. int num_magn_errors = 0;
  359. int num_gyro_errors = 0;
  360.  
  361. void read_sensors() {
  362.   Read_Gyro(); // Read gyroscope
  363.   Read_Accel(); // Read accelerometer
  364.   Read_Magn(); // Read magnetometer
  365. }
  366.  
  367. // Read every sensor and record a time stamp
  368. // Init DCM with unfiltered orientation
  369. // TODO re-init global vars?
  370. void reset_sensor_fusion() {
  371.   float temp1[3];
  372.   float temp2[3];
  373.   float xAxis[] = {
  374.     1.0f, 0.0f, 0.0f  };
  375.  
  376.   read_sensors();
  377.   timestamp = millis();
  378.  
  379.   // GET PITCH
  380.   // Using y-z-plane-component/x-component of gravity vector
  381.   pitch = -atan2(accel[0], sqrt(accel[1] * accel[1] + accel[2] * accel[2]));
  382.  
  383.   // GET ROLL
  384.   // Compensate pitch of gravity vector
  385.   Vector_Cross_Product(temp1, accel, xAxis);
  386.   Vector_Cross_Product(temp2, xAxis, temp1);
  387.   // Normally using x-z-plane-component/y-component of compensated gravity vector
  388.   // roll = atan2(temp2[1], sqrt(temp2[0] * temp2[0] + temp2[2] * temp2[2]));
  389.   // Since we compensated for pitch, x-z-plane-component equals z-component:
  390.   roll = atan2(temp2[1], temp2[2]);
  391.  
  392.   // GET YAW
  393.   Compass_Heading();
  394.   yaw = MAG_Heading;
  395.  
  396.   // Init rotation matrix
  397.   init_rotation_matrix(DCM_Matrix, yaw, pitch, roll);
  398. }
  399.  
  400. // Apply calibration to raw sensor readings
  401. void compensate_sensor_errors() {
  402.   // Compensate accelerometer error
  403.   accel[0] = (accel[0] - ACCEL_X_OFFSET) * ACCEL_X_SCALE;
  404.   accel[1] = (accel[1] - ACCEL_Y_OFFSET) * ACCEL_Y_SCALE;
  405.   accel[2] = (accel[2] - ACCEL_Z_OFFSET) * ACCEL_Z_SCALE;
  406.  
  407.   // Compensate magnetometer error
  408.   magnetom[0] = (magnetom[0] - MAGN_X_OFFSET) * MAGN_X_SCALE;
  409.   magnetom[1] = (magnetom[1] - MAGN_Y_OFFSET) * MAGN_Y_SCALE;
  410.   magnetom[2] = (magnetom[2] - MAGN_Z_OFFSET) * MAGN_Z_SCALE;
  411.  
  412.   // Compensate gyroscope error
  413.   gyro[0] -= GYRO_AVERAGE_OFFSET_X;
  414.   gyro[1] -= GYRO_AVERAGE_OFFSET_Y;
  415.   gyro[2] -= GYRO_AVERAGE_OFFSET_Z;
  416. }
  417.  
  418. // Reset calibration session if reset_calibration_session_flag is set
  419. void check_reset_calibration_session()
  420. {
  421.   // Raw sensor values have to be read already, but no error compensation applied
  422.  
  423.   // Reset this calibration session?
  424.   if (!reset_calibration_session_flag) return;
  425.  
  426.   // Reset acc and mag calibration variables
  427.   for (int i = 0; i < 3; i++) {
  428.     accel_min[i] = accel_max[i] = accel[i];
  429.     magnetom_min[i] = magnetom_max[i] = magnetom[i];
  430.   }
  431.  
  432.   // Reset gyro calibration variables
  433.   gyro_num_samples = 0;  // Reset gyro calibration averaging
  434.   gyro_average[0] = gyro_average[1] = gyro_average[2] = 0.0f;
  435.  
  436.   reset_calibration_session_flag = false;
  437. }
  438.  
  439. void turn_output_stream_on()
  440. {
  441.   output_stream_on = true;
  442.   digitalWrite(STATUS_LED_PIN, HIGH);
  443. }
  444.  
  445. void turn_output_stream_off()
  446. {
  447.   output_stream_on = false;
  448.   digitalWrite(STATUS_LED_PIN, LOW);
  449. }
  450.  
  451. // Blocks until another byte is available on serial port
  452. char readChar()
  453. {
  454.   while (Serial.available() < 1) {
  455.   } // Block
  456.   return Serial.read();
  457. }
  458.  
  459. void setup()
  460. {
  461.   // Init serial output
  462.   Serial.begin(OUTPUT__BAUD_RATE);
  463.  
  464.   // Init status LED
  465.   pinMode (STATUS_LED_PIN, OUTPUT);
  466.   digitalWrite(STATUS_LED_PIN, LOW);
  467.  
  468.   // Init sensors
  469.   delay(50);  // Give sensors enough time to start
  470.   I2C_Init();
  471.   Accel_Init();
  472.   Magn_Init();
  473.   Gyro_Init();
  474.  
  475.   // Read sensors, init DCM algorithm
  476.   delay(20);  // Give sensors enough time to collect data
  477.   reset_sensor_fusion();
  478.  
  479.   // Init output
  480. #if (OUTPUT__HAS_RN_BLUETOOTH == true) || (OUTPUT__STARTUP_STREAM_ON == false)
  481.   turn_output_stream_off();
  482. #else
  483.   turn_output_stream_on();
  484. #endif
  485. }
  486.  
  487. // Main loop
  488. void loop()
  489. {
  490.   // Read incoming control messages
  491.   if (Serial.available() >= 2)
  492.   {
  493.     if (Serial.read() == '#') // Start of new control message
  494.     {
  495.       int command = Serial.read(); // Commands
  496.       if (command == 'f') // request one output _f_rame
  497.         output_single_on = true;
  498.       else if (command == 's') // _s_ynch request
  499.       {
  500.         // Read ID
  501.         byte id[2];
  502.         id[0] = readChar();
  503.         id[1] = readChar();
  504.  
  505.         // Reply with synch message
  506.         Serial.print("#SYNCH");
  507.         Serial.write(id, 2);
  508.         Serial.println();
  509.       }
  510.       else if (command == 'o') // Set _o_utput mode
  511.       {
  512.         char output_param = readChar();
  513.         if (output_param == 'n')  // Calibrate _n_ext sensor
  514.         {
  515.           curr_calibration_sensor = (curr_calibration_sensor + 1) % 3;
  516.           reset_calibration_session_flag = true;
  517.         }
  518.         else if (output_param == 't') // Output angles as _t_ext
  519.           output_mode = OUTPUT__MODE_ANGLES_TEXT;
  520.         else if (output_param == 'b') // Output angles in _b_inary form
  521.           output_mode = OUTPUT__MODE_ANGLES_BINARY;
  522.         else if (output_param == 'c') // Go to _c_alibration mode
  523.         {
  524.           output_mode = OUTPUT__MODE_CALIBRATE_SENSORS;
  525.           reset_calibration_session_flag = true;
  526.         }
  527.         else if (output_param == 's') // Output _s_ensor values as text
  528.           output_mode = OUTPUT__MODE_SENSORS_TEXT;
  529.         else if (output_param == '0') // Disable continuous streaming output
  530.         {
  531.           turn_output_stream_off();
  532.           reset_calibration_session_flag = true;
  533.         }
  534.         else if (output_param == '1') // Enable continuous streaming output
  535.         {
  536.           reset_calibration_session_flag = true;
  537.           turn_output_stream_on();
  538.         }
  539.         else if (output_param == 'e') // _e_rror output settings
  540.         {
  541.           char error_param = readChar();
  542.           if (error_param == '0') output_errors = false;
  543.           else if (error_param == '1') output_errors = true;
  544.           else if (error_param == 'c') // get error count
  545.           {
  546.             Serial.print("#AMG-ERR:");
  547.             Serial.print(num_accel_errors);
  548.             Serial.print(",");
  549.             Serial.print(num_magn_errors);
  550.             Serial.print(",");
  551.             Serial.println(num_gyro_errors);
  552.           }
  553.         }
  554.       }
  555. #if OUTPUT__HAS_RN_BLUETOOTH == true
  556.       // Read messages from bluetooth module
  557.       // For this to work, the connect/disconnect message prefix of the module has to be set to "#".
  558.       else if (command == 'C') // Bluetooth "#CONNECT" message (does the same as "#o1")
  559.         turn_output_stream_on();
  560.       else if (command == 'D') // Bluetooth "#DISCONNECT" message (does the same as "#o0")
  561.         turn_output_stream_off();
  562. #endif // OUTPUT__HAS_RN_BLUETOOTH == true
  563.     }
  564.     else
  565.     {
  566.     } // Skip character
  567.   }
  568.  
  569.   // Time to read the sensors again?
  570.   if((millis() - timestamp) >= OUTPUT__DATA_INTERVAL)
  571.   {
  572.     timestamp_old = timestamp;
  573.     timestamp = millis();
  574.     if (timestamp > timestamp_old)
  575.       G_Dt = (float) (timestamp - timestamp_old) / 1000.0f; // Real time of loop run. We use this on the DCM algorithm (gyro integration time)
  576.     else G_Dt = 0;
  577.  
  578.     // Update sensor readings
  579.     read_sensors();
  580.  
  581.     if (output_mode == OUTPUT__MODE_CALIBRATE_SENSORS)  // We're in calibration mode
  582.     {
  583.       check_reset_calibration_session();  // Check if this session needs a reset
  584.       if (output_stream_on || output_single_on) output_calibration(curr_calibration_sensor);
  585.     }
  586.     else if (output_mode == OUTPUT__MODE_SENSORS_TEXT)
  587.     {
  588.       // Apply sensor calibration
  589.       compensate_sensor_errors();
  590.  
  591.       if (output_stream_on || output_single_on) output_sensors();
  592.     }
  593.     else
  594.     {
  595.       // Apply sensor calibration
  596.       compensate_sensor_errors();
  597.  
  598.       // Run DCM algorithm
  599.       Compass_Heading(); // Calculate magnetic heading
  600.       Matrix_update();
  601.       Normalize();
  602.       Drift_correction();
  603.       Euler_angles();
  604.  
  605.       if (output_stream_on || output_single_on) output_angles();
  606.     }
  607.  
  608.     output_single_on = false;
  609.  
  610. #if DEBUG__PRINT_LOOP_TIME == true
  611.     Serial.print("loop time (ms) = ");
  612.     Serial.println(millis() - timestamp);
  613. #endif
  614.   }
  615. #if DEBUG__PRINT_LOOP_TIME == true
  616.   else
  617.   {
  618.     Serial.println("waiting...");
  619.   }
  620. #endif
  621. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement