Advertisement
ROSALES_RUIZ

CONTROL E INVERSION DE GIRO DE UN MOTOR CD CON SENSOR 9 DOF

Nov 26th, 2015
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 27.53 KB | None | 0 0
  1. //INSTITUTO POLITECNICO NACIONAL
  2. //ESCUELA SUPERIOR DE INGENIERIA MECANICA Y ELECTRICA
  3. //UNIDAD ZACATENCO
  4. //
  5. //ING. EN CONTROL Y AUTOMATIZACION
  6. //ASIGNATURA: INTERFASES Y MICROCONTROLADORES
  7. //M.C LUIS ARTURO BENITEZ VELAZQUEZ
  8. //GRUPO 7AM1
  9. //
  10. //AUTORES:
  11. //ROSALES HERNANDEZ JOSE EDUARDO
  12. //RUIZ ESTUDILLO MARIA FERNANDA
  13. //***********************************************************************************
  14. //***********************************************************************************
  15. //PRACTICA NO. 5
  16. //PROGRAMA: CONTROL E INVERSION DE GIRO DE UN MOTOR CD CON SENSOR STICK 9DOF
  17. /***************************************************************************************************************
  18. * Razor AHRS Firmware v1.4.2
  19. * 9 Degree of Measurement Attitude and Heading Reference System
  20. * for Sparkfun "9DOF Razor IMU" (SEN-10125 and SEN-10736)
  21. * and "9DOF Sensor Stick" (SEN-10183, 10321 and SEN-10724)
  22. *
  23. * Released under GNU GPL (General Public License) v3.0
  24. * Copyright (C) 2013 Peter Bartz [http://ptrbrtz.net]
  25. * Copyright (C) 2011-2012 Quality & Usability Lab, Deutsche Telekom Laboratories, TU Berlin
  26. *
  27. * Infos, updates, bug reports, contributions and feedback:
  28. *     https://github.com/ptrbrtz/razor-9dof-ahrs
  29. *
  30. *
  31. * History:
  32. *   * Original code (http://code.google.com/p/sf9domahrs/) by Doug Weibel and Jose Julio,
  33. *     based on ArduIMU v1.5 by Jordi Munoz and William Premerlani, Jose Julio and Doug Weibel. Thank you!
  34. *
  35. *   * Updated code (http://groups.google.com/group/sf_9dof_ahrs_update) by David Malik (david.zsolt.malik@gmail.com)
  36. *     for new Sparkfun 9DOF Razor hardware (SEN-10125).
  37. *
  38. *   * Updated and extended by Peter Bartz (peter-bartz@gmx.de):
  39. *     * v1.3.0
  40. *       * Cleaned up, streamlined and restructured most of the code to make it more comprehensible.
  41. *       * Added sensor calibration (improves precision and responsiveness a lot!).
  42. *       * Added binary yaw/pitch/roll output.
  43. *       * Added basic serial command interface to set output modes/calibrate sensors/synch stream/etc.
  44. *       * Added support to synch automatically when using Rovering Networks Bluetooth modules (and compatible).
  45. *       * Wrote new easier to use test program (using Processing).
  46. *       * Added support for new version of "9DOF Razor IMU": SEN-10736.
  47. *       --> The output of this code is not compatible with the older versions!
  48. *       --> A Processing sketch to test the tracker is available.
  49. *     * v1.3.1
  50. *       * Initializing rotation matrix based on start-up sensor readings -> orientation OK right away.
  51. *       * Adjusted gyro low-pass filter and output rate settings.
  52. *     * v1.3.2
  53. *       * Adapted code to work with new Arduino 1.0 (and older versions still).
  54. *     * v1.3.3
  55. *       * Improved synching.
  56. *     * v1.4.0
  57. *       * Added support for SparkFun "9DOF Sensor Stick" (versions SEN-10183, SEN-10321 and SEN-10724).
  58. *     * v1.4.1
  59. *       * Added output modes to read raw and/or calibrated sensor data in text or binary format.
  60. *       * Added static magnetometer soft iron distortion compensation
  61. *     * v1.4.2
  62. *       * (No core firmware changes)
  63. *
  64. * TODOs:
  65. *   * Allow optional use of EEPROM for storing and reading calibration values.
  66. *   * Use self-test and temperature-compensation features of the sensors.
  67. ***************************************************************************************************************/
  68.  
  69. /*
  70.   "9DOF Razor IMU" hardware versions: SEN-10125 and SEN-10736
  71.  
  72.   ATMega328@3.3V, 8MHz
  73.  
  74.   ADXL345  : Accelerometer
  75.   HMC5843  : Magnetometer on SEN-10125
  76.   HMC5883L : Magnetometer on SEN-10736
  77.   ITG-3200 : Gyro
  78.  
  79.   Arduino IDE : Select board "Arduino Pro or Pro Mini (3.3v, 8Mhz) w/ATmega328"
  80. */
  81.  
  82. /*
  83.   "9DOF Sensor Stick" hardware versions: SEN-10183, SEN-10321 and SEN-10724
  84.  
  85.   ADXL345  : Accelerometer
  86.   HMC5843  : Magnetometer on SEN-10183 and SEN-10321
  87.   HMC5883L : Magnetometer on SEN-10724
  88.   ITG-3200 : Gyro
  89. */
  90.  
  91. /*
  92.   Axis definition (differs from definition printed on the board!):
  93.     X axis pointing forward (towards the short edge with the connector holes)
  94.     Y axis pointing to the right
  95.     and Z axis pointing down.
  96.    
  97.   Positive yaw   : clockwise
  98.   Positive roll  : right wing down
  99.   Positive pitch : nose up
  100.  
  101.   Transformation order: first yaw then pitch then roll.
  102. */
  103.  
  104. /*
  105.   Serial commands that the firmware understands:
  106.  
  107.   "#o<params>" - Set OUTPUT mode and parameters. The available options are:
  108.  
  109.       // Streaming output
  110.       "#o0" - DISABLE continuous streaming output. Also see #f below.
  111.       "#o1" - ENABLE continuous streaming output.
  112.      
  113.       // Angles output
  114.       "#ob" - Output angles in BINARY format (yaw/pitch/roll as binary float, so one output frame
  115.               is 3x4 = 12 bytes long).
  116.       "#ot" - Output angles in TEXT format (Output frames have form like "#YPR=-142.28,-5.38,33.52",
  117.               followed by carriage return and line feed [\r\n]).
  118.      
  119.       // Sensor calibration
  120.       "#oc" - Go to CALIBRATION output mode.
  121.       "#on" - When in calibration mode, go on to calibrate NEXT sensor.
  122.      
  123.       // Sensor data output
  124.       "#osct" - Output CALIBRATED SENSOR data of all 9 axes in TEXT format.
  125.                 One frame consist of three lines - one for each sensor: acc, mag, gyr.
  126.       "#osrt" - Output RAW SENSOR data of all 9 axes in TEXT format.
  127.                 One frame consist of three lines - one for each sensor: acc, mag, gyr.
  128.       "#osbt" - Output BOTH raw and calibrated SENSOR data of all 9 axes in TEXT format.
  129.                 One frame consist of six lines - like #osrt and #osct combined (first RAW, then CALIBRATED).
  130.                 NOTE: This is a lot of number-to-text conversion work for the little 8MHz chip on the Razor boards.
  131.                 In fact it's too much and an output frame rate of 50Hz can not be maintained. #osbb.
  132.       "#oscb" - Output CALIBRATED SENSOR data of all 9 axes in BINARY format.
  133.                 One frame consist of three 3x3 float values = 36 bytes. Order is: acc x/y/z, mag x/y/z, gyr x/y/z.
  134.       "#osrb" - Output RAW SENSOR data of all 9 axes in BINARY format.
  135.                 One frame consist of three 3x3 float values = 36 bytes. Order is: acc x/y/z, mag x/y/z, gyr x/y/z.
  136.       "#osbb" - Output BOTH raw and calibrated SENSOR data of all 9 axes in BINARY format.
  137.                 One frame consist of 2x36 = 72 bytes - like #osrb and #oscb combined (first RAW, then CALIBRATED).
  138.      
  139.       // Error message output        
  140.       "#oe0" - Disable ERROR message output.
  141.       "#oe1" - Enable ERROR message output.
  142.    
  143.    
  144.   "#f" - Request one output frame - useful when continuous output is disabled and updates are
  145.          required in larger intervals only. Though #f only requests one reply, replies are still
  146.          bound to the internal 20ms (50Hz) time raster. So worst case delay that #f can add is 19.99ms.
  147.          
  148.          
  149.   "#s<xy>" - Request synch token - useful to find out where the frame boundaries are in a continuous
  150.          binary stream or to see if tracker is present and answering. The tracker will send
  151.          "#SYNCH<xy>\r\n" in response (so it's possible to read using a readLine() function).
  152.          x and y are two mandatory but arbitrary bytes that can be used to find out which request
  153.          the answer belongs to.
  154.          
  155.          
  156.   ("#C" and "#D" - Reserved for communication with optional Bluetooth module.)
  157.  
  158.   Newline characters are not required. So you could send "#ob#o1#s", which
  159.   would set binary output mode, enable continuous streaming output and request
  160.   a synch token all at once.
  161.  
  162.   The status LED will be on if streaming output is enabled and off otherwise.
  163.  
  164.   Byte order of binary output is little-endian: least significant byte comes first.
  165. */
  166.  
  167.  
  168.  
  169. /*****************************************************************/
  170. /*********** USER SETUP AREA! Set your options here! *************/
  171. /*****************************************************************/
  172. //LIBRARY LCD
  173. #include "LiquidCrystal.h"
  174.  
  175.  
  176. // HARDWARE OPTIONS
  177. /*****************************************************************/
  178. // Select your hardware here by uncommenting one line!
  179. //#define HW__VERSION_CODE 10125 // SparkFun "9DOF Razor IMU" version "SEN-10125" (HMC5843 magnetometer)
  180. //#define HW__VERSION_CODE 10736 // SparkFun "9DOF Razor IMU" version "SEN-10736" (HMC5883L magnetometer)
  181. //#define HW__VERSION_CODE 10183 // SparkFun "9DOF Sensor Stick" version "SEN-10183" (HMC5843 magnetometer)
  182. //#define HW__VERSION_CODE 10321 // SparkFun "9DOF Sensor Stick" version "SEN-10321" (HMC5843 magnetometer)
  183. #define HW__VERSION_CODE 10724 // SparkFun "9DOF Sensor Stick" version "SEN-10724" (HMC5883L magnetometer)
  184.  
  185.  
  186. // OUTPUT OPTIONS
  187. /*****************************************************************/
  188. // Set your serial port baud rate used to send out data here!
  189. #define OUTPUT__BAUD_RATE 9600
  190.  
  191. // Sensor data output interval in milliseconds
  192. // This may not work, if faster than 20ms (=50Hz)
  193. // Code is tuned for 20ms, so better leave it like that
  194. #define OUTPUT__DATA_INTERVAL 20  // in milliseconds
  195.  
  196. // Output mode definitions (do not change)
  197. #define OUTPUT__MODE_CALIBRATE_SENSORS 0 // Outputs sensor min/max values as text for manual calibration
  198. #define OUTPUT__MODE_ANGLES 1 // Outputs yaw/pitch/roll in degrees
  199. #define OUTPUT__MODE_SENSORS_CALIB 2 // Outputs calibrated sensor values for all 9 axes
  200. #define OUTPUT__MODE_SENSORS_RAW 3 // Outputs raw (uncalibrated) sensor values for all 9 axes
  201. #define OUTPUT__MODE_SENSORS_BOTH 4 // Outputs calibrated AND raw sensor values for all 9 axes
  202. // Output format definitions (do not change)
  203. #define OUTPUT__FORMAT_TEXT 0 // Outputs data as text
  204. #define OUTPUT__FORMAT_BINARY 1 // Outputs data as binary float
  205.  
  206. // Select your startup output mode and format here!
  207. int output_mode = OUTPUT__MODE_ANGLES;
  208. int output_format = OUTPUT__FORMAT_TEXT;
  209.  
  210. // Select if serial continuous streaming output is enabled per default on startup.
  211. #define OUTPUT__STARTUP_STREAM_ON true  // true or false
  212.  
  213. // If set true, an error message will be output if we fail to read sensor data.
  214. // Message format: "!ERR: reading <sensor>", followed by "\r\n".
  215. boolean output_errors = true;  // true or false
  216.  
  217. // Bluetooth
  218. // You can set this to true, if you have a Rovering Networks Bluetooth Module attached.
  219. // The connect/disconnect message prefix of the module has to be set to "#".
  220. // (Refer to manual, it can be set like this: SO,#)
  221. // When using this, streaming output will only be enabled as long as we're connected. That way
  222. // receiver and sender are synchronzed easily just by connecting/disconnecting.
  223. // It is not necessary to set this! It just makes life easier when writing code for
  224. // the receiving side. The Processing test sketch also works without setting this.
  225. // NOTE: When using this, OUTPUT__STARTUP_STREAM_ON has no effect!
  226. #define OUTPUT__HAS_RN_BLUETOOTH false  // true or false
  227.  
  228.  
  229. // SENSOR CALIBRATION
  230. /*****************************************************************/
  231. // How to calibrate? Read the tutorial at http://dev.qu.tu-berlin.de/projects/sf-razor-9dof-ahrs
  232. // Put MIN/MAX and OFFSET readings for your board here!
  233. // Accelerometer
  234. // "accel x,y,z (min/max) = X_MIN/X_MAX  Y_MIN/Y_MAX  Z_MIN/Z_MAX"
  235. #define ACCEL_X_MIN ((float) -138)
  236. #define ACCEL_X_MAX ((float) 58)
  237. #define ACCEL_Y_MIN ((float) -355)
  238. #define ACCEL_Y_MAX ((float) 272)
  239. #define ACCEL_Z_MIN ((float) -223)
  240. #define ACCEL_Z_MAX ((float) 370)
  241.  
  242. // Magnetometer (standard calibration mode)
  243. // "magn x,y,z (min/max) = X_MIN/X_MAX  Y_MIN/Y_MAX  Z_MIN/Z_MAX"
  244. #define MAGN_X_MIN ((float) -22)
  245. #define MAGN_X_MAX ((float) 96)
  246. #define MAGN_Y_MIN ((float) 155)
  247. #define MAGN_Y_MAX ((float) 303)
  248. #define MAGN_Z_MIN ((float) -263)
  249. #define MAGN_Z_MAX ((float) -114)
  250.  
  251. // Magnetometer (extended calibration mode)
  252. // Uncommend to use extended magnetometer calibration (compensates hard & soft iron errors)
  253. //#define CALIBRATION__MAGN_USE_EXTENDED true
  254. //const float magn_ellipsoid_center[3] = {0, 0, 0};
  255. //const float magn_ellipsoid_transform[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
  256.  
  257. // Gyroscope
  258. // "gyro x,y,z (current/average) = .../OFFSET_X  .../OFFSET_Y  .../OFFSET_Z
  259. #define GYRO_AVERAGE_OFFSET_X ((float) -28.32)
  260. #define GYRO_AVERAGE_OFFSET_Y ((float) 3.16)
  261. #define GYRO_AVERAGE_OFFSET_Z ((float) 5.08)
  262.  
  263. /*
  264. // Calibration example:
  265.  
  266. // "accel x,y,z (min/max) = -277.00/264.00  -256.00/278.00  -299.00/235.00"
  267. #define ACCEL_X_MIN ((float) -277)
  268. #define ACCEL_X_MAX ((float) 264)
  269. #define ACCEL_Y_MIN ((float) -256)
  270. #define ACCEL_Y_MAX ((float) 278)
  271. #define ACCEL_Z_MIN ((float) -299)
  272. #define ACCEL_Z_MAX ((float) 235)
  273.  
  274. // "magn x,y,z (min/max) = -511.00/581.00  -516.00/568.00  -489.00/486.00"
  275. //#define MAGN_X_MIN ((float) -511)
  276. //#define MAGN_X_MAX ((float) 581)
  277. //#define MAGN_Y_MIN ((float) -516)
  278. //#define MAGN_Y_MAX ((float) 568)
  279. //#define MAGN_Z_MIN ((float) -489)
  280. //#define MAGN_Z_MAX ((float) 486)
  281.  
  282. // Extended magn
  283. #define CALIBRATION__MAGN_USE_EXTENDED true
  284. const float magn_ellipsoid_center[3] = {91.5, -13.5, -48.1};
  285. const float magn_ellipsoid_transform[3][3] = {{0.902, -0.00354, 0.000636}, {-0.00354, 0.9, -0.00599}, {0.000636, -0.00599, 1}};
  286.  
  287. // Extended magn (with Sennheiser HD 485 headphones)
  288. //#define CALIBRATION__MAGN_USE_EXTENDED true
  289. //const float magn_ellipsoid_center[3] = {72.3360, 23.0954, 53.6261};
  290. //const float magn_ellipsoid_transform[3][3] = {{0.879685, 0.000540833, -0.0106054}, {0.000540833, 0.891086, -0.0130338}, {-0.0106054, -0.0130338, 0.997494}};
  291.  
  292. //"gyro x,y,z (current/average) = -40.00/-42.05  98.00/96.20  -18.00/-18.36"
  293. #define GYRO_AVERAGE_OFFSET_X ((float) -42.05)
  294. #define GYRO_AVERAGE_OFFSET_Y ((float) 96.20)
  295. #define GYRO_AVERAGE_OFFSET_Z ((float) -18.36)
  296. */
  297.  
  298.  
  299. // DEBUG OPTIONS
  300. /*****************************************************************/
  301. // When set to true, gyro drift correction will not be applied
  302. #define DEBUG__NO_DRIFT_CORRECTION false
  303. // Print elapsed time after each I/O loop
  304. #define DEBUG__PRINT_LOOP_TIME false
  305.  
  306.  
  307. /*****************************************************************/
  308. /****************** END OF USER SETUP AREA!  *********************/
  309. /*****************************************************************/
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320. // Check if hardware version code is defined
  321. #ifndef HW__VERSION_CODE
  322.   // Generate compile error
  323.   #error YOU HAVE TO SELECT THE HARDWARE YOU ARE USING! See "HARDWARE OPTIONS" in "USER SETUP AREA" at top of Razor_AHRS.ino!
  324. #endif
  325.  
  326. #include <Wire.h>
  327.  
  328. // Sensor calibration scale and offset values
  329. #define ACCEL_X_OFFSET ((ACCEL_X_MIN + ACCEL_X_MAX) / 2.0f)
  330. #define ACCEL_Y_OFFSET ((ACCEL_Y_MIN + ACCEL_Y_MAX) / 2.0f)
  331. #define ACCEL_Z_OFFSET ((ACCEL_Z_MIN + ACCEL_Z_MAX) / 2.0f)
  332. #define ACCEL_X_SCALE (GRAVITY / (ACCEL_X_MAX - ACCEL_X_OFFSET))
  333. #define ACCEL_Y_SCALE (GRAVITY / (ACCEL_Y_MAX - ACCEL_Y_OFFSET))
  334. #define ACCEL_Z_SCALE (GRAVITY / (ACCEL_Z_MAX - ACCEL_Z_OFFSET))
  335.  
  336. #define MAGN_X_OFFSET ((MAGN_X_MIN + MAGN_X_MAX) / 2.0f)
  337. #define MAGN_Y_OFFSET ((MAGN_Y_MIN + MAGN_Y_MAX) / 2.0f)
  338. #define MAGN_Z_OFFSET ((MAGN_Z_MIN + MAGN_Z_MAX) / 2.0f)
  339. #define MAGN_X_SCALE (100.0f / (MAGN_X_MAX - MAGN_X_OFFSET))
  340. #define MAGN_Y_SCALE (100.0f / (MAGN_Y_MAX - MAGN_Y_OFFSET))
  341. #define MAGN_Z_SCALE (100.0f / (MAGN_Z_MAX - MAGN_Z_OFFSET))
  342.  
  343.  
  344. // Gain for gyroscope (ITG-3200)
  345. #define GYRO_GAIN 0.06957 // Same gain on all axes
  346. #define GYRO_SCALED_RAD(x) (x * TO_RAD(GYRO_GAIN)) // Calculate the scaled gyro readings in radians per second
  347.  
  348. // DCM parameters
  349. #define Kp_ROLLPITCH 0.02f
  350. #define Ki_ROLLPITCH 0.00002f
  351. #define Kp_YAW 1.2f
  352. #define Ki_YAW 0.00002f
  353.  
  354. // Stuff
  355. #define STATUS_LED_PIN 13  // Pin number of status LED
  356. #define GRAVITY 256.0f // "1G reference" used for DCM filter and accelerometer calibration
  357. #define TO_RAD(x) (x * 0.01745329252)  // *pi/180
  358. #define TO_DEG(x) (x * 57.2957795131)  // *180/pi
  359. //LCD variables
  360. LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
  361. byte charGrado[8] = {//creando 'º'
  362.   0b01110,
  363.   0b01010,
  364.   0b01110,
  365.   0b00000,
  366.   0b00000,
  367.   0b00000,
  368.   0b00000,
  369.   0b00000
  370. };
  371. // Sensor variables
  372. float accel[3];  // Actually stores the NEGATED acceleration (equals gravity, if board not moving).
  373. float accel_min[3];
  374. float accel_max[3];
  375.  
  376. float magnetom[3];
  377. float magnetom_min[3];
  378. float magnetom_max[3];
  379. float magnetom_tmp[3];
  380.  
  381. float gyro[3];
  382. float gyro_average[3];
  383. int gyro_num_samples = 0;
  384.  
  385. // DCM variables
  386. float MAG_Heading;
  387. float Accel_Vector[3]= {0, 0, 0}; // Store the acceleration in a vector
  388. float Gyro_Vector[3]= {0, 0, 0}; // Store the gyros turn rate in a vector
  389. float Omega_Vector[3]= {0, 0, 0}; // Corrected Gyro_Vector data
  390. float Omega_P[3]= {0, 0, 0}; // Omega Proportional correction
  391. float Omega_I[3]= {0, 0, 0}; // Omega Integrator
  392. float Omega[3]= {0, 0, 0};
  393. float errorRollPitch[3] = {0, 0, 0};
  394. float errorYaw[3] = {0, 0, 0};
  395. float DCM_Matrix[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
  396. float Update_Matrix[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
  397. float Temporary_Matrix[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
  398.  
  399. // Euler angles
  400. float yaw;
  401. float pitch;
  402. float roll;
  403.  
  404. // DCM timing in the main loop
  405. unsigned long timestamp;
  406. unsigned long timestamp_old;
  407. float G_Dt; // Integration time for DCM algorithm
  408.  
  409. // More output-state variables
  410. boolean output_stream_on;
  411. boolean output_single_on;
  412. int curr_calibration_sensor = 0;
  413. boolean reset_calibration_session_flag = true;
  414. int num_accel_errors = 0;
  415. int num_magn_errors = 0;
  416. int num_gyro_errors = 0;
  417.  
  418. void read_sensors() {
  419.   Read_Gyro(); // Read gyroscope
  420.   Read_Accel(); // Read accelerometer
  421.   Read_Magn(); // Read magnetometer
  422. }
  423.  
  424. // Read every sensor and record a time stamp
  425. // Init DCM with unfiltered orientation
  426. // TODO re-init global vars?
  427. void reset_sensor_fusion() {
  428.   float temp1[3];
  429.   float temp2[3];
  430.   float xAxis[] = {1.0f, 0.0f, 0.0f};
  431.  
  432.   read_sensors();
  433.   timestamp = millis();
  434.  
  435.   // GET PITCH
  436.   // Using y-z-plane-component/x-component of gravity vector
  437.   pitch = -atan2(accel[0], sqrt(accel[1] * accel[1] + accel[2] * accel[2]));
  438.    
  439.   // GET ROLL
  440.   // Compensate pitch of gravity vector
  441.   Vector_Cross_Product(temp1, accel, xAxis);
  442.   Vector_Cross_Product(temp2, xAxis, temp1);
  443.   // Normally using x-z-plane-component/y-component of compensated gravity vector
  444.   // roll = atan2(temp2[1], sqrt(temp2[0] * temp2[0] + temp2[2] * temp2[2]));
  445.   // Since we compensated for pitch, x-z-plane-component equals z-component:
  446.   roll = atan2(temp2[1], temp2[2]);
  447.  
  448.   // GET YAW
  449.   Compass_Heading();
  450.   yaw = MAG_Heading;
  451.  
  452.   // Init rotation matrix
  453.   init_rotation_matrix(DCM_Matrix, yaw, pitch, roll);
  454. }
  455.  
  456. // Apply calibration to raw sensor readings
  457. void compensate_sensor_errors() {
  458.     // Compensate accelerometer error
  459.     accel[0] = (accel[0] - ACCEL_X_OFFSET) * ACCEL_X_SCALE;
  460.     accel[1] = (accel[1] - ACCEL_Y_OFFSET) * ACCEL_Y_SCALE;
  461.     accel[2] = (accel[2] - ACCEL_Z_OFFSET) * ACCEL_Z_SCALE;
  462.  
  463.     // Compensate magnetometer error
  464. #if CALIBRATION__MAGN_USE_EXTENDED == true
  465.     for (int i = 0; i < 3; i++)
  466.       magnetom_tmp[i] = magnetom[i] - magn_ellipsoid_center[i];
  467.     Matrix_Vector_Multiply(magn_ellipsoid_transform, magnetom_tmp, magnetom);
  468. #else
  469.     magnetom[0] = (magnetom[0] - MAGN_X_OFFSET) * MAGN_X_SCALE;
  470.     magnetom[1] = (magnetom[1] - MAGN_Y_OFFSET) * MAGN_Y_SCALE;
  471.     magnetom[2] = (magnetom[2] - MAGN_Z_OFFSET) * MAGN_Z_SCALE;
  472. #endif
  473.  
  474.     // Compensate gyroscope error
  475.     gyro[0] -= GYRO_AVERAGE_OFFSET_X;
  476.     gyro[1] -= GYRO_AVERAGE_OFFSET_Y;
  477.     gyro[2] -= GYRO_AVERAGE_OFFSET_Z;
  478. }
  479.  
  480. // Reset calibration session if reset_calibration_session_flag is set
  481. void check_reset_calibration_session()
  482. {
  483.   // Raw sensor values have to be read already, but no error compensation applied
  484.  
  485.   // Reset this calibration session?
  486.   if (!reset_calibration_session_flag) return;
  487.  
  488.   // Reset acc and mag calibration variables
  489.   for (int i = 0; i < 3; i++) {
  490.     accel_min[i] = accel_max[i] = accel[i];
  491.     magnetom_min[i] = magnetom_max[i] = magnetom[i];
  492.   }
  493.  
  494.   // Reset gyro calibration variables
  495.   gyro_num_samples = 0;  // Reset gyro calibration averaging
  496.   gyro_average[0] = gyro_average[1] = gyro_average[2] = 0.0f;
  497.  
  498.   reset_calibration_session_flag = false;
  499. }
  500.  
  501. void turn_output_stream_on()
  502. {
  503.   output_stream_on = true;
  504.   digitalWrite(STATUS_LED_PIN, HIGH);
  505. }
  506.  
  507. void turn_output_stream_off()
  508. {
  509.   output_stream_on = false;
  510.   digitalWrite(STATUS_LED_PIN, LOW);
  511. }
  512.  
  513. // Blocks until another byte is available on serial port
  514. char readChar()
  515. {
  516.   while (Serial.available() < 1) { } // Block
  517.   return Serial.read();
  518. }
  519.  
  520. void setup()
  521. {
  522. //inicializacion de la LCD
  523. lcd.begin(16, 2);
  524. lcd.setCursor(0,0);
  525. lcd.print("IPN    ESIME ZAC");
  526. lcd.setCursor(0,1);
  527. lcd.print("    SEGWAY    ");
  528. delay (3000);
  529. lcd.clear();
  530. lcd.createChar(0, charGrado);
  531.  
  532.   // Init serial output
  533.   Serial.begin(OUTPUT__BAUD_RATE);
  534.  
  535.   // Init status LED
  536.   pinMode (STATUS_LED_PIN, OUTPUT);
  537.   digitalWrite(STATUS_LED_PIN, LOW);
  538.  
  539.   // Init sensors
  540.   delay(50);  // Give sensors enough time to start
  541.   I2C_Init();
  542.   Accel_Init();
  543.   Magn_Init();
  544.   Gyro_Init();
  545.  
  546.   // Read sensors, init DCM algorithm
  547.   delay(20);  // Give sensors enough time to collect data
  548.   reset_sensor_fusion();
  549.  
  550.   // Init output
  551. #if (OUTPUT__HAS_RN_BLUETOOTH == true) || (OUTPUT__STARTUP_STREAM_ON == false)
  552.   turn_output_stream_off();
  553. #else
  554.   turn_output_stream_on();
  555. #endif
  556.  
  557.   pinMode(9,OUTPUT);
  558.   pinMode(10,OUTPUT);
  559.  
  560. }
  561.  
  562. // Main loop
  563. void loop()
  564. {
  565.   // Read incoming control messages
  566.   if (Serial.available() >= 2)
  567.   {
  568.     if (Serial.read() == '#') // Start of new control message
  569.     {
  570.       int command = Serial.read(); // Commands
  571.       if (command == 'f') // request one output _f_rame
  572.         output_single_on = true;
  573.       else if (command == 's') // _s_ynch request
  574.       {
  575.         // Read ID
  576.         byte id[2];
  577.         id[0] = readChar();
  578.         id[1] = readChar();
  579.        
  580.         // Reply with synch message
  581.         Serial.print("#SYNCH");
  582.         Serial.write(id, 2);
  583.         Serial.println();
  584.       }
  585.       else if (command == 'o') // Set _o_utput mode
  586.       {
  587.         char output_param = readChar();
  588.         if (output_param == 'n')  // Calibrate _n_ext sensor
  589.         {
  590.           curr_calibration_sensor = (curr_calibration_sensor + 1) % 3;
  591.           reset_calibration_session_flag = true;
  592.         }
  593.         else if (output_param == 't') // Output angles as _t_ext
  594.         {
  595.           output_mode = OUTPUT__MODE_ANGLES;
  596.           output_format = OUTPUT__FORMAT_TEXT;
  597.         }
  598.         else if (output_param == 'b') // Output angles in _b_inary format
  599.         {
  600.           output_mode = OUTPUT__MODE_ANGLES;
  601.           output_format = OUTPUT__FORMAT_BINARY;
  602.         }
  603.         else if (output_param == 'c') // Go to _c_alibration mode
  604.         {
  605.           output_mode = OUTPUT__MODE_CALIBRATE_SENSORS;
  606.           reset_calibration_session_flag = true;
  607.         }
  608.         else if (output_param == 's') // Output _s_ensor values
  609.         {
  610.           char values_param = readChar();
  611.           char format_param = readChar();
  612.           if (values_param == 'r')  // Output _r_aw sensor values
  613.             output_mode = OUTPUT__MODE_SENSORS_RAW;
  614.           else if (values_param == 'c')  // Output _c_alibrated sensor values
  615.             output_mode = OUTPUT__MODE_SENSORS_CALIB;
  616.           else if (values_param == 'b')  // Output _b_oth sensor values (raw and calibrated)
  617.             output_mode = OUTPUT__MODE_SENSORS_BOTH;
  618.  
  619.           if (format_param == 't') // Output values as _t_text
  620.             output_format = OUTPUT__FORMAT_TEXT;
  621.           else if (format_param == 'b') // Output values in _b_inary format
  622.             output_format = OUTPUT__FORMAT_BINARY;
  623.         }
  624.         else if (output_param == '0') // Disable continuous streaming output
  625.         {
  626.           turn_output_stream_off();
  627.           reset_calibration_session_flag = true;
  628.         }
  629.         else if (output_param == '1') // Enable continuous streaming output
  630.         {
  631.           reset_calibration_session_flag = true;
  632.           turn_output_stream_on();
  633.         }
  634.         else if (output_param == 'e') // _e_rror output settings
  635.         {
  636.           char error_param = readChar();
  637.           if (error_param == '0') output_errors = false;
  638.           else if (error_param == '1') output_errors = true;
  639.           else if (error_param == 'c') // get error count
  640.           {
  641.             Serial.print("#AMG-ERR:");
  642.             Serial.print(num_accel_errors); Serial.print(",");
  643.             Serial.print(num_magn_errors); Serial.print(",");
  644.             Serial.println(num_gyro_errors);
  645.           }
  646.         }
  647.       }
  648. #if OUTPUT__HAS_RN_BLUETOOTH == true
  649.       // Read messages from bluetooth module
  650.       // For this to work, the connect/disconnect message prefix of the module has to be set to "#".
  651.       else if (command == 'C') // Bluetooth "#CONNECT" message (does the same as "#o1")
  652.         turn_output_stream_on();
  653.       else if (command == 'D') // Bluetooth "#DISCONNECT" message (does the same as "#o0")
  654.         turn_output_stream_off();
  655. #endif // OUTPUT__HAS_RN_BLUETOOTH == true
  656.     }
  657.     else
  658.     { } // Skip character
  659.   }
  660.  
  661.   // Time to read the sensors again?
  662.   if((millis() - timestamp) >= OUTPUT__DATA_INTERVAL)
  663.   {
  664.     timestamp_old = timestamp;
  665.     timestamp = millis();
  666.     if (timestamp > timestamp_old)
  667.       G_Dt = (float) (timestamp - timestamp_old) / 1000.0f; // Real time of loop run. We use this on the DCM algorithm (gyro integration time)
  668.     else G_Dt = 0;
  669.  
  670.     // Update sensor readings
  671.     read_sensors();
  672.    
  673.     float roll2;
  674.     float roll3;
  675.    
  676.     if(roll>0)
  677.     {
  678.       roll2=40+((roll/3.1416)*(255-40));
  679.       analogWrite(9,roll2);
  680. //      digitalWrite(9,HIGH);
  681.     }
  682.     else
  683.       analogWrite(9,0);
  684. //        digitalWrite(9,LOW);
  685.     if(roll<0)
  686.     {
  687.       roll3=255+(((roll+3.1416)/3.1416)*(40-255));
  688.       analogWrite(10,roll3);
  689. //      digitalWrite(10,HIGH);
  690.     }
  691.     else
  692.       analogWrite(10,0);
  693. //digitalWrite(10,LOW);
  694.     LCD();
  695.  
  696.     if (output_mode == OUTPUT__MODE_CALIBRATE_SENSORS)  // We're in calibration mode
  697.     {
  698.       check_reset_calibration_session();  // Check if this session needs a reset
  699.       if (output_stream_on || output_single_on) output_calibration(curr_calibration_sensor);
  700.     }
  701.     else if (output_mode == OUTPUT__MODE_ANGLES)  // Output angles
  702.     {
  703.       // Apply sensor calibration
  704.       compensate_sensor_errors();
  705.    
  706.       // Run DCM algorithm
  707.       Compass_Heading(); // Calculate magnetic heading
  708.       Matrix_update();
  709.       Normalize();
  710.       Drift_correction();
  711.       Euler_angles();
  712.      
  713.       if (output_stream_on || output_single_on) output_angles();
  714.     }
  715.     else  // Output sensor values
  716.     {      
  717.       if (output_stream_on || output_single_on) output_sensors();
  718.     }
  719.    
  720.     output_single_on = false;
  721.    
  722. #if DEBUG__PRINT_LOOP_TIME == true
  723.     Serial.print("loop time (ms) = ");
  724.     Serial.println(millis() - timestamp);
  725. #endif
  726.   }
  727. #if DEBUG__PRINT_LOOP_TIME == true
  728.   else
  729.   {
  730.     Serial.println("waiting...");
  731.   }
  732. #endif
  733.                                                                                                                                                                                                            
  734. }
  735.  
  736. void LCD()
  737. {
  738.   float roll4;
  739.   roll4=roll*180/3.1416;
  740. lcd.setCursor(0,0);
  741. lcd.print("SENSOR:");
  742. for(int i=7;i<=16;i++)
  743. {
  744.   lcd.setCursor(i,0);
  745.   lcd.print(" ");
  746. }
  747. lcd.setCursor(7,0);
  748. lcd.print(roll4);
  749. lcd.setCursor(15,0);
  750. lcd.write(byte(0)); //caracter 'º'
  751. lcd.setCursor(0,1);
  752. lcd.print("SENTIDO:");
  753. for(int i=9;i<=16;i++)
  754. {
  755.   lcd.setCursor(i,1);
  756.   lcd.print(" ");
  757. }
  758. if(roll<0)
  759. {
  760.   lcd.setCursor(9,1);
  761.   lcd.print("IZQ.");
  762. }else
  763. {
  764.   lcd.setCursor(9,1);
  765.   lcd.print("DERECHA");
  766. }
  767. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement