IT_Study/Embedded System

Embedded System (4) : Raspberry Pi와 Control Sensor 연동 및 IMU 제어

__Vivacé__ 2023. 4. 20. 23:04

SenseHat

라즈베리 파이용 확장 보드, 여러 센서로 다양한 환경 데이터를 측정하고 표시할 수 있는 기능을 제공

 - 자이로 센서, 가속도 센서, 기압 센서, 지자기 센서, 온/습도 센서 등

 - 8x8 LED, 8방향 조이스틱

SenseHat 사진

 

 

센스햇 설치

$ sudo apt-get update
$ sudo apt-get install python3-sense-emu sense-emu-tools

설치 시, 라즈베리파이에서 emulator를 확인할 수 있다
Sense HAT Emulator 실행 시, 실행 화면

API Test

# from sense_hat import SenseHat <-- 실제 Hat에 적용됨
from sense_emu import SenseHat

sense = SenseHat()
sense.show_message("HELLO")

위 코드 실행 시, emulator LED에 HELLO가 뜨는 것을 확인할 수 있다.

 

실제 Hat에서 OS Error: Cannot detect RPi-Sense FB device 가 뜰 시, 다음 코드를 입력 후 재부팅하면 된다.

$sudo vi /boot/config.txt

# 마지막 줄에 해당 내용으로 바꿈

---

[all]
dtoverlay=w1-gpio
enable_uart=1
gpu_mem=128
dtoverlay=rpi=sen

---

DataSheet

데이터시트에서, 각 제품의 설명, 특징을 알 수 있음

 원래는 각 센서마다 Timing 차트와 레지스터 맵을 보면서 개발해야 하지만, Library로 이미 구현되어 있다.

 

온도 센서(U3) - HTS221  |  온도, 습도 측정 가능

기압 센서(UT) - LPS25H  |  대기압 측정 가능

from sense_hat import SenseHat
from time import sleep

sense = SenseHat()

while True:
    humi = sense.get_humidity()
    temp = sense.get_temperature()
    press = sense.get_pressure()
    
    print("Humidity : %s" % humi)
    print("Temperature : %s" % temp)
    print("Pressure : %s" % press)
    sleep(1)

 


LED Matrix(U7) 제어

MCU가 64개의 LED를 제어 - GPIO PIN이 부족하기도 하고, 프로그래밍이 어려움

--> Driver 이용 (모듈을 제어할 수 있는 interface 역할)

 

Driver 종류는 FND driver, Motor driver, LCD driver, LED driver 등이 존재

데이터시트는 LED2472G를 참고

 

 

8x8 LED를 이용한 표기

1. 메세지 표기

from sense_emu import SenseHat
from time import sleep

sense = SenseHat()

sense.show_message("A") # A가 우에서 좌로 이동

sense.set_rotation(90)
senses.show_message("A") # A가 시계방향으로 90도 회전한 모양에서, 아래에서 위로 이동

컬러와 속도 조절도 가능

from sense_emu import SenseHat
from time import sleep

sense = SenseHat()
# (표시할 메세지, 속도, 메세지 색깔), 속도는 default가 0.1

sense.show_message("3", 0.3, text_colour=[255, 0, 255])

 

2. 전체 픽셀 표기

from sense_emu import SenseHat
from time import sleep

sense = SenseHat()

# 화면 초기화
sense.clear() # 불빛 모두 끄기
sense.clear(255, 255, 255) # 특정 컬러로 화면 모두 채우기

# 전체 픽셀 표기
X = [255, 0, 0] # Red
O = [255, 255, 255] # White

question_mark = [
O, O, O, X, X, O, O, O,
O, O, X, O, O, X, O, O,
O, O, O, O, O, X, O, O,
O, O, O, O, X, O, O, O,
O, O, O, X, O, O, O, O,
O, O, O, X, O, O, O, O,
O, O, O, O, O, O, O, O,
O, O, O, X, O, O, O, O
]

sense.set_pixels(question_mark)

# 반전도 가능하다
# 1. 상하 반전해서 화면 표기
sense.flip_v()
# 2. 좌우 반전해서 화면 표기
sense.flip_h()

 

3. 특정 픽셀 표기

from sense_emu import SenseHat
from time import sleep

sense = SenseHat()

sense.clear()

red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)

# (x, y, pixel_color)
sense.set_pixel(0, 0, red)
sense.set_pixel(0, 1, red)
sense.set_pixel(0, 2, red)

 

4. 빛의 세기 설정

from sense_emu import SenseHat
from time import sleep

sense = SenseHat()
sense.clear(255, 255, 255)

sense.low_light = True # 불빛 약화
sleep(2)
sense.low_light = False # 불빛 원상 복구

! 디스플레이의 Low_light API가 LED의 전압 값을 낮추는 건 지, rgb 값을 이용해서 낮추는 지를 확인해야 한다. 

 


IMU (Inertial Measurement Unit)

관성 측정 장치를 의미, 

*자이로스코프 센서 : 회전 속도를 측정하는데 사용
*가속도 센서 : 가속도와 중력을 측정하여 운동 상태를 파악하는데 사용
*지자기 센서 : 자기장을 측정하여 나침반과 같은 방향성 정보를 제공하는데 사용

1. 3축 센서
 - 자이로스코프 or 가속도 센서 or 지자기 센서 중 하나를 사용
 - (X, Y, Z) 값을 읽을 수 있음
     - X 축은 좌우 방향, Y 축은 위아래 방향, Z 축은 앞뒤 방향
     - 가속도 센서 : 가속도 정보  |  자이로스코프 센서 : 각속도 정보  |  지자기 센서 자기장 정보

2. 6축 센서
 - 자이로스코프 + 가속도 센서
 - (X, Y, Z) 두 set의 값을 읽을 수 있음

3. 9축 센서
 - 자이로스코프 + 가속도 센서 + 지자기 센서
 - (X, Y, Z) 세 set의 값을 읽을 수 있음

센스햇에는 9축 센서가 있음 - 데이터 시트 검색 : (U4) - LSM9DS1

{"originWidth":546,"originHeight":477,"style":"alignCenter","caption":"자이로스코프 : P, R, Y

 

자이로스코프 값 출력

자이로스코프 값 이해

from sense_hat import SenseHat
from time import sleep

sense = SenseHat()

# 자이로스코프 값 출력
while True:
    ori = sense.get_orientation_degrees()
    print(f'[{ori["pitch"]:5.1f}] - ', end = '')
    print(f'[{ori["roll"]:5.1f}] - ', end = '')
    print(f'[{ori["yaw"]:5.1f}]')

해당 코드 실행 시 결과

가속도센서 값 출력

 - 알아낼 수 있는 정보 : 이동 경로, 진동여부 (장비 고장여부 판단), 기울기 정도

     - 가속도를 적분해서 속도를 알아낼 수 있다.

     - 속도를 적분해서 이동 경로를 알아낼 수 있다.

     --> 센서를 목에 걸고 이동 시, 계산을 통해 경로 추적이 가능

from sense_hat import SenseHat
from time import sleep

sense = SenseHat()

while True:
    acc = sense.get_accelerometer_raw()
    print(f'[{acc["x"]:5.1f}] - ', end = '')
    print(f'[{acc["y"]:5.1f}] - ', end = '')
    print(f'[{acc["z"]:5.1f}]')

정지 시 가속도는 중력가속도를 의미

지자기센서 값 출력

자기력 측정 가능 - 나침반 역할 수행 가능 

from sense_hat import SenseHat
from time import sleep

sense = SenseHat()

while True:
    com = sense.get_compass_raw()
    print(f'[{com["x"]:5.1f}] - ', end='')
    print(f'[{com["y"]:5.1f}] - ', end='')
    print(f'[{com["z"]:5.1f}]')

해당 코드 실행 시 결과

 


조이스틱

"상, 하, 좌, 우, 클릭" 가능

조이스틱 위치

 

wait_for_event()

이벤트가 발생할 때까지 대기하는 방식

from sense_hat import SenseHat
from time import sleep

sense = SenseHat()

while True:
    event = sense.stick.wait_for_event()
    print("The joystick was {} {}".format(event.action, event.direction))
    sleep(0.1)

코드 실행 후, 조이스틱 움직였을 때 반응

 

Polling

프로세서가 상태 변화를 감지하기 위해 주기적으로 하드웨어나 소프트웨어에게 "데이터 준비됨?"과 같은 질문을 보냄

from sense_hat import SenseHat

sense = SenseHat()

while True:
    for event in sense.stick.get_events():
        print("The joystick was {} {}".format(event.action, event.direction))

코드 실행 후, 조이스틱 움직였을 때 반응

Interrupt

이벤트 발생 시, SW나 HW가 프로세서에게 정보를 보내 이벤트를 처리하고, 다시 중단되었던 작업으로 돌아가는 방식

from sense_hat import SenseHat, ACTION_PRESSED, ACTION_RELEASED
from signal import pause

def pushed_up(event):
    global y
    if event.action != ACTION_RELEASED:
        y -= 1

def pushed_down(event):
    global y
    if event.action != ACTION_RELEASED:
        y += 1

def pushed_left(event):
    global x
    if event.action != ACTION_RELEASED:
        x -= 1

def pushed_right(event):
    global x
    if event.action != ACTION_RELEASED:
        x += 1

# Sense HAT LED 디스플레이 새로 고침 함수
def refresh():
    sense.clear()
    sense.set_pixel(x, y, 255, 255, 255)
    
x = 3
y = 3

sense = SenseHat()

# 각 방향에 해당하는 조이스틱 이벤트 처리 함수를 할당
# 어떤 조이스틱 이벤트가 발생하면 'refresh' 함수를 호출하여 디스플레이를 업데이트
sense.stick.direction_up = pushed_up
sense.stick.direction_down = pushed_down
sense.stick.direction_left = pushed_left
sense.stick.direction_right = pushed_right
sense.stick.direction_any = refresh

# 지속적 스크립트 실행이 가능하도록 메인스레드 종료를 막는 함수 실행
pause()