Arduino

[Arduino] 1. MPU6050 가속도 / 자이로 센서 (1) - 구현

Easyho.log 2024. 7. 23. 15:42

1. MPU6050 센서를 보기 전

현재 쓰고 있는 아두이노 보드를 본다. 내가 쓰는 아두이노 보드는 "Arduino GIGA Wifi r1" 보드이다.

"Arduino GIGA Wifi r1" 보드의 PinMap은 다음과 같다.

Arduino.cc에서 가져온 GIGA Wifi r1 보드의 핀맵

이 핀맵을 보면서 결선을 해야 센서가 고장이 안 난다.


2. MPU6050 센서란?

MPU6050 센서는 회전과 기울기를 측정하여 모터를 제어하는데 쓰이는 모듈이다. 이 모듈은 향후 드론에서 많이 쓰이며, 드론이 균형을 제어하는데 주로 쓰이는 모듈이 된다.

MPU6050의 다이어그램

MPU6050의 모듈은 3축의 가속도 센서와 3축의 자이로 센서 그리고 온도 센서로 나뉠 수 있다. 나중에 아두이노 코드로 구현해서 시리얼 모니터에 나오는 걸 보면, X, Y, Z 축에서의 가속도와 각속도가 출력될 것이다. 

 

실제 MPU6050 모듈

저렇게 생겼다. 모듈을 보면 x축 방향과 y축 방향이 어느 방향을 가리키는 지도 나와 있다. 그렇다면 가속도랑 각속도는 어떻게 구할까?


3. 가속도와 각속도 측정 원리

Roll, Pitch, Yaw

 

 일단 좌표가 우리가 아는 X, Y, Z와 같은 좌표가 아니다. 아까도 말했다시피 이 모듈은 드론이나 비행 물체에 많이 쓰인다고 했다. 비행 물체에서는 항공 좌표계라고 하는 X, Y, Z와 비슷하지만 살짝 다른 좌표계를 사용한다.


각 축의 정의는 다음과 같이 할 수 있다.

1. Yaw (요)
   - 회전 축 : 수직 축 (Z축)
   - 설명: 항공기의 수직 축을 중심으로 좌우 방향의 회전을 나타낸다. 좌우로 방향을 바꾸는 동작.


2. Pitch (피치)
   - 회전 축 : 측면 축 (Y축)
   - 설명 : 항공기의 측면 축을 중심으로 상하 방향의 회전을 나타낸다. 

3. Roll (롤) 
   - 회전 축 : 전방 축 (X축)
   - 설명 : 항공기의 전방 축을 중심으로 기울어지는 회전을 나타낸다. 날개가 한쪽으로 기울어지는 동작.
 

이러한 좌표로 각 방향마다의 각속도를 구한다. 가속도는 우리가 흔히 쓰는 좌표계로 구하면 된다. MPU6050 모듈은 가속도를 중력 가속도를 이용하여 가속도를 구한다. 따라서 MPU6050에서 가속도 단위를 g로 바꾸었다.


4. 모듈 이용하여 측정

1) 결선

Arduino GIGA Wifi R1 보드 기준으로 다음과 같다.

VCC 5V
GND GND
SCL SCL(21)
SDA SDA(20)

결선하면 다음과 같이 생겼다.

모양은 썩;;

2) 코드 예제

예제는 다음과 같다. 사실 라이브러리를 설치하여 하는 방법도 있다.

#include <Wire.h>

const int MPU_addr = 0x68;  // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

// 가속도계와 자이로스코프의 감도 계수
const float ACCEL_SCALE = 16384.0;  // 가속도계: ±2g, 16384 LSB/g
const float GYRO_SCALE = 131.0;     // 자이로스코프: ±250 degrees/sec, 131 LSB/(degrees/sec)

void setup() {
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);

  // 가속도계 및 자이로스코프 설정
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x1C);  // ACCEL_CONFIG register
  Wire.write(0x00);  // set to ±2g (least sensitivity)
  Wire.endTransmission(true);

  Wire.beginTransmission(MPU_addr);
  Wire.write(0x1B);  // GYRO_CONFIG register
  Wire.write(0x00);  // set to ±250 degrees/sec (least sensitivity)
  Wire.endTransmission(true);

  Serial.begin(115200);
}

void loop() {
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr, 14, true);  // request a total of 14 registers
  
  AcX = Wire.read() << 8 | Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  AcY = Wire.read() << 8 | Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ = Wire.read() << 8 | Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp = Wire.read() << 8 | Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX = Wire.read() << 8 | Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY = Wire.read() << 8 | Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ = Wire.read() << 8 | Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

  // 원시 데이터를 물리 단위로 변환
  float ax = AcX / ACCEL_SCALE;  // 가속도: g 단위
  float ay = AcY / ACCEL_SCALE;  // 가속도: g 단위
  float az = AcZ / ACCEL_SCALE;  // 가속도: g 단위

  float gx = GyX / GYRO_SCALE;  // 자이로: degrees/sec 단위
  float gy = GyY / GYRO_SCALE;  // 자이로: degrees/sec 단위
  float gz = GyZ / GYRO_SCALE;  // 자이로: degrees/sec 단위

  // 결과 출력
  Serial.print("AcX = "); Serial.print(ax);
  Serial.print(" g | AcY = "); Serial.print(ay);
  Serial.print(" g | AcZ = "); Serial.print(az);
  Serial.print(" g | Tmp = "); Serial.print(Tmp / 340.00 + 36.53);  // equation for temperature in degrees C from datasheet
  Serial.print(" | GyX = "); Serial.print(gx);
  Serial.print(" deg/s | GyY = "); Serial.print(gy);
  Serial.print(" deg/s | GyZ = "); Serial.println(gz);
  Serial.println(" deg/s");

  delay(1000);
}

 

MPU6050은 I2C 통신을 이용하기 때문에 <Wire.h> 라이브러리를 불러와야 한다. 이러한 코드를 입력하면 다음과 같이 뜬다.

 

출력 결과

가속도의 경우에는 본래 -32768 ~ 32767의 범위를 16384로 나눈 값이므로 -2g ~ +2g 안에서 중력 가속도가 출력될 것이다. 하지만 가속도에서는 문제가 없지만 각속도에서는 오차가 생길 것이다. 이 오차는 다음에 다뤄보도록 하겠다.