範例九-讀取陀螺儀資料
I2C 介面只需兩根 SCL/SDA 腳位,就可以接不同的裝置 (裝置間 address 要不同)
-> 使用陀螺儀時,請先校正後再填入校正值。本範例不含校正的程式.
// 範例九:
// I2C 同時插上 SSD1306 及 MPU6050 陀螺儀,讓陀螺儀資料顯示在 OLED 上
// (陀螺儀使用時,請先校正)
// 使用 I2C 腳位 GPIO21/22
// 需要的 library : I2Cdev,MPU6050_6Axis_MotionApps20,U8g2lib
// FB : https://www.facebook.com/mason.chen.1420
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h" //https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050
#include "U8g2lib.h"
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
MPU6050 mpu;
int MPUOffsets[6] = {0, 0, 0, 0, 0, 0}; //更新 MPU6050 的校正值
#define M_PI 3.14159265;
#define debug
// 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
VectorFloat gravity; // [x, y, z] gravity vector
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
bool run_status = true;
double input, out_y,out_p,out_r;
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}
/** Get latest byte from FIFO buffer no matter how much time has passed.
=== GetCurrentFIFOPacket ===
================================================================
Returns 1) when data was received
0) when no valid data is available
================================================================ */
uint8_t GetCurrentFIFOPacket(uint8_t *data, uint8_t length) { // overflow proof
uint16_t fifoC;
if ((fifoC = mpu.getFIFOCount()) > length) {
while (fifoC > length) { // Shrink down to 1 packet
mpu.getFIFOBytes(data, length);
fifoC--;
}
if ((fifoC = mpu.getFIFOCount()) > length) {
while (fifoC > length) { // We got more data while we were shrinking
mpu.getFIFOBytes(data, length);
fifoC--;
}
if ((fifoC = mpu.getFIFOCount()) > length) {
while (fifoC > length) {// we need to be sure, but this shouldn't happen... Shrink some more
mpu.getFIFOBytes(data, length);
fifoC--;
}
}
}
}
while (fifoC && (fifoC < length)) fifoC = mpu.getFIFOCount(); //Finish loading the packet!
if (fifoC == length) {
mpu.getFIFOBytes(data, length);
return 1;
}
return 0;
}
void setup() {
#ifdef debug
Serial.begin(115200);
#endif
// join I2C bus (I2Cdev library doesn't do this automatically)
Wire.begin();
Wire.setClock(400000);
u8g2.begin();
u8g2.setFlipMode(1); // 畫面轉 180 度
u8g2.setFont(u8g2_font_6x10_tf);
u8g2.setFontRefHeightExtendedText();
u8g2.setDrawColor(1);
u8g2.setFontPosTop();
u8g2.setFontDirection(0);
u8g2.setFont(u8g2_font_8x13_mf);
u8g2.firstPage();
do {
u8g2.drawStr(0, 0, String("MPU test!").c_str());
u8g2.drawLine(0, 11, 60, 11);
} while (u8g2.nextPage());
#ifdef debug
Serial.println(F("Initializing I2C devices..."));
#endif
mpu.initialize();
// verify connection
#ifdef debug
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
#endif
// load and configure the DMP
devStatus = mpu.dmpInitialize();
// supply your own gyro offsets here, scaled for min sensitivity
mpu.setXAccelOffset(MPUOffsets[0]);
mpu.setYAccelOffset(MPUOffsets[1]);
mpu.setZAccelOffset(MPUOffsets[2]);
mpu.setXGyroOffset(MPUOffsets[3]);
mpu.setYGyroOffset(MPUOffsets[4]);
mpu.setZGyroOffset(MPUOffsets[5]);
if (devStatus == 0) {
#ifdef debug
Serial.println(F("Enabling DMP..."));
#endif
mpu.setDMPEnabled(true);
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
#ifdef debug
Serial.print("DMP Initialization failed ");
#endif
}
}
void loop() {
if (! GetCurrentFIFOPacket(fifoBuffer, packetSize))return;
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer); //get value for q
mpu.dmpGetGravity(&gravity, &q); //get value for gravity
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); //get value for ypr
out_y = ypr[0] * 180/M_PI;
out_p = ypr[1] * 180/M_PI;
out_r = ypr[2] * 180/M_PI;
#ifdef debug
Serial.print("Yaw =");
Serial.print(out_y);
Serial.print(",Pitch =");
Serial.print(out_p);
Serial.print(",Roll =");
Serial.println(out_r);
#endif
u8g2.firstPage();
do {
u8g2.drawStr(0, 0, "Yaw =");
u8g2.drawStr(60, 0, String(out_y).c_str());
u8g2.drawStr(0, 16, "Pitch =");
u8g2.drawStr(60, 16, String(out_p).c_str());
u8g2.drawStr(0, 32, "Roll =");
u8g2.drawStr(60, 32, String(out_r).c_str());
} while (u8g2.nextPage());
}