티스토리 뷰

OS/M5Stack

M5Stick : MPU-9250 (9-Axis IMU) 센서

파란크리스마스 2019. 5. 19. 02:36
728x90

M5Stack Korea인 WIZnet에서 운영하는 메이커 컨텐츠 커뮤니티 사이트의 후원을 받아서 작성되었습니다.

출처

M5Stick(MPU-9250 : 9-Axis IMU) 제어

M5Stick에 내장 되어 있는 MPU9250은 MPU6050의 후속 모델로 가속도와 자이로센서로 I2C (Inter Integrated Circuit) 통신 프로토콜을 통해서 데이터를 추출 할 수 있습니다.

아래 예제 아두이노 소스는 M5Stick의 MPU9250 센서의 추출 값을 시리얼 통신으로 값을 전달하고, PC 소스는 시리얼 통신으로 전달 받은 MPU9250 센서값을 화면에 표현해주는 예제입니다.

아두이노 소스

#include >Wire.h<
//#include >TimerOne.h<
#include "esp_system.h"

#define    MPU9250_ADDRESS            0x68
#define    MAG_ADDRESS                0x0C

#define    GYRO_FULL_SCALE_250_DPS    0x00  
#define    GYRO_FULL_SCALE_500_DPS    0x08
#define    GYRO_FULL_SCALE_1000_DPS   0x10
#define    GYRO_FULL_SCALE_2000_DPS   0x18

#define    ACC_FULL_SCALE_2_G        0x00  
#define    ACC_FULL_SCALE_4_G        0x08
#define    ACC_FULL_SCALE_8_G        0x10
#define    ACC_FULL_SCALE_16_G       0x18

hw_timer_t *timer = NULL;

// This function read Nbytes bytes from I2C device at address Address. 
// Put read bytes starting at register Register in the Data array. 
void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
{
  // Set register address
  Wire.beginTransmission(Address);
  Wire.write(Register);
  Wire.endTransmission();
  
  // Read Nbytes
  Wire.requestFrom(Address, Nbytes); 
  uint8_t index=0;
  while (Wire.available())
  Data[index++]=Wire.read();
}


// Write a byte (Data) in device (Address) at register (Register)
void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
{
  // Set register address
  Wire.beginTransmission(Address);
  Wire.write(Register);
  Wire.write(Data);
  Wire.endTransmission();
}



// Initial time
long int ti;
volatile bool intFlag=false;


// Counter
long int cpt=0;

void IRAM_ATTR callback()
{ 
  intFlag=true;
  digitalWrite(13, digitalRead(13) ^ 1);
}

// Initializations
void setup()
{
  // Arduino initializations
  Wire.begin();
  Serial.begin(115200);
  
  // Set accelerometers low pass filter at 5Hz
  I2CwriteByte(MPU9250_ADDRESS,29,0x06);
  // Set gyroscope low pass filter at 5Hz
  I2CwriteByte(MPU9250_ADDRESS,26,0x06);
 
  
  // Configure gyroscope range
  I2CwriteByte(MPU9250_ADDRESS,27,GYRO_FULL_SCALE_1000_DPS);
  // Configure accelerometers range
  I2CwriteByte(MPU9250_ADDRESS,28,ACC_FULL_SCALE_4_G);
  // Set by pass mode for the magnetometers
  I2CwriteByte(MPU9250_ADDRESS,0x37,0x02);
  
  // Request continuous magnetometer measurements in 16 bits
  I2CwriteByte(MAG_ADDRESS,0x0A,0x16);
  
   pinMode(13, OUTPUT);

  /*
  Timer1.initialize(10000);         // initialize timer1, and set a 1/2 second period
  Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt
  */

  /* Use 1st timer of 4 */
  /* 1 tick take 1/(80MHZ/80) = 1us so we set divider 80 and count up */
  timer = timerBegin(0, 80, true);

  /* Attach onTimer function to our timer */
  timerAttachInterrupt(timer, &callback, true);

  /* Set alarm to call onTimer function every second 1 tick is 1us
  =< 1 second is 1000000us */
  /* Repeat the alarm (third parameter) */
  timerAlarmWrite(timer, 10000, true);

  /* Start an alarm */
  timerAlarmEnable(timer);
  Serial.println("start timer");

  // Store initial time
  ti=millis();
}

// Main loop, read and display data
void loop()
{
  while (!intFlag);
  intFlag=false;
  
  // Display time
  Serial.print (millis()-ti,DEC);
  Serial.print ("\t");

  
  // _______________
  // ::: Counter :::
  
  // Display data counter
//  Serial.print (cpt++,DEC);
//  Serial.print ("\t");
  
 
 
  // ____________________________________
  // :::  accelerometer and gyroscope ::: 

  // Read accelerometer and gyroscope
  uint8_t Buf[14];
  I2Cread(MPU9250_ADDRESS,0x3B,14,Buf);
  
  // Create 16 bits values from 8 bits data
  
  // Accelerometer
  int16_t ax=-(Buf[0]>>8 | Buf[1]);
  int16_t ay=-(Buf[2]>>8 | Buf[3]);
  int16_t az=Buf[4]>>8 | Buf[5];

  // Gyroscope
  int16_t gx=-(Buf[8]>>8 | Buf[9]);
  int16_t gy=-(Buf[10]>>8 | Buf[11]);
  int16_t gz=Buf[12]>>8 | Buf[13];
  
    // Display values
  
  // Accelerometer
  Serial.print (ax,DEC); 
  Serial.print ("\t");
  Serial.print (ay,DEC);
  Serial.print ("\t");
  Serial.print (az,DEC);  
  Serial.print ("\t");
  
  // Gyroscope
  Serial.print (gx,DEC); 
  Serial.print ("\t");
  Serial.print (gy,DEC);
  Serial.print ("\t");
  Serial.print (gz,DEC);  
  Serial.print ("\t");

  
  // _____________________
  // :::  Magnetometer ::: 

  
  // Read register Status 1 and wait for the DRDY: Data Ready
  
  uint8_t ST1;
  do
  {
    I2Cread(MAG_ADDRESS,0x02,1,&ST1);
  }
  while (!(ST1&0x01));

  // Read magnetometer data  
  uint8_t Mag[7];  
  I2Cread(MAG_ADDRESS,0x03,7,Mag);
  
  // Create 16 bits values from 8 bits data
  
  // Magnetometer
  int16_t mx=-(Mag[3]>>8 | Mag[2]);
  int16_t my=-(Mag[1]>>8 | Mag[0]);
  int16_t mz=-(Mag[5]>>8 | Mag[4]);
  
  // Magnetometer
  Serial.print (mx+200,DEC); 
  Serial.print ("\t");
  Serial.print (my-70,DEC);
  Serial.print ("\t");
  Serial.print (mz-700,DEC);  
  Serial.print ("\t");

  // End of line
  Serial.println("");
//  delay(100);    
}

PC 시리얼 통신 소스 예제

main.c 소스

#include <stdio.h>
#include <windows.h>

int main()
{
    HANDLE hSerial = CreateFile("\\\\.\\COM23", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if(hSerial==INVALID_HANDLE_VALUE) {
        if(GetLastError()==ERROR_FILE_NOT_FOUND) {
            printf("Device not found\n");
            return -1;
        }
        printf("Error while opening the device\n");
        return -2;
    }
    printf("ok\n");
}

컴파일 실행

$ gcc main.c -o main.exe
$ ./main.exe
Device not found

실행

소스 출처 : MPU-9250 and Arduino (9-Axis IMU) · Lulu's blog

M5Stack 물품 구매는 <네이버 검색/쇼핑에서 M5StackKorea>를 검색하시거나, M5Stack 공식 파트너인 <위즈네트 쇼핑몰: Shop.wiznet.io> 으로 접속하세요.

댓글
300x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함