


라이브러리는 아래 링크에서 다운로드하고 아두이노 프로그램 메뉴에서 스케치->라이브러리 포함하기->.ZIP 라이브러리 추가를 누르고, 파일선택창이 나오면 다운받은 라이브러리 파일을 선택하시면 됩니다.
라이브러리
소스코드
아래는 소스코드입니다. 아두이노 IDE에 붙여넣기 하여 컴파일하고 업로드합니다.
#include <LiquidCrystal.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
LiquidCrystal lcd(7,8,9,10,11,12);//RS,E,DB4,DB5,DB6,DB7
MPU6050 mpu;
#define INTERRUPT_PIN 2 // 인터럽트 핀
#define LED_PIN 13 // 아두이노 내장 LED
bool blinkState = false;
// MPU6050 제어 및 상태표시 변수
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
// 요롤피치 계산용
Quaternion q; // [w, x, y, z] 4원법 변수
VectorFloat gravity; // [x, y, z] 중력 벡터
float ypr[3]; // [yaw, pitch, roll] 요롤피치 변수
int intCount;
volatile bool mpuInterrupt = false; // MPU6050 인터럽트 발생유무 확인용
// 인터럽트 루틴
void dmpDataReady() {
mpuInterrupt = true;
}
void setup() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
lcd.begin(16,2);
intCount = 0;
Serial.begin(9600);
while (!Serial);
//초기화
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
pinMode(INTERRUPT_PIN, INPUT);
//MPU6050과 연결상태 확인
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
//요롤피치 산출을 위한 DMP(Digital Motion Processor) 초기화
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
//옵셋 설정
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1688);
//정상동작여부 확인 0이면 정상
if (devStatus == 0) {
//DMP 활성화
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
//아두이노 인터럽트 활성화
Serial.print(F("Enabling interrupt detection (Arduino external interrupt "));
Serial.print(digitalPinToInterrupt(INTERRUPT_PIN));
Serial.println(F(")..."));
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
//DMP 대기상태
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
// DMP패킷 크기 비교
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(")"));
}
//LED 포트 출력으로 설정
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// 오류시 종료
if (!dmpReady) return;
//MPU6050 데이터 대기
while (!mpuInterrupt && fifoCount < packetSize) {
if (mpuInterrupt && fifoCount < packetSize) {
// try to get out of the infinite loop
fifoCount = mpu.getFIFOCount();
}
// 사용자 프로그램은 여기에 작성
// .
}
// 인터럽트 플래그를 리셋
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 & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) {
// reset so we can continue cleanly
mpu.resetFIFO();
fifoCount = mpu.getFIFOCount();
Serial.println(F("FIFO overflow!"));
// otherwise, check for DMP data ready interrupt (this should happen frequently)
} else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) {
// 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;
if(intCount++ > 20) //LCD표시 주기 조절용
{
intCount = 0;
showYPR();
}
}
}
void showYPR()
{
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
lcd.clear();
lcd.print(" Y P R");
lcd.setCursor(0,1);
lcd.print(ypr[0] * 180/M_PI,0);
lcd.setCursor(6,1);
lcd.print(ypr[1] * 180/M_PI,0);
lcd.setCursor(12,1);
lcd.print(ypr[2] * 180/M_PI,0);
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);
// 데이터 1번 표시할 때마다 LED 상태를 바꿈
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
} 