◆ MPU6050은 3축 가속도계와 3축 자이로스코프가 통합된 6축 모션 센서이다.
◆ I2C 통신으로 자세 및 움직임을 감지하며, 드론, 로봇, 게임 컨트롤러 등 다양한 프로젝트에 활용된다.
■ 동작원리
가속도계는 중력 가속도를 포함한 선형 가속도를 측정하여 기울기와 움직임을 감지한다.
자이로스코프는 각속도를 측정하여 회전 움직임을 감지한다.
두 센서의 데이터를 융합(Sensor Fusion)하면 더 정확한 자세 정보를 얻을 수 있다.
■ 사양
동작 전압 : 3.3V ~ 5V
통신 방식 : I2C (기본 주소: 0x68)
가속도 범위 : ±2g, ±4g, ±8g, ±16g
자이로 범위 : ±250, ±500, ±1000, ±2000 °/s
ADC 분해능 : 16비트
내장 온도 센서 : 있음
핀 구성 : 8핀 (VCC, GND, SCL, SDA, XDA, XCL, AD0, INT)
■ 축 방향
축 설명
--------------------------------
X축 좌우 방향 (Roll)
Y축 앞뒤 방향 (Pitch)
Z축 상하 방향 (Yaw)
■ 회로 구성
MPU6050 라즈베리 파이
-----------------------------------------------------
VCC 3.3V
GND GND
SDA GPIO 2 (Pin 3)
SCL GPIO 3 (Pin 5)
● i2c 모듈 활성화 확인
$ lsmod | grep i2c
● I2C 주소 확인
$ i2cdetect -y 1
● smbus2 설치
- smbus는 i2c 통신을 지원하는 파이썬 모듈로 데이터를 읽고 쓸 수 있는 기능을 지원한다.
$ sudo pip install smbus2
--->>> 예제 : Gyro_MPU6050.py <<<-------------------------------
import smbus2
import time
MPU6050_ADDR = 0x68
PWR_MGMT_1 = 0x6B
ACCEL_XOUT_H = 0x3B
bus = smbus2.SMBus(1)
bus.write_byte_data(MPU6050_ADDR, PWR_MGMT_1, 0)
def read_raw_data(reg):
high = bus.read_byte_data(MPU6050_ADDR, reg)
low = bus.read_byte_data(MPU6050_ADDR, reg + 1)
value = (high << 8) | low
if value > 32768:
value -= 65536
return value
while True:
ax = read_raw_data(ACCEL_XOUT_H)
ay = read_raw_data(ACCEL_XOUT_H + 2)
az = read_raw_data(ACCEL_XOUT_H + 4)
print(f"Accel: {ax}, {ay}, {az}")
time.sleep(0.1)
-------------------------------------------------------------------------------------
◆ x축으로 기울이거나 y축으로 기울일때마다 LED에 불이 켜지게 한다.
--->>> 예제 : Gyro_MPU6050-LED.py <<<----------------------------
from smbus2 import SMBus
from bitstring import Bits
import math
import time
import RPi.GPIO as GPIO
bus = SMBus(1)
DEV_ADDR = 0x68
register_gyro_xout_h = 0x43
register_gyro_yout_h = 0x45
register_gyro_zout_h = 0x47
sensitive_gyro = 131.0
register_accel_xout_h = 0x3B
register_accel_yout_h = 0x3D
register_accel_zout_h = 0x3F
sensitive_accel = 16384.0
def read_data(register):
high = bus.read_byte_data(DEV_ADDR,register)
low = bus.read_byte_data(DEV_ADDR,register+1)
val = (high << 8) + low
return val
def twocomplements(val):
s = Bits(uint=val,length=16)
return s.int
def gyro_dps(val):
return twocomplements(val)/sensitive_gyro
def accel_g(val):
return twocomplements(val)/sensitive_accel
def dist(a,b):
return math.sqrt((a*a)+(b*b))
def get_x_rotation(x,y,z):
radians = math.atan(x/dist(y,z))
return radians
def get_y_rotation(x,y,z):
radians = math.atan(y/dist(x,z))
return radians
bus.write_byte_data(DEV_ADDR,0x6B,0b00000000)
GPIO.setmode(GPIO.BCM)
LED1 = 18
LED2 = 23
GPIO.setup(LED1, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(LED2, GPIO.OUT, initial=GPIO.LOW)
try:
while True:
x = read_data(register_accel_xout_h)
y = read_data(register_accel_yout_h)
z = read_data(register_accel_zout_h)
aX = get_x_rotation(accel_g(x),accel_g(y),accel_g(z))
aY = get_y_rotation(accel_g(x),accel_g(y),accel_g(z))
data = str(aX) + ' , ' + str(aY) + '$'
if aX > 0.7 or aX < -0.5:
print("on LED1")
GPIO.output(LED1, GPIO.HIGH)
else:
GPIO.output(LED1, GPIO.LOW)
if aY < -0.5 or aY > 0.5:
print("on LED2")
GPIO.output(LED2, GPIO.HIGH)
else:
GPIO.output(LED2, GPIO.LOW)
print(data)
time.sleep(0.3)
except KeyboardInterrupt:
print("\nInterrupted!")
except:
print("\nClosing socket")
finally:
bus.close()
GPIO.cleanup()
--------------------------------------------------------------------------------------------