SenseHat으로 방향지시등 보여주기 (with Raspberry Pi)

GAON PARK·2023년 11월 23일
0
post-custom-banner

SenseHat

센서들이 모여있는 Hat이다.
- 자이로 센서
- 가속도 센서
- 기압 센서
- 지자기 센서
- 온/습도 센서
컨트롤러와 디스플레이도 포함한다.
- 8x8 LED
- 8 방향 조이스틱
무려 우주정거장에 보내진 제품이라고 한다(!)

참고로 라즈베리파이의 위(?)에 결합시켜 사용할 수 있는 악세사리로 Add-on board라고도 한다. (라즈베리파이 종료하고, 케이블을 분리하고 연결할 것!!)
=> https://www.raspberrypi.com/products/

이번에는 센스햇에 달린 8x8 LED를 이용해 방향지시등을 만들어 보려고 한다. (실시간 방향에 따라 반영되는 거라 사실 방향"지시"등 보다는 방향"중계"등에 가깝다)

설정

센스햇을 사용하기 위해 관련 라이브러리를 설치하고, 재시작한다.

sudo apt-get update
sudo apt-get install sense-hat
sudo reboot

샘플 코드를 작성하고 테스트해보자.

from sense_hat import SenseHat
sense = SenseHat()
sense.show_message("Hello world!")

더 많은 API는 센스햇 공식 document 참고
=> https://pythonhosted.org/sense-hat/api/

라즈베리파이 코드

sensehat_thread.py

from sense_hat import SenseHat
import threading
import paho.mqtt.client as mqtt
import socket


class SenseHatThread(threading.Thread):
    BROKER_ADDRESS = socket.gethostbyname(socket.gethostname())
    WHITE = (255, 255, 255)
    RED = (255, 0, 0)
    YELLOW = (255, 255, 0)

    FRONT = [
        [0, 3], [0, 4],
        [1, 2], [1, 3], [1, 4], [1, 5],
        [2, 3], [2, 4],
        [3, 3], [3, 4]
    ]
    BACK = [
        [4, 3], [4, 4],
        [5, 3], [5, 4],
        [6, 2], [6, 3], [6, 4], [6, 5],
        [7, 3], [7, 4]
    ]
    LEFT = [
        [3, 4], [4, 4],
        [3, 5], [4, 5],
        [2, 6], [3, 6], [4, 6], [5, 6],
        [3, 7], [4, 7]
    ]
    RIGHT = [
        [3, 0], [4, 0],
        [2, 1], [3, 1], [4, 1], [5, 1],
        [3, 2], [4, 2],
        [3, 3], [4, 3]
    ]
    FRONT_LEFT = [
        [0, 7],
        [0, 6], [1, 7],
        [0, 5], [1, 6], [2, 7],
        [2, 5],
        [3, 4]
    ]
    FRONT_RIGHT = [
        [0, 0],
        [0, 1], [1, 0],
        [0, 2], [1, 1], [2, 0],
        [2, 2],
        [3, 3]
    ]
    BACK_LEFT = [
        [7, 7],
        [6, 7], [7, 6],
        [5, 7], [6, 6], [7, 5],
        [5, 5],
        [4, 4]
    ]
    BACK_RIGHT = [
        [7, 0],
        [6, 0], [7, 1],
        [5, 0], [6, 1], [7, 2],
        [5, 2],
        [4, 3]
    ]

    IS_FRONT = False
    IS_BACK = False
    IS_LEFT = False
    IS_RIGHT = False

    def __init__(self):
        super().__init__()
        self.sense = SenseHat()
        self.client = mqtt.Client("sensehat_sub")
        self.client.connect(self.BROKER_ADDRESS)
        self.client.subscribe("command")
        self.client.on_message = self.on_command

    def on_command(self, client, userdata, message):
        cmd = str(message.payload.decode("utf-8"))
        self.sense.clear()
        if "go" == cmd:
            if self.IS_LEFT:
                self.on_dir_led(self.FRONT_LEFT)
            elif self.IS_RIGHT:
                self.on_dir_led(self.FRONT_RIGHT)
            else:
                self.on_dir_led(self.FRONT)
            self.IS_FRONT = True
            self.IS_BACK = False
        elif "back" == cmd:
            if self.IS_LEFT:
                self.on_dir_led(self.BACK_LEFT)
            elif self.IS_RIGHT:
                self.on_dir_led(self.BACK_RIGHT)
            else:
                self.on_dir_led(self.BACK)
            self.IS_FRONT = False
            self.IS_BACK = True
        elif "stop" == cmd:
            self.IS_FRONT = False
            self.IS_BACK = False
            if self.IS_LEFT:
                self.on_dir_led(self.LEFT)
            elif self.IS_RIGHT:
                self.on_dir_led(self.RIGHT)
            else:
                self.on_break_led()
        elif "left" in cmd:
            if self.IS_FRONT:
                self.on_dir_led(self.FRONT_LEFT)
            elif self.IS_BACK:
                self.on_dir_led(self.BACK_LEFT)
            else:
                self.on_dir_led(self.LEFT)
            self.IS_LEFT = True
            self.IS_RIGHT = False
        elif "right" in cmd:
            if self.IS_FRONT:
                self.on_dir_led(self.FRONT_RIGHT)
            elif self.IS_BACK:
                self.on_dir_led(self.BACK_RIGHT)
            else:
                self.on_dir_led(self.RIGHT)
            self.IS_LEFT = False
            self.IS_RIGHT = True
        elif "mid" == cmd:
            self.IS_LEFT = False
            self.IS_RIGHT = False
            if self.IS_FRONT:
                self.on_dir_led(self.FRONT)
            elif self.IS_BACK:
                self.on_dir_led(self.BACK)
            else:
                self.on_break_led()

    def on_dir_led(self, arg):
        for pos in arg:
            self.sense.set_pixel(pos[0], pos[1], self.YELLOW)

    def on_break_led(self):
        self.sense.set_pixel(7, 7, self.RED)
        self.sense.set_pixel(7, 0, self.RED)

    def run(self):
        self.sense.clear()
        self.on_break_led()
        self.client.loop_forever()

main app.py

import camera_thread  
import cmd_thread  
import etc_thread  
import oled_thread  
import sensehat_thread  
  
  
if __name__ == '__main__':  
    camera_th = camera_thread.CameraThread()  
    camera_th.start()  
    sense_th = sensehat_thread.SenseHatThread()  
    sense_th.start()  
    cmd_th = cmd_thread.CmdThread()  
    cmd_th.start()  
    etc_th = etc_thread.EtcThread()  
    etc_th.start()  
    oled_th = oled_thread.OLEDThread()  
    oled_th.start()

트러블 슈팅

센스햇 코드 동작 시, OSError: Cannot detect RPi-Sense FB device 같은 에러 메시지가 뜬다?

sudo vi /boot/config.txt

# 문서 가장 아래에 다음 내용 추가 후
dtoverlay=rpi-sense

# 재시작
sudo reboot
post-custom-banner

0개의 댓글