▲MPU-6050

MPU-6050은 X,Y,Z 3축의 자이로와 각속도, 센서의 온도를 알 수 있어 드론에 많이 사용되는 부품이다.

▲MPU6000, MPU6050의 차이점 

MPU-6050는 3.3V를 사용(완성된 보드는 5V를 인가해도 3.3V로 낮추는 회로가 있는 것 같다)

i2c 통신방식만 사용가능 

i2c이란? (자세한 설명은 첨부파일과 링크 참고 http://eslectures.blog.me/80137860924)

동기식 통신으로 SCL(Serial clock)과 SDA(serial data)로 2가닥의 선으로 이루어져있다. 

SCL은 IC 간의 동기를 맞추기위한 클럭을 발생하는 선이고,

SDA는 데이터를 보내는 선이다. (SPI는 송수신 선이 따로존재 데이터선만 2가닥)

이 SCL선과 SDA선은 모든 IC가 같이 사용하는데 특정 장치의 값을 받아올 때는 그 장치의 주소번지를 접근하여 데이터를 가져오게 된다.

때문에 CPU가 정보를 가져오기위한 오버헤드가 발생할 수있지만 회로적으로 간단하게 구성할 수 있는 장점이 있다.

그 주소를 AD에서 주소를 제공하게 되는데 MPU6050은 AD0를 하나만 가지고 있으므로 주소가 1bit => 2개 밖에 동시에 사용하지 못한다.


 

▲MPU6000의 내부정보(MPU6050도 비슷하게 사용함)

AUX_CL,AUX_DA은 결국 SCL,SDA에서 선을 따온 것이여서 사용하지 않아도 된다. 따라서 VCC와 GND, SCL, SDA 핀만 사용하면 된다.


아두이노 UNO기준 SCL, SDA핀이 있다.

 

▲아두이노 핀정보

위 그림을 처럼 A4,A5에 SDA, SCL이 있는데 내부 회로적으로 두 핀중에 아무거나 사용해도 된다.

 아두이노

MPU-6050 

 3.3V or 5V(MPU6050 내부적으로 전압을 낮춰주는 회로가 있음)

VCC 

 GND

GND 

 A4 or SDA

SDA 

 A5 or SCL

SCL 


'프로그래밍 > 아두이노' 카테고리의 다른 글

아두이노 드론 - 모터 PWM 제어  (0) 2016.07.09
MPU6050의 사용  (0) 2016.07.09
(아두이노)리미트 스위치  (0) 2016.07.09

아두이노의 analogWrite로 조절할 수도 있지만

아두이노의 Servo.h 라이브러리를 이용하여 DB모터의 PWM제어를 할 수 있다.

장점이라면 신호를 계속 만들어 주지않아도 되고 한번준 신호는 다시 신호를 줄때까지 같은 속도로 주기 때문에 쓰레딩을 할 필요가 없다.


Servo 설명

This library allows an Arduino board to control RC (hobby) servo motors. Servos have integrated gears and a shaft that can be precisely controlled. Standard servos allow the shaft to be positioned at various angles, usually between 0 and 180 degrees. Continuous rotation servos allow the rotation of the shaft to be set to various speeds.

 

The Servo library supports up to 12 motors on most Arduino boards and 48 on the Arduino Mega. On boards other than the Mega, use of the library disables analogWrite() (PWM) functionality on pins 9 and 10, whether or not there is a Servo on those pins. On the Mega, up to 12 servos can be used without interfering with PWM functionality; use of 12 to 23 motors will disable PWM on pins 11 and 12.


필자가 사용한 BLDC모터의 변속기는 Servo.write() 메소드 기준으로 30~150도의 신호에서 반응하고 약50부터 정회전을 하기 시작한다.

(옛날 ±60도의 신호를 받음)

역회전을 지원한다면 90도를 기준으로하여 값이 크거나 작으면 회전방향이 달라질 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<Servo.h>
 
const int MOTOR_PIN = 9;
Servo m_servo;
int iPWM;
void setup() {
  m_servo.attach(MOTOR_PIN);
  Serial.begin(9600);
}
 
void loop() {
  if(Serial.available() > 0){
    iPWM = Serial.read();
    if(iPWM>150)iPWM=150;
    if(iPWM<30)iPWM=30;
    m_servo.write(iPWM);
  }
}
cs

       ▲Simple source

'프로그래밍 > 아두이노' 카테고리의 다른 글

아두이노 드론 MPC6050  (0) 2016.07.09
MPU6050의 사용  (0) 2016.07.09
(아두이노)리미트 스위치  (0) 2016.07.09

아두이노 보드에 호환이 되는 자이로센서를 찾아본결과 MPU-6050이 적합하여 사용하게되었다.

MPU-6050은 3축 각속도, 3축 가속도, 온도를 측정할 수 있는 센서이다.


▲아두이노에 연결하는 방법 -출처 : 메카솔루션 -


표준 아두이노 보드는 클럭 시그널을 제공하는 SCL을 위해 아날로그 핀 5을 사용하고 데이터 전송을 위한 SDA을 위해서는 아날로그 핀 4을 사용한다. (Mega는 SDA는 디지털 핀 20 그리고 SCL은 핀 21을 사용한다.) 따라서, MPU-6050의 SCL은 아두이노의 A5, SDA는 아두이노의 A4에 연결하면 된다.

인터럽트가 필요하다면 각각의 아두이노보드에 내장된 인터럽트 핀을 이용하자.


/* 본 스케치는 arduino.cc의 JoghChi님이 작성하신 스케치입니다.*/

#include<Wire.h>


const int MPU=0x68;  //MPU 6050 의 I2C 기본 주소

int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;


void setup(){

  Wire.begin();      //Wire 라이브러리 초기화

  Wire.beginTransmission(MPU); //MPU로 데이터 전송 시작

  Wire.write(0x6B);  // PWR_MGMT_1 register

  Wire.write(0);     //MPU-6050 시작 모드로

  Wire.endTransmission(true); 

  Serial.begin(9600);

}


void loop(){

  Wire.beginTransmission(MPU);    //데이터 전송시작

  Wire.write(0x3B);               // register 0x3B (ACCEL_XOUT_H), 큐에 데이터 기록

  Wire.endTransmission(false);    //연결유지

  Wire.requestFrom(MPU,14,true);  //MPU에 데이터 요청

  //데이터 한 바이트 씩 읽어서 반환

  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)    

  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)

  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)

  Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)

  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)

  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)

  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

  

  //시리얼 모니터에 출력

  Serial.print("AcX = "); Serial.print(AcX);

  Serial.print(" | AcY = "); Serial.print(AcY);

  Serial.print(" | AcZ = "); Serial.print(AcZ);

  Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53);  

  Serial.print(" | GyX = "); Serial.print(GyX);

  Serial.print(" | GyY = "); Serial.print(GyY);

  Serial.print(" | GyZ = "); Serial.println(GyZ);

  delay(333);

}


순수한 센서값을 읽는 소스이다.

이 소스로 얻는 값을 바로 사용하기엔 신뢰성이 낮아서 필터를 사용하기로 했다.

필자는 칼만필터를 이용하기로 하여 칼만필터 라이브러리를 가져와 사용하기로 하였다.

https://github.com/TKJElectronics/KalmanFilter


/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.


 This software may be distributed and modified under the terms of the GNU

 General Public License version 2 (GPL2) as published by the Free Software

 Foundation and appearing in the file GPL2.TXT included in the packaging of

 this file. Please note that GPL2 Section 2[b] requires that all works based

 on this software must also be made publicly available under the terms of

 the GPL2 ("Copyleft").


 Contact information

 -------------------


 Kristian Lauszus, TKJ Electronics

 Web      :  http://www.tkjelectronics.com

 e-mail   :  kristianl@tkjelectronics.com

 */


#include <Wire.h>

#include <Kalman.h> // Source: https://github.com/TKJElectronics/KalmanFilter


#define RESTRICT_PITCH // Comment out to restrict roll to ±90deg instead - please read:http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf


Kalman kalmanX; // Create the Kalman instances

Kalman kalmanY;


/* IMU Data */

double accX, accY, accZ;

double gyroX, gyroY, gyroZ;

int16_t tempRaw;


double gyroXangle, gyroYangle; // Angle calculate using the gyro only

double compAngleX, compAngleY; // Calculated angle using a complementary filter

double kalAngleX, kalAngleY; // Calculated angle using a Kalman filter


uint32_t timer;

uint8_t i2cData[14]; // Buffer for I2C data


// TODO: Make calibration routine


void setup() {

  Serial.begin(115200);

  Wire.begin();

#if ARDUINO >= 157

  Wire.setClock(400000UL); // Set I2C frequency to 400kHz

#else

  TWBR = ((F_CPU / 400000UL) - 16) / 2; // Set I2C frequency to 400kHz

#endif


  i2cData[0] = 7; // Set the sample rate to 1000Hz - 8kHz/(7+1) = 1000Hz

  i2cData[1] = 0x00; // Disable FSYNC and set 260 Hz Acc filtering, 256 Hz Gyro filtering, 8 KHz sampling

  i2cData[2] = 0x00; // Set Gyro Full Scale Range to ±250deg/s

  i2cData[3] = 0x00; // Set Accelerometer Full Scale Range to ±2g

  while (i2cWrite(0x19, i2cData, 4, false)); // Write to all four registers at once

  while (i2cWrite(0x6B, 0x01, true)); // PLL with X axis gyroscope reference and disable sleep mode


  while (i2cRead(0x75, i2cData, 1));

  if (i2cData[0] != 0x68) { // Read "WHO_AM_I" register

    Serial.print(F("Error reading sensor"));

    while (1);

  }


  delay(100); // Wait for sensor to stabilize


  /* Set kalman and gyro starting angle */

  while (i2cRead(0x3B, i2cData, 6));

  accX = (i2cData[0] << 8) | i2cData[1];

  accY = (i2cData[2] << 8) | i2cData[3];

  accZ = (i2cData[4] << 8) | i2cData[5];


  // Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf eq. 25 and eq. 26

  // atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2

  // It is then converted from radians to degrees

#ifdef RESTRICT_PITCH // Eq. 25 and 26

  double roll  = atan2(accY, accZ) * RAD_TO_DEG;

  double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;

#else // Eq. 28 and 29

  double roll  = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;

  double pitch = atan2(-accX, accZ) * RAD_TO_DEG;

#endif


  kalmanX.setAngle(roll); // Set starting angle

  kalmanY.setAngle(pitch);

  gyroXangle = roll;

  gyroYangle = pitch;

  compAngleX = roll;

  compAngleY = pitch;


  timer = micros();

}


void loop() {

  /* Update all the values */

  while (i2cRead(0x3B, i2cData, 14));

  accX = ((i2cData[0] << 8) | i2cData[1]);

  accY = ((i2cData[2] << 8) | i2cData[3]);

  accZ = ((i2cData[4] << 8) | i2cData[5]);

  tempRaw = (i2cData[6] << 8) | i2cData[7];

  gyroX = (i2cData[8] << 8) | i2cData[9];

  gyroY = (i2cData[10] << 8) | i2cData[11];

  gyroZ = (i2cData[12] << 8) | i2cData[13];


  double dt = (double)(micros() - timer) / 1000000; // Calculate delta time

  timer = micros();


  // Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf eq. 25 and eq. 26

  // atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2

  // It is then converted from radians to degrees

#ifdef RESTRICT_PITCH // Eq. 25 and 26

  double roll  = atan2(accY, accZ) * RAD_TO_DEG;

  double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;

#else // Eq. 28 and 29

  double roll  = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;

  double pitch = atan2(-accX, accZ) * RAD_TO_DEG;

#endif


  double gyroXrate = gyroX / 131.0; // Convert to deg/s

  double gyroYrate = gyroY / 131.0; // Convert to deg/s


#ifdef RESTRICT_PITCH

  // This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees

  if ((roll < -90 && kalAngleX > 90) || (roll > 90 && kalAngleX < -90)) {

    kalmanX.setAngle(roll);

    compAngleX = roll;

    kalAngleX = roll;

    gyroXangle = roll;

  } else

    kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter


  if (abs(kalAngleX) > 90)

    gyroYrate = -gyroYrate; // Invert rate, so it fits the restriced accelerometer reading

  kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt);

#else

  // This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees

  if ((pitch < -90 && kalAngleY > 90) || (pitch > 90 && kalAngleY < -90)) {

    kalmanY.setAngle(pitch);

    compAngleY = pitch;

    kalAngleY = pitch;

    gyroYangle = pitch;

  } else

    kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt); // Calculate the angle using a Kalman filter


  if (abs(kalAngleY) > 90)

    gyroXrate = -gyroXrate; // Invert rate, so it fits the restriced accelerometer reading

  kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter

#endif


  gyroXangle += gyroXrate * dt; // Calculate gyro angle without any filter

  gyroYangle += gyroYrate * dt;

  //gyroXangle += kalmanX.getRate() * dt; // Calculate gyro angle using the unbiased rate

  //gyroYangle += kalmanY.getRate() * dt;


  compAngleX = 0.93 * (compAngleX + gyroXrate * dt) + 0.07 * roll; // Calculate the angle using a Complimentary filter

  compAngleY = 0.93 * (compAngleY + gyroYrate * dt) + 0.07 * pitch;


  // Reset the gyro angle when it has drifted too much

  if (gyroXangle < -180 || gyroXangle > 180)

    gyroXangle = kalAngleX;

  if (gyroYangle < -180 || gyroYangle > 180)

    gyroYangle = kalAngleY;


  /* Print Data */

#if 0 // Set to 1 to activate

  Serial.print(accX); Serial.print("\t");

  Serial.print(accY); Serial.print("\t");

  Serial.print(accZ); Serial.print("\t");


  Serial.print(gyroX); Serial.print("\t");

  Serial.print(gyroY); Serial.print("\t");

  Serial.print(gyroZ); Serial.print("\t");


  Serial.print("\t");

#endif


  Serial.print(roll); Serial.print("\t");

  Serial.print(gyroXangle); Serial.print("\t");

  Serial.print(compAngleX); Serial.print("\t");

  Serial.print(kalAngleX); Serial.print("\t");


  Serial.print("\t");


  Serial.print(pitch); Serial.print("\t");

  Serial.print(gyroYangle); Serial.print("\t");

  Serial.print(compAngleY); Serial.print("\t");

  Serial.print(kalAngleY); Serial.print("\t");


#if 0 // Set to 1 to print the temperature

  Serial.print("\t");


  double temperature = (double)tempRaw / 340.0 + 36.53;

  Serial.print(temperature); Serial.print("\t");

#endif


  Serial.print("\r\n");

  delay(2);

}

 

칼만필터를 적용해서 해본결과 움직임에 따른 값의 변화 속도는 나름대로 괜찮았다.

그런데 아두이노 내에서 연산을 하는 부분이 많아 다른 것을 찾아보던중 MPU6050이 DMP(Digital Motion Processing)기능을 제공해준다고 하여 찾아보았다.

이 기능은 센서 내에서 연산을 하고 그것을 버퍼에 저장하여 아두이노가 값을 가져가는 것으로 아두이노에서는 연산을 할 필요가 없어지게된다.


http://www.i2cdevlib.com/

이 기능을 사용하려면 i2Cdevlib에서 제공하는 라이브러리와 MPU6050모델의 라이브러리를 추가하면 사용할 수 있다. (Arduino Processing을 이용하여 그래픽으로 구현하는 소스도 제공해준다)

 

// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0)

// 6/21/2012 by Jeff Rowberg <jeff@rowberg.net>

// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib

//

// Changelog:

//      2013-05-08 - added seamless Fastwire support

//                 - added note about gyro calibration

//      2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error

//      2012-06-20 - improved FIFO overflow handling and simplified read process

//      2012-06-19 - completely rearranged DMP initialization code and simplification

//      2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly

//      2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING

//      2012-06-05 - add gravity-compensated initial reference frame acceleration output

//                 - add 3D math helper file to DMP6 example sketch

//                 - add Euler output and Yaw/Pitch/Roll output formats

//      2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee)

//      2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250

//      2012-05-30 - basic DMP initialization working


/* ============================================

I2Cdev device library code is placed under the MIT license

Copyright (c) 2012 Jeff Rowberg


Permission is hereby granted, free of charge, to any person obtaining a copy

of this software and associated documentation files (the "Software"), to deal

in the Software without restriction, including without limitation the rights

to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

copies of the Software, and to permit persons to whom the Software is

furnished to do so, subject to the following conditions:


The above copyright notice and this permission notice shall be included in

all copies or substantial portions of the Software.


THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

THE SOFTWARE.

===============================================

*/


// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files

// for both classes must be in the include path of your project

#include "I2Cdev.h"


#include "MPU6050_6Axis_MotionApps20.h"

//#include "MPU6050.h" // not necessary if using MotionApps include file


// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation

// is used in I2Cdev.h

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE

    #include "Wire.h"

#endif


// class default I2C address is 0x68

// specific I2C addresses may be passed as a parameter here

// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)

// AD0 high = 0x69

MPU6050 mpu;

//MPU6050 mpu(0x69); // <-- use for AD0 high


/* =========================================================================

   NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch

   depends on the MPU-6050's INT pin being connected to the Arduino's

   external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is

   digital I/O pin 2.

 * ========================================================================= */


/* =========================================================================

   NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error

   when using Serial.write(buf, len). The Teapot output uses this method.

   The solution requires a modification to the Arduino USBAPI.h file, which

   is fortunately simple, but annoying. This will be fixed in the next IDE

   release. For more info, see these links:


   http://arduino.cc/forum/index.php/topic,109987.0.html

   http://code.google.com/p/arduino/issues/detail?id=958

 * ========================================================================= */




// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual

// quaternion components in a [w, x, y, z] format (not best for parsing

// on a remote host such as Processing or something though)

//#define OUTPUT_READABLE_QUATERNION


// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles

// (in degrees) calculated from the quaternions coming from the FIFO.

// Note that Euler angles suffer from gimbal lock (for more info, see

// http://en.wikipedia.org/wiki/Gimbal_lock)

//#define OUTPUT_READABLE_EULER


// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/

// pitch/roll angles (in degrees) calculated from the quaternions coming

// from the FIFO. Note this also requires gravity vector calculations.

// Also note that yaw/pitch/roll angles suffer from gimbal lock (for

// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)

#define OUTPUT_READABLE_YAWPITCHROLL //아두이노에서 사용시 주석해제


// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration

// components with gravity removed. This acceleration reference frame is

// not compensated for orientation, so +X is always +X according to the

// sensor, just without the effects of gravity. If you want acceleration

// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.

//#define OUTPUT_READABLE_REALACCEL


// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration

// components with gravity removed and adjusted for the world frame of

// reference (yaw is relative to initial orientation, since no magnetometer

// is present in this case). Could be quite handy in some cases.

//#define OUTPUT_READABLE_WORLDACCEL


// uncomment "OUTPUT_TEAPOT" if you want output that matches the

// format used for the InvenSense teapot demo

//#define OUTPUT_TEAPOT                  //Procssing을 사용할 시 주석해제




#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)

bool blinkState = false;


// MPU control/status vars

bool dmpReady = false;  // set true if DMP init was successful

uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU

uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)

uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)

uint16_t fifoCount;     // count of all bytes currently in FIFO

uint8_t fifoBuffer[64]; // FIFO storage buffer


// orientation/motion vars

Quaternion q;           // [w, x, y, z]         quaternion container

VectorInt16 aa;         // [x, y, z]            accel sensor measurements

VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements

VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements

VectorFloat gravity;    // [x, y, z]            gravity vector

float euler[3];         // [psi, theta, phi]    Euler angle container

float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector


// packet structure for InvenSense teapot demo

uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };




// ================================================================

// ===               INTERRUPT DETECTION ROUTINE                ===

// ================================================================


volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high

void dmpDataReady() {

    mpuInterrupt = true;

}




// ================================================================

// ===                      INITIAL SETUP                       ===

// ================================================================


void setup() {

    // join I2C bus (I2Cdev library doesn't do this automatically)

    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE

        Wire.begin();

        TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)

    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE

        Fastwire::setup(400, true);

    #endif


    // initialize serial communication

    // (115200 chosen because it is required for Teapot Demo output, but it's

    // really up to you depending on your project)

    Serial.begin(115200);

    while (!Serial); // wait for Leonardo enumeration, others continue immediately


    // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio

    // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to

    // the baud timing being too misaligned with processor ticks. You must use

    // 38400 or slower in these cases, or use some kind of external separate

    // crystal solution for the UART timer.


    // initialize device

    Serial.println(F("Initializing I2C devices..."));

    mpu.initialize();


    // verify connection

    Serial.println(F("Testing device connections..."));

    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));


    // wait for ready

    Serial.println(F("\nSend any character to begin DMP programming and demo: "));

    while (Serial.available() && Serial.read()); // empty buffer

    while (!Serial.available());                 // wait for data

    while (Serial.available() && Serial.read()); // empty buffer again


    // load and configure the DMP

    Serial.println(F("Initializing DMP..."));

    devStatus = mpu.dmpInitialize();


    // supply your own gyro offsets here, scaled for min sensitivity

    mpu.setXGyroOffset(220);

    mpu.setYGyroOffset(76);

    mpu.setZGyroOffset(-85);

    mpu.setZAccelOffset(1788); // 1688 factory default for my test chip


    // make sure it worked (returns 0 if so)

    if (devStatus == 0) {

        // turn on the DMP, now that it's ready

        Serial.println(F("Enabling DMP..."));

        mpu.setDMPEnabled(true);


        // enable Arduino interrupt detection

        Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));

        attachInterrupt(0, dmpDataReady, RISING);

        mpuIntStatus = mpu.getIntStatus();


        // set our DMP Ready flag so the main loop() function knows it's okay to use it

        Serial.println(F("DMP ready! Waiting for first interrupt..."));

        dmpReady = true;


        // get expected DMP packet size for later comparison

        packetSize = mpu.dmpGetFIFOPacketSize();

    } else {

        // ERROR!

        // 1 = initial memory load failed

        // 2 = DMP configuration updates failed

        // (if it's going to break, usually the code will be 1)

        Serial.print(F("DMP Initialization failed (code "));

        Serial.print(devStatus);

        Serial.println(F(")"));

    }


    // configure LED for output

    pinMode(LED_PIN, OUTPUT);

}




// ================================================================

// ===                    MAIN PROGRAM LOOP                     ===

// ================================================================


void loop() {

    // if programming failed, don't try to do anything

    if (!dmpReady) return;


    // wait for MPU interrupt or extra packet(s) available

    while (!mpuInterrupt && fifoCount < packetSize) {

        // other program behavior stuff here

        // .

        // .

        // .

        // if you are really paranoid you can frequently test in between other

        // stuff to see if mpuInterrupt is true, and if so, "break;" from the

        // while() loop to immediately process the MPU data

        // .

        // .

        // .

    }


    // reset interrupt flag and get INT_STATUS byte

    mpuInterrupt = false;

    mpuIntStatus = mpu.getIntStatus();


    // get current FIFO count

    fifoCount = mpu.getFIFOCount();


    // check for overflow (this should never happen unless our code is too inefficient)

    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {

        // reset so we can continue cleanly

        mpu.resetFIFO();

        Serial.println(F("FIFO overflow!"));


    // otherwise, check for DMP data ready interrupt (this should happen frequently)

    } else if (mpuIntStatus & 0x02) {

        // wait for correct available data length, should be a VERY short wait

        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();


        // read a packet from FIFO

        mpu.getFIFOBytes(fifoBuffer, packetSize);

        

        // track FIFO count here in case there is > 1 packet available

        // (this lets us immediately read more without waiting for an interrupt)

        fifoCount -= packetSize;


        #ifdef OUTPUT_READABLE_QUATERNION

            // display quaternion values in easy matrix form: w x y z

            mpu.dmpGetQuaternion(&q, fifoBuffer);

            Serial.print("quat\t");

            Serial.print(q.w);

            Serial.print("\t");

            Serial.print(q.x);

            Serial.print("\t");

            Serial.print(q.y);

            Serial.print("\t");

            Serial.println(q.z);

        #endif


        #ifdef OUTPUT_READABLE_EULER

            // display Euler angles in degrees

            mpu.dmpGetQuaternion(&q, fifoBuffer);

            mpu.dmpGetEuler(euler, &q);

            Serial.print("euler\t");

            Serial.print(euler[0] * 180/M_PI);

            Serial.print("\t");

            Serial.print(euler[1] * 180/M_PI);

            Serial.print("\t");

            Serial.println(euler[2] * 180/M_PI);

        #endif


        #ifdef OUTPUT_READABLE_YAWPITCHROLL

            // display Euler angles in degrees

            mpu.dmpGetQuaternion(&q, fifoBuffer);

            mpu.dmpGetGravity(&gravity, &q);

            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);

            Serial.print("ypr\t");

            Serial.print(ypr[0] * 180/M_PI);

            Serial.print("\t");

            Serial.print(ypr[1] * 180/M_PI);

            Serial.print("\t");

            Serial.println(ypr[2] * 180/M_PI);

        #endif


        #ifdef OUTPUT_READABLE_REALACCEL

            // display real acceleration, adjusted to remove gravity

            mpu.dmpGetQuaternion(&q, fifoBuffer);

            mpu.dmpGetAccel(&aa, fifoBuffer);

            mpu.dmpGetGravity(&gravity



Arduino.zip

datasheet.pdf

I2Cdev.zip


'프로그래밍 > 아두이노' 카테고리의 다른 글

아두이노 드론 MPC6050  (0) 2016.07.09
아두이노 드론 - 모터 PWM 제어  (0) 2016.07.09
(아두이노)리미트 스위치  (0) 2016.07.09
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
n.c : 누를때 HIGH
n.o : 누를때 LOW
c :   나머지 한쪽(그라운드에 물리거나 파워거나)
 
const int led=13,button=12;   //핀번호
int buttonchack=LOW;           
 
void setup(){
  pinMode(led,OUTPUT);      //led Pin number
  pinMode(button,INPUT);    //limit switch Pin number
}
 
void loop(){
  buttonchack=digitalRead(button);
  
  if(buttonchack==HIGH){                        //HIGH값이 들어오면 13번 값에 HIGH를 줌
    digitalWrite(led,HIGH);
  }
  else{                                                  //LOW값이 들어오면 13번 값에 LOW를 줌
    digitalWrite(led,LOW);
  }
}
cs


'프로그래밍 > 아두이노' 카테고리의 다른 글

아두이노 드론 MPC6050  (0) 2016.07.09
아두이노 드론 - 모터 PWM 제어  (0) 2016.07.09
MPU6050의 사용  (0) 2016.07.09

+ Recent posts