Arduino如何获取MPU6050的姿态数据

Arduino如何获取MPU6050的姿态数据

其实代码也是在Github开源的项目,但是自己确实也是理解了许久,先给出自己翻译以及稍微修改的代码,这代码是可以直接使用的(无需修改就行可以用,串口打印数据),关于接线我就不做过多的说明了,注意arduino nano的SCL是A5,SDA是A4就行,我用的是Arduino MEGA 2560,上面有SCL,SDA专门标注有。
准备:I2Cdev、MPU6050库(这里附送的是我发在网上的资源,大家也可找开源的地址了)
注意:MPU6050用最新的,不然下面的 CalibrateAccel、、 那个三个函数用不了(会报错找不到),当然我发的这个不会有错。。。有点黄婆卖瓜——自卖自夸了,,,哈哈哈

#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#include <EEPROM.h>

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

MPU6050 mpu;

#define OUTPUT_READABLE_QUATERNION  //定义后串口才可打印四元数
#define OUTPUT_READABLE_YAWPITCHROLL //定义后串口才可打印 偏航/俯仰/横摇容器
#define OUTPUT_READABLE_GRAVITY

#define INTERRUPT_PIN 2  // 中断引脚D2
#define LED_PIN 13 // led灯
#define MPUCALIB 80           // 16字节数组
//缩写
#define PT(s) Serial.print(s)  //makes life easier
#define PTL(s) Serial.println(s)
#define PTF(s) Serial.print(F(s))//trade flash memory for dynamic memory with F() function
#define PTLF(s) Serial.println(F(s))

bool blinkState = false;

//MPU控制/状态变量
bool dmpReady = false;  // set true if DMP init was successful            如果DMP init成功,则设置为true
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU    保留来自MPU的实际中断状态字节
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)每次设备操作后返回状态(0 =成功,!0 =错误)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes) 预期的DMP包大小(默认为42字节)
uint16_t fifoCount;     // count of all bytes currently in FIFO           当前FIFO中所有字节的计数
uint8_t fifoBuffer[64]; // FIFO storage buffer                            FIFO存储缓冲区

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 偏航/俯仰/横摇容器

//中断检测程序
volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high 指示主控板中断引脚是否过高
void dmpDataReady() {
    mpuInterrupt = true;
}

int EEPROMReadInt(int p_address)
{
  byte lowByte = EEPROM.read(p_address);
  byte highByte = EEPROM.read(p_address + 1);
  return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}

//初始化设置
void setup()
{
    //加入I2C总线(I2Cdev库不会自动执行此操作)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
        //Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties //400千赫I2C时钟。如果有编译困难,注释这行
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif
    
    //初始化串行通讯
    Serial.begin(57600);
    while (!Serial); 

    //初始化设备
    Serial.println(F("Initializing I2C devices..."));
    mpu.initialize();             //初始化MPU6050
    pinMode(INTERRUPT_PIN, INPUT);//设置中断引脚D2的模式为输入

    // 验证连接
    Serial.println(F("Testing device connections..."));
    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

    // 等待准备
    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

     // 加载并配置DMP
    Serial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();

    //在此处提供您自己的陀螺仪偏移量,以最小灵敏度进行缩放
     for (byte i = 0; i < 4; i++)
     {
      PT(EEPROMReadInt(MPUCALIB + 4 + i * 2));
      PT(" ");
     }
    PTL();
    mpu.setZAccelOffset(EEPROMReadInt(MPUCALIB + 4));
    mpu.setXGyroOffset(EEPROMReadInt(MPUCALIB + 6));
    mpu.setYGyroOffset(EEPROMReadInt(MPUCALIB + 8));
    mpu.setZGyroOffset(EEPROMReadInt(MPUCALIB + 10));

    //确保它正常工作(如果是,则返回0)
    if (devStatus == 0) 
    {
        //校准时间:生成偏移并校准我们的MPU6050
       mpu.CalibrateAccel(6);
       mpu.CalibrateGyro(6);
       mpu.PrintActiveOffsets();
        
        //打开DMP,现在已经准备好
        Serial.println(F("Enabling DMP..."));
        mpu.setDMPEnabled(true);

        //启用Arduino中断检测
        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 Ready标志,以便主loop()函数知道可以使用它
        Serial.println(F("DMP ready! Waiting for first interrupt..."));
        dmpReady = true;
        
        //获得预期的DMP数据包大小,以便以后进行比较
        packetSize = mpu.dmpGetFIFOPacketSize();
    }
    else 
    {
        // ERROR!
        // 1 = 初始内存加载失败
        // 2 = (DMP配置更新失败)
        //(如果要中断,通常代码将为1)
        Serial.print(F("DMP Initialization failed (code "));
        Serial.print(devStatus);
        Serial.println(F(")"));
    }

    // 配置LED输出
    pinMode(LED_PIN, OUTPUT);
    
}
//主程序循环
void loop()
{  
  //如果编程失败,请不要尝试做任何事情
  if (!dmpReady) return;
   if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer))
   {
    #ifdef OUTPUT_READABLE_QUATERNION
            // display quaternion values in easy matrix form: w x y z
            //以简单矩阵形式显示四元数值: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_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_GRAVITY
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);                                                                                                                                                                         
            Serial.print("gravity\t");
            Serial.print(gravity.x);
            Serial.print("\t");
            Serial.print(gravity.y);
            Serial.print("\t");
            Serial.println(gravity.z);
        #endif

        // led闪烁指示活动
        blinkState = !blinkState;
        digitalWrite(LED_PIN, blinkState);
   }
  
}

Arduino写ROS的发布者发布MPU数据

在基础上,我再添加了的ros的发布者,将MPU的四元数数据发布给了上位机。
提一嘴,如果想把Arduino写成ROS的一个节点而且交互数据量在280字节以上的,不要用nano板子,不然MPU6050这样的数据都传不到上位机,接不通的(毕设遇到的坑,rosserial_python节点运行会一直报错),所以最好MEGA,输出数据可达1024)。

这部分代码后续更新博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LionelMartin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值