Processor

【라즈베리파이】 wiringPi Python : 자이로 센서(MPU6050)

작성자 임베디드코리아 작성일26-02-20 00:42 조회96회 댓글0건
◆ 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()
--------------------------------------------------------------------------------------------