반응형

MPU6050 은 자이로센서와 가속도 센서가 결합된 센서이다. 이 센서에는 DMP(Digital Motion Processing) 모드가 있어서 상보필터를 이용해서 계산하지 않아도 Yaw/Pitch/Roll 각도를 구할 수 있다. Raspberry Pi에서 MPU6050의 DMP 모드는 C++ 코드로 이용 가능하다.


다음은 MPU6050 센서에서 값을 가져오는 코드가 있는 github 이다.


https://github.com/richardghirst/PiBits


이 코드는 I2Cdev 라이브러리가 포함되어 있는데, Raspberry Pi 3에서 이용하기 위해서는 I2cDev.cpp에서 /dev/i2c-0 를 /dev/i2c-1 로 바꿔주어야 한다. 


git clone https://github.com/richardghirst/PiBits.git


명령을 주면 PiBits 라는 폴더가 생기고 이 안에 MPU6050-Pi-Demo 폴더가 있다.

여기에서 I2Cdev.cpp 에 /dev/i2c-0 를 찾아서 /dev/i2c-1로 바꿔주고 make 하게 되면 빌드가 된다. 빌드할떼 demo_3d 는 lilbgtkmm-3.0-dev 가 설치되어 있어야 하는데, 본 포스팅에서는 불필요해서 생략한다.


빌드되고 나면 demo_raw, demo_dmp가 생성되는데 이중 demo_dmp 가 dmp 모드로 센서에서 값을 읽는 것이다.


demo_dmp.cpp 에서 #define OUTPUT_READABLE_YAWPITCHROLL 을 주석 해제하고 나머지 OUTPUT_ 로 되어 있는 부분은 주석처리 한다.


컴파일 하고 실행하면 yaw, pitch roll 각도가 출력된다. 


다음은 demo_dmp.cpp 에서 필요한 yaw,pitch,roll 각도만 출력되도록 정리한 코드이다.


#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <stdint.h>

#include <string.h>

#include <math.h>

#include "I2Cdev.h"

#include "MPU6050_6Axis_MotionApps20.h"


MPU6050 mpu;

uint16_t setupDMP() {

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

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


        printf("Initializing I2C devices...\n");

        mpu.initialize();

        // verify connection

        printf("Testing device connections...\n");

        printf(mpu.testConnection() ? "MPU6050 connection successful\n" : "MPU6050 connection failed\n");

        // load and configure the DMP

        printf("Initializing DMP...\n");

        devStatus = mpu.dmpInitialize();

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


        if (devStatus == 0) {

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

                printf("Enabling DMP...\n");

                mpu.setDMPEnabled(true);

                //mpuIntStatus = mpu.getIntStatus();

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

                printf("DMP ready!\n");

                // get expected DMP packet size for later comparison

                packetSize = mpu.dmpGetFIFOPacketSize();

                return packetSize;

        } else {

                // ERROR!

                // 1 = initial memory load failed

                // 2 = DMP configuration updates failed

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

                printf("DMP Initialization failed (code %d)\n", devStatus);

                return -1;

        }

}

int main() {

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

        float x_angle;

        float y_angle;

        float z_angle;

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

        uint8_t fifoBuffer[64]; // FIFO storage buffer

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

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

        uint16_t packetSize=setupDMP();

        usleep(100000);

        printf("PacketSize:%d\n",packetSize);

        int loopFlag=1;

        while(loopFlag==1){

                fifoCount = mpu.getFIFOCount();

                if (fifoCount == 1024) {

                        // reset so we can continue cleanly

                        mpu.resetFIFO();

                        printf("FIFO overflow!\n");

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

                } else if (fifoCount >= 42) {

                        // read a packet from FIFO

                        mpu.getFIFOBytes(fifoBuffer, packetSize);

                        // display Euler angles in degrees

                        mpu.dmpGetQuaternion(&q, fifoBuffer);

                        mpu.dmpGetGravity(&gravity, &q);

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

                        x_angle=ypr[2]*180/M_PI;

                        y_angle=ypr[1]*180/M_PI;

                        z_angle=ypr[0]*180/M_PI;

                        printf("x:%7.2f y:%7.2f z:%7.2f \n", x_angle,y_angle,z_angle);

                }

        };

        return 0;


반응형
Posted by alias
,