움직임·거리·위치 · 난이도 어려움
MPU6050 가속도 센서로 XYZ 가속도와 기울기 각도를 재고 영점 오차 보정하기
MPU6050은 가속도 3축과 회전 속도 3축을 I²C로 보내는 센서예요. 0x68·0x69 주소 확인, ±2g 범위에서 16384가 1g라는 환산, 중력 방향으로 앞뒤·좌우 기울기를 구하는 식, 데이터시트의 영점 오차를 줄이는 보정, 마찰각과 진동 탐구를 정리했어요.
이 센서로 무엇을 잴 수 있나
MPU-6050은 인벤센스(InvenSense, 지금은 TDK)가 만든 칩으로, 가속도 3축과 자이로(회전 속도) 3축, 온도 센서가 함께 들어 있어요. 흔히 GY-521이라는 작은 기판에 얹어 팔아요. 제품 사양서에 적힌 칩의 전원 범위는 2.375~3.46V이고, I²C로 최대 400kHz까지 통신해요.
이 글은 가속도와 기울기를 다뤄요. 가만히 놓인 센서는 중력만 느끼기 때문에, 세 축에 나뉜 중력의 크기로 판이 얼마나 기울었는지 계산할 수 있어요. 그래서 경사로의 기울기, 물체가 미끄러지기 시작하는 각도, 선풍기 받침의 떨림처럼 움직임과 각도에 관한 것을 숫자로 잴 수 있어요. 회전 속도(자이로)도 읽을 수 있지만 각도로 바꾸려면 시간에 따라 더해야 하고 오차가 쌓여서, 처음에는 가속도로 시작하는 편이 쉬워요.
원리
가속도 센서 안에는 아주 작은 추가 스프링에 매달린 것과 비슷한 구조가 있고, 추가 밀리는 정도를 전기 신호로 바꿔요. 그래서 센서가 가만히 있어도 중력 때문에 1g를 느껴요. 칩 면이 하늘을 향하게 평평히 두면 Z축이 약 +1g, X·Y축은 0에 가깝게 나와요.
출력은 −32768~32767 사이의 정수예요. 범위 설정(AFS_SEL)이 ±2g일 때 1g가 16384, ±4g면 8192, ±8g면 4096, ±16g면 2048이에요. 레지스터 지도에 따르면 전원을 켰을 때 범위 레지스터는 0이라 ±2g로 시작해요. 같은 문서는 칩이 잠든 상태로 켜진다고 적어요. 전원 관리 레지스터(0x6B)에 0을 써야 깨어나는데, 아래 코드가 쓰는 라이브러리가 이 일을 해 줘요.
판을 기울이면 중력이 세 축에 나뉘어 실려요. 가만히 있을 때만 쓸 수 있는 기울기 식은 이래요(NXP 응용 노트 AN3461).
- 좌우 기울기(roll) = atan2(ay, az)
- 앞뒤 기울기(pitch) = atan2(−ax, √(ay² + az²))
센서가 움직이거나 떨리면 중력 말고 다른 가속도가 섞여서 이 식이 틀려져요. 세 축을 합친 크기 √(ax² + ay² + az²)가 1g에 가까운지 보면 지금 값을 각도로 믿어도 되는지 판단할 수 있어요.
준비물
- 라즈베리파이 피코와 USB 케이블
- MPU6050 모듈(GY-521 등), 점퍼선 4개
- 라이브러리
mpu6050.py(시나브로 PICO가 자동으로 넣어 줘요) - 평평한 판(두꺼운 하드보드 30cm 정도), 각도기, 양면테이프
- 탐구용: 지우개, 동전, 나무토막, 종이·천·고무판, USB 선풍기
배선
브레드보드 따라 꽂기 순서 (9단계)
- 피코를 브레드보드 가운데 홈에 걸쳐 꽂아요. USB 단자가 왼쪽을 보게 하고, 1번 핀이 f2, 40번 핀이 e2에 들어가요. 다리가 홈 양쪽에 모두 들어갔는지 옆에서 봐요.
- 주황 선: 피코 36번 핀(3V3(OUT)) 옆 칸 a6 → 위쪽 + 줄(3.3V). 이제 이 줄 전체가 3.3V예요.
- 검은 선: 피코 38번 핀(GND) 옆 칸 a4 → 위쪽 − 줄(GND). 이제 이 줄 전체가 GND예요.
- 자이로/가속도 MPU6050 꽂기: 다리 VCC · GND · SCL · SDA를 위쪽 a24 · a25 · a26 · a27에 차례로 꽂아요. 다리가 브레드보드에 바로 안 들어가면 암-수 점퍼선으로 같은 칸에 이어요.
- 주황 선(3.3V 전원): 자이로/가속도 VCC 줄 b24 → 위쪽 + 줄(3.3V)
- 검은 선(GND): 자이로/가속도 GND 줄 b25 → 위쪽 − 줄(GND)
- 파란 선(신호): 자이로/가속도 SCL 줄 b26 → 피코 7번 핀(GP5) 옆 칸 j8
- 파란 선(신호): 자이로/가속도 SDA 줄 b27 → 피코 6번 핀(GP4) 옆 칸 j7
- 마지막 확인: ① 위쪽 + 줄(3.3V)과 아래쪽 + 줄(5V)이 서로 이어지지 않았나요? ② 모든 부품의 GND가 − 줄에 이어졌나요? ③ 5V 신호 다리는 저항을 거쳐 피코에 이어졌나요? ④ 긴 브레드보드는 + − 줄이 가운데에서 끊긴 것도 있어요(빨간·파란 선이 끊겨 있으면 짧은 선으로 이어요). ⑤ 그림과 한 칸씩 비교한 뒤 USB를 꽂아요.
| 모듈 핀 | 피코 핀 | 비고 |
|---|---|---|
| VCC | 3V3 (36번) | 칩 전원 범위 2.375~3.46V |
| GND | GND (38번) | 공통 접지 |
| SCL | GP5 (7번) | I2C0 SCL |
| SDA | GP4 (6번) | I2C0 SDA |
| AD0 | 연결 안 함 | AD0가 GND면 0x68, 3V3이면 0x69 |
| XDA·XCL·INT | 연결 안 함 | 보조 I²C와 인터럽트, 이 글에서는 안 써요 |
GP4·GP5는 I2C0 묶음이라 코드에서 I2C(0, sda=Pin(4), scl=Pin(5))로 열어요. 사양서에 적힌 I²C 주소는 이진수 110100X이고, 마지막 자리를 AD0 핀이 정해요. AD0를 비워 두었다면 코드의 i2c.scan() 결과로 주소를 확인해요. DS3231 시계 모듈도 0x68을 쓰니 함께 쓸 때는 AD0를 3V3에 이어 0x69로 바꾸거나 다른 I²C 버스로 옮겨요(I²C 장치 여러 개).
센서를 판에 붙일 때는 기판이 들뜨지 않게 양면테이프로 꼭 붙여요. 기판이 판과 어긋나 있으면 그만큼 각도가 틀려져요.
코드
from machine import Pin, I2C
import mpu6050
import math
import time
i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)
found = i2c.scan()
print("I2C 주소:", [hex(a) for a in found])
addr = 0x68 if 0x68 in found else 0x69
mpu = mpu6050.accel(i2c, addr) # 잠든 칩을 깨워요(0x6B에 0)
LSB = 16384 # ±2g 범위에서 1g
# 1) 영점: 칩 면을 위로 하고 평평한 곳에 1초 동안 둔 채 평균
ox = 0
oy = 0
oz = 0
for i in range(50):
v = mpu.get_values()
ox += v['AcX']
oy += v['AcY']
oz += v['AcZ']
time.sleep_ms(20)
ox = ox / 50
oy = oy / 50
oz = oz / 50 - LSB # Z는 1g가 정상이라 1g를 빼요
print(f"영점 차이(mg): X {ox / LSB * 1000:.0f}, Y {oy / LSB * 1000:.0f}, Z {oz / LSB * 1000:.0f}")
while True:
v = mpu.get_values()
ax = (v['AcX'] - ox) / LSB
ay = (v['AcY'] - oy) / LSB
az = (v['AcZ'] - oz) / LSB
g = math.sqrt(ax * ax + ay * ay + az * az)
roll = math.atan2(ay, az) * 180 / math.pi
pitch = math.atan2(-ax, math.sqrt(ay * ay + az * az)) * 180 / math.pi
print(f"DATA: ax={ax:.3f}, ay={ay:.3f}, az={az:.3f}, g={g:.3f}, roll={roll:.1f}, pitch={pitch:.1f}")
time.sleep(0.2)
- 처음에 I²C를 훑어 0x68이 있으면 그 주소로, 없으면 0x69로 열어요. 둘 다 없으면 배선부터 봐요.
- 영점 단계는 50번(약 1초) 평균을 내서 X·Y는 0, Z는 1g에서 얼마나 벗어났는지 구해요. 이 차이를 이후 값에서 빼요. 결과는 밀리g(mg) 단위로 보여 줘요.
ax,ay,az는 g 단위,g는 세 축을 합친 크기,roll과pitch는 도(°) 단위예요.
값 해석과 보정
사양서는 가속도 0점의 처음 오차를 X·Y축 ±50mg, Z축 ±80mg로 적고, 0~70℃ 사이에서 X·Y가 ±35mg, Z가 ±60mg까지 더 움직일 수 있다고 적어요. 50mg는 작아 보이지만, 수평 근처에서 X축에 50mg가 더해지면 각도로 약 2.9°가 틀어져요. 영점 단계를 지우면 안 되는 이유예요. 감도(16384) 자체도 ±3%까지 다를 수 있어서, 각도가 클수록 오차가 조금씩 커져요.
영점 단계에는 함정이 하나 있어요. 책상이 기울어 있으면 그 기울기까지 "영점"으로 빼 버려요. 판을 그 자리에서 180° 돌려 한 번 더 재고 두 번의 X·Y 평균을 내면, 책상 기울기는 서로 지워지고 센서 자체의 영점만 남아요. 정확한 각도가 필요한 탐구라면 이렇게 두 번 재서 ox, oy에 직접 넣어요.
g가 1.000에서 크게 벗어난 줄은 센서가 움직이던 순간이에요. 예를 들어 0.95~1.05 밖의 줄은 각도 분석에서 빼기로 미리 정해 두면 좋아요(센서 값의 신뢰도). pitch가 ±90°에 가까워지면 ay와 az가 모두 0에 가까워 roll이 크게 흔들려요. 그런 자세에서는 다른 축으로 바꿔 계산해요.
회전 속도가 궁금하면 GyX~GyZ를 읽어요. 기본 범위(±250°/s)에서는 131이 초당 1°예요.
자주 하는 실수
- 주소를 확인하지 않기. AD0가 3V3에 이어진 기판을 0x68로 부르면 통신 오류가 나요. 스캔 결과를 먼저 봐요.
- 움직이는 중에 각도를 믿기. 손으로 들고 흔들면 각도 식이 틀려요.
g가 1에 가까운 줄만 써요. - 범위를 바꾸고 16384를 그대로 쓰기. ±4g로 바꿨다면 1g는 8192예요. 범위와 환산값은 늘 함께 바꿔요.
- 영점을 잡는 동안 책상을 건드리기. 1초 사이의 흔들림이 영점에 섞여요. 영점 단계에서는 손을 떼요.
- 길고 헐거운 선으로 판을 기울이기. 선이 당겨지며 I²C 통신이 끊길 수 있어요. 선을 판에 테이프로 고정하고 짧게 써요.
이 센서로 잴 수 있는 탐구
1. 센서 각도는 각도기와 얼마나 맞을까
- 질문: 영점 보정 전과 후에 센서가 잰 기울기는 각도기 값과 얼마나 다를까?
- 바꾸는 것: 판의 기울기 0°, 15°, 30°, 45°, 60°(각도기로 맞춤)
- 재는 것: pitch와 각도기 값의 차이(°)
- 방법: 판 한쪽을 책으로 받쳐 각도를 맞추고 10줄 평균을 내요. 각도마다 3번, 보정 전과 후를 모두 기록해요.
2. 미끄러지기 시작하는 각도로 마찰 계수 구하기
- 질문: 판에 붙인 재질에 따라 지우개가 미끄러지기 시작하는 각도가 얼마나 다를까?
- 바꾸는 것: 판 표면(종이, 천, 고무판). 올려 둘 물체는 같은 지우개
- 재는 것: 미끄러지기 직전의 pitch(°), 정지 마찰 계수 tan(각도)
- 방법: 판 한쪽을 1초에 몇 도씩 아주 천천히 들어 올리고, 지우개가 움직이는 순간의 줄을 표시해요. 재질마다 5번 반복해 평균을 내요.
3. 선풍기 세기에 따라 받침은 얼마나 떨릴까
- 질문: USB 선풍기의 바람 세기를 올리면 받침의 떨림이 커질까?
- 바꾸는 것: 선풍기 세기(끔, 약, 중, 강)
- 재는 것: 10초 동안 g의 표준편차(g)
- 방법: 센서를 선풍기 받침 아래쪽에 양면테이프로 붙이고, 세기마다 10초씩 3번 기록해요. 받침을 놓는 책상과 자리는 바꾸지 않아요.
안전
- 선풍기 날개에 손가락과 점퍼선이 닿지 않게 해요. 센서와 선은 날개에서 먼 받침 쪽에 붙여요.
- 마찰 탐구에서는 가벼운 물체만 쓰고, 판 끝 아래에 물체를 받을 상자를 둬요.
- 전원은 사이트 배선대로 3V3에 이어요. 배선은 USB를 뽑은 채로 바꿔요.
- 이 장치를 자전거나 사람 몸의 안전을 판단하는 데 쓰지 마세요.
더 알아보기
- 데이터시트: InvenSense "MPU-6000 and MPU-6050 Product Specification" 3.1판(범위·감도, 0점 허용 오차, 전원 범위, I²C 주소), "Register Map and Descriptions" 4.0판(0x3B 가속도 출력, 0x6B 전원 관리, 0x75 WHO_AM_I, 초기값, 온도 식)
- 응용 노트: NXP(Freescale) AN3461 "Tilt Sensing Using a Three-Axis Accelerometer"(기울기 식)
- 라이브러리: 시나브로 PICO가 제공하는
mpu6050.py(adamjezek98/MPU6050-ESP8266-MicroPython을 피코 하드웨어 I²C에 맞게 고친 판, MIT) - 기초 글: I²C 장치 여러 개, 피코 핀 지도, 센서 값의 신뢰도, 잴 수 있는 탐구 주제 만들기