Guest User

MPU-6050 and 3 servos, stable version

a guest
Oct 10th, 2014
581
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.84 KB | None | 0 0
  1. //Servo
  2. #include <Servo.h>
  3.  
  4. Servo myservoY; // Roll
  5. Servo myservoX; // Pitch
  6. Servo myservoZ; // Yaw
  7.  
  8. // I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
  9. // for both classes must be in the include path of your project
  10. #include "I2Cdev.h"
  11.  
  12. #include "MPU6050_6Axis_MotionApps20.h"
  13. //#include "MPU6050.h" // not necessary if using MotionApps include file
  14.  
  15. // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
  16. // is used in I2Cdev.h
  17. #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  18. #include "Wire.h"
  19. #endif
  20.  
  21. // class default I2C address is 0x68
  22. // specific I2C addresses may be passed as a parameter here
  23. // AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
  24. // AD0 high = 0x69
  25. MPU6050 mpu;
  26. //MPU6050 mpu(0x69); // <-- use for AD0 high
  27.  
  28. /* =========================================================================
  29. NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
  30. depends on the MPU-6050's INT pin being connected to the Arduino's
  31. external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is
  32. digital I/O pin 2.
  33. * ========================================================================= */
  34.  
  35. /* =========================================================================
  36. NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error
  37. when using Serial.write(buf, len). The Teapot output uses this method.
  38. The solution requires a modification to the Arduino USBAPI.h file, which
  39. is fortunately simple, but annoying. This will be fixed in the next IDE
  40. release. For more info, see these links:
  41.  
  42. http://arduino.cc/forum/index.php/topic,109987.0.html
  43. http://code.google.com/p/arduino/issues/detail?id=958
  44. * ========================================================================= */
  45.  
  46.  
  47.  
  48. // uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/
  49. // pitch/roll angles (in degrees) calculated from the quaternions coming
  50. // from the FIFO. Note this also requires gravity vector calculations.
  51. // Also note that yaw/pitch/roll angles suffer from gimbal lock (for
  52. // more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)
  53. #define OUTPUT_READABLE_YAWPITCHROLL
  54.  
  55. #define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
  56. bool blinkState = false;
  57.  
  58. // MPU control/status vars
  59. bool dmpReady = false; // set true if DMP init was successful
  60. uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
  61. uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
  62. uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
  63. uint16_t fifoCount; // count of all bytes currently in FIFO
  64. uint8_t fifoBuffer[64]; // FIFO storage buffer
  65.  
  66. // orientation/motion vars
  67. Quaternion q; // [w, x, y, z] quaternion container
  68. VectorInt16 aa; // [x, y, z] accel sensor measurements
  69. VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
  70. VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
  71. VectorFloat gravity; // [x, y, z] gravity vector
  72. float euler[3]; // [psi, theta, phi] Euler angle container
  73. float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
  74.  
  75. // packet structure for InvenSense teapot demo
  76. uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
  77.  
  78.  
  79.  
  80. // ================================================================
  81. // === INTERRUPT DETECTION ROUTINE ===
  82. // ================================================================
  83.  
  84. volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
  85. void dmpDataReady() {
  86. mpuInterrupt = true;
  87. }
  88.  
  89.  
  90.  
  91. // ================================================================
  92. // === INITIAL SETUP ===
  93. // ================================================================
  94.  
  95. void setup() {
  96. // join I2C bus (I2Cdev library doesn't do this automatically)
  97. #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  98. Wire.begin();
  99. TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
  100. #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  101. Fastwire::setup(400, true);
  102. #endif
  103.  
  104. //Attach servo
  105.  
  106. myservoY.attach(9); // Attach Y servo to pin 9
  107. myservoX.attach(10);// Attach X servo to pin 10
  108. myservoZ.attach(11); // Attach Z servo to pin 11
  109.  
  110. // initialize serial communication
  111. // (115200 chosen because it is required for Teapot Demo output, but it's
  112. // really up to you depending on your project)
  113. Serial.begin(115200);
  114. while (!Serial); // wait for Leonardo enumeration, others continue immediately
  115.  
  116. // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio
  117. // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to
  118. // the baud timing being too misaligned with processor ticks. You must use
  119. // 38400 or slower in these cases, or use some kind of external separate
  120. // crystal solution for the UART timer.
  121.  
  122. // initialize device
  123. Serial.println(F("Initializing I2C devices..."));
  124. mpu.initialize();
  125.  
  126. // verify connection
  127. Serial.println(F("Testing device connections..."));
  128. Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
  129. /*
  130. // wait for ready
  131. Serial.println(F("\nSend any character to begin DMP programming and demo: "));
  132. while (Serial.available() && Serial.read()); // empty buffer
  133. while (!Serial.available()); // wait for data
  134. while (Serial.available() && Serial.read()); // empty buffer again
  135. */
  136. // load and configure the DMP
  137. Serial.println(F("Initializing DMP..."));
  138. devStatus = mpu.dmpInitialize();
  139.  
  140. // supply your own gyro offsets here, scaled for min sensitivity
  141. mpu.setXGyroOffset(49);
  142. mpu.setYGyroOffset(-26);
  143. mpu.setZGyroOffset(13);
  144. mpu.setZAccelOffset(1459); // 1688 factory default for my test chip
  145.  
  146. // make sure it worked (returns 0 if so)
  147. if (devStatus == 0) {
  148. // turn on the DMP, now that it's ready
  149. Serial.println(F("Enabling DMP..."));
  150. mpu.setDMPEnabled(true);
  151.  
  152. // enable Arduino interrupt detection
  153. Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
  154. attachInterrupt(0, dmpDataReady, RISING);
  155. mpuIntStatus = mpu.getIntStatus();
  156.  
  157. // set our DMP Ready flag so the main loop() function knows it's okay to use it
  158. Serial.println(F("DMP ready! Waiting for first interrupt..."));
  159. dmpReady = true;
  160.  
  161. // get expected DMP packet size for later comparison
  162. packetSize = mpu.dmpGetFIFOPacketSize();
  163. } else {
  164. // ERROR!
  165. // 1 = initial memory load failed
  166. // 2 = DMP configuration updates failed
  167. // (if it's going to break, usually the code will be 1)
  168. Serial.print(F("DMP Initialization failed (code "));
  169. Serial.print(devStatus);
  170. Serial.println(F(")"));
  171. }
  172.  
  173. // configure LED for output
  174. pinMode(LED_PIN, OUTPUT);
  175. }
  176.  
  177.  
  178.  
  179. // ================================================================
  180. // === MAIN PROGRAM LOOP ===
  181. // ================================================================
  182.  
  183. void loop() {
  184. // if programming failed, don't try to do anything
  185. if (!dmpReady) return;
  186.  
  187. // wait for MPU interrupt or extra packet(s) available
  188. while (!mpuInterrupt && fifoCount < packetSize) {
  189. // other program behavior stuff here
  190. // .
  191. // .
  192. // .
  193. // if you are really paranoid you can frequently test in between other
  194. // stuff to see if mpuInterrupt is true, and if so, "break;" from the
  195. // while() loop to immediately process the MPU data
  196. // .
  197. // .
  198. // .
  199. }
  200.  
  201. // reset interrupt flag and get INT_STATUS byte
  202. mpuInterrupt = false;
  203. mpuIntStatus = mpu.getIntStatus();
  204.  
  205. // get current FIFO count
  206. fifoCount = mpu.getFIFOCount();
  207.  
  208. // check for overflow (this should never happen unless our code is too inefficient)
  209. if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
  210. // reset so we can continue cleanly
  211. mpu.resetFIFO();
  212. Serial.println(F("FIFO overflow!"));
  213.  
  214. // otherwise, check for DMP data ready interrupt (this should happen frequently)
  215. } else if (mpuIntStatus & 0x02) {
  216. // wait for correct available data length, should be a VERY short wait
  217. while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
  218.  
  219. // read a packet from FIFO
  220. mpu.getFIFOBytes(fifoBuffer, packetSize);
  221.  
  222. // track FIFO count here in case there is > 1 packet available
  223. // (this lets us immediately read more without waiting for an interrupt)
  224. fifoCount -= packetSize;
  225.  
  226. #ifdef OUTPUT_READABLE_YAWPITCHROLL
  227. // display Euler angles in degrees
  228. mpu.dmpGetQuaternion(&q, fifoBuffer);
  229. mpu.dmpGetGravity(&gravity, &q);
  230. mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
  231. Serial.print("ypr\t");
  232. Serial.print(ypr[0] * 180/M_PI);
  233. myservoZ.write(int(ypr[0] * -180/M_PI)+90); // Rotation around Z
  234. Serial.print("\t");
  235. Serial.print(ypr[1] * 180/M_PI);
  236. myservoY.write(int(ypr[1] * 180/M_PI)+90); // Rotation around Y
  237. Serial.print("\t");
  238. Serial.println(ypr[2] * 180/M_PI);
  239. myservoX.write(int(ypr[2] * 180/M_PI)+90); // Rotation around X
  240. #endif
  241.  
  242.  
  243. // blink LED to indicate activity
  244. blinkState = !blinkState;
  245. digitalWrite(LED_PIN, blinkState);
  246. }
  247.  
  248. }
Advertisement
Add Comment
Please, Sign In to add comment