IT_Study/Embedded System

Embedded System (2) : 라즈베리파이를 이용한 통신, I2C, SPI 방식을 통한 프로그램 구현

__Vivacé__ 2023. 4. 20. 23:04
라즈베리파이에 썼던 모듈(.py)르네사스보드 / ST보드(.c)에 사용하고 싶다 --> how?

 1. 해당 모듈이 르네사스보드 or st보드도 지원하는 지(라이브러리 유무 등) 알아본다.
 2. Datasheet와 메모리 맵을 보면서 bit operation을 통해 data를 읽어야 한다.
 3. python으로 제작된 라이브러리를 c로 바꾼다. 
     - class로 구현된 라이브러리를 함수로 변경 등

 

장치 연결 시, 기본적인 통신 방법

유선 통신 프로토콜 무선 통신 프로토콜
UART  적외선
SPI RFID
I2C 블루투스
CAN WiFi

*매 순간 신뢰성을 보장해야 하는 환경은 유선통신을 사용

 

 

BMP 280

정밀한 대기압 센서, 온도 측정 가능

BMP 280

 

SDA / SCL 핀이 존재 -> I2C 통신이 가능하다는 의미

I2C가 GPIO 연결보다 좋은 점
 - PIN 2개로 다량의 장치를 연결하여 각각 제어할 수 있음

 


I2C

https://www.appskit.co.kr/single-post/2018/05/09/%EA%B8%B0%EC%88%A0%EB%85%B8%ED%8A%B8-%ED%86%B5%EC%8B%A0i2c-%ED%86%B5%EC%8B%A0%EC%9D%B4%EB%9E%80

Master Slave 보다, Main / Sub 이란 단어를 사용

 1. Main이 START 신호를 보내고 데이터를 전송 (버스 승하차 비유)

 2. Sub이 ACK 또는 NACK 응답을 보내며, Main이 STOP 신호를 보내어 통신을 종료

 

 

 

I2C 통신 연결 해보기 - 기본 세팅

라즈베리파이와 BMP280을 위와 같이 설정 후, 라즈베리파이 부팅 

Configuration의 Interface에서 I2C를 Enabled 설정 후, cmd 실행

위의 명령어를 했을 때 다음과 같은 창이 뜬다면, 연결 성공

위의 숫자가 있는 구간이 slave 주소값을 의미 --> 0x76

 

 

BMP280의 데이터시트 확인

온도와 기압을 확인할 예정

BMP280의 데이터시트 / https://www.digikey.kr/ko/datasheets/bosch-sensortec/bosch-sensortec-bst-bmp280-ds001-19#pf13

 - 0xFA : Bit 전체는 [19:12] 에 대한 값

 - 0xFB : Bit 전체는 [11:4]에 대한 값

 - 0xFC : 7, 6, 5, 4번 bit는 [3:0]에 대한 값

 따라서, Bit Operation을 통해 I2C 값을 읽어들일 수 있다.

import smbus
from time import sleep

DEVICE_BUS = 1 # I2C 통신에서 라즈베리파이의 버스 번호, 보통 0이나 1을 사용 
DEVICE_ADDR = 0x76  # 아까 얻은 slave 주소

# smbus 라이브러리를 사용하여 라즈베리파이의 I2C 통신 버스 객체 생성
bus = smbus.SMBus(DEVICE_BUS)

while True:
    a = bus.read_byte_data(DEVICe_ADDR, 0xFA) # 1번 버스의 0xFA라는 주소로부터 1 byte만큼 읽어옴 
    b = bus.read_byte_data(DEVICe_ADDR, 0xFB)
    c = bus.read_byte_data(DEVICe_ADDR, 0xFC)
    
    result = (a<<12) | (b<<4) | ((c&0xF0)>>4) # 위의 데이터시트 기반으로 값을 읽어옴
    print(result) # 530096
    sleep(0.5)

530096이라는 값을 해석하기 위해서는, 데이터시트를 참조해야 하는데, 

다음과 같은 귀찮은 수식을 참고해야 하므로, 라이브러리를 사용하기를 권장하고 있음

 

라이브러리 설치

# 라즈베리파이 cmd에서 해당 명령어 실행

$ git clone https://github.com/pimoroni/bmp280 python
$ cd bmp280 python
$ sudo ./install.sh

 

import time
from bmp280 import BMP280
from smbus import SMBus

bus = SMBus(1)
bmp280 = BMP280(i2c_dev=bus)

while True:
    temperature = bmp280.get_temperature()
    pressure = bmp280.get_pressure()
    print('{:05.2f|*C {:05.2f}hPa'.format(temperature, pressure)) # 온도와 압력 표시됨
    time.sleep(1)

 


SPI

마이크로컨트롤러와 센서, 메모리 칩, 디스플레이 등의 주변장치 간 통신에 사용, 주로 고속이 필요한 장치에 쓰임

 

장점

 - Master가 Slave에게 데이터를 전송하면서, 동시에 데이터 받기도 가능

 - 빠른 통신이 가능

단점

 - I2C는 2개의 핀(SCL, SDA), SPI는 4개의 핀이 필요(CS, SCK, MOSI, MISO) 

     - SS / CS : Slave 선택 / Chip 선택

     - SCK : 클럭

     - MOSI : Master Out Slave In (Master가 말하고, Slave가 들음)

     - MISO : Mister In Slave Out

 

LED 연결하기

Waveshare 사의 0.96inch OELD (B)를 사용 예정

LED (Light Emitting Diode)
 - 정의: 전기가 흐르면서 발광하는 반도체 소자로, 전기 에너지를 빛으로 변환하는 역할을 수행
 - 특징
     - 발광 다이오드이기 때문에 소비 전력이 낮고 수명이 길다
     - 적은 전류로도 발광이 가능하므로 경제적이며 저전력 소자에 많이 사용
     - 단색 LED는 발광 색상이 하나뿐이지만, RGB LED는 세 가지 색상을 혼합하여 다양한 색상을 만들어낼 수 있음

7segment 디스플레이
 - 정의: 일곱 개의 LED 막대로 구성된 디스플레이
 - 특징
     - 간단하고 저렴한 가격으로 구현이 가능함
     - 디자인이 단순하므로 숫자와 일부 문자만 표시 가능하며, 한글 등 복잡한 문자를 표시하는 데에는 한계가 있음
     - 전체 디스플레이를 켜지 않고 필요한 부분만 켤 수 있어서 전력 소모가 적음

LCD (Liquid Crystal Display)
 - 정의: 액체 결정을 이용한 디스플레이로, 백색 조명과 액체 결정층을 이용하여 이미지를 생성
 - 특징
     - 낮은 전력 소모와 고해상도 디스플레이가 가능하여 휴대폰, 노트북 등에 많이 사용됨
     - 액체 결정이 사용되므로 광도가 낮아 햇빛 아래에서는 가시성이 떨어질 수 있음
     - 백색 조명을 사용하므로 전체 디스플레이가 밝게 보여지며, 화면이 커질수록 전력 소모가 높아짐

OLED (Organic Light Emitting Diode)
 - 정의: 유기성 발광 다이오드로, 전기가 흐르면서 발광하는 소자로, 각각의 픽셀이 발광체 역할을 수행
 - 특징
     - LED와 유사하게 발광 다이오드를 이용하기 때문에 전력 소모가 적음
     - 빠른 응답 속도와 넓은 시야각을 가짐
     - 백색 조명이 필요 없어서 전체 디스플레이가 어둡고, 더 낮은 전력 소모량을 가짐
     - 유연한 소재를 사용하여 곡면 디스플레이도 가능하며, 반도체 제조 공정이 단순하므로 제품 생산 비용이 낮음

 

1. LED 라즈베리파이에 연결

다음을 참고하여 라즈베리파이 선을 연결 

 

2. 라즈베리파이 cmd에서 해당 명령어 실행

$ sudo apt-get install p7zip-full
$ sudo wget  https://www.waveshare.com/w/upload/2/2c/OLED_Module_Code.7z --no-check-certificate

# wget으로 받은 파일 압축 해제
$ 7z x OLED_Module_Code.7z -O./OLED_Module_Code
$ cd OLED_Module_Code/RaspberryPi/python/

# setup 파일 설치
$ sudo python3 setup.py install

# LED 작동 확인
$ cd example/
$ python OLED_0in96_test.py

 


센서를 통해 기압과 온도를 읽고, OLED 디스플레이에 표시하기

import sys
import os
import requests
import time
from bmp280 import BMP280
from smbus import SMBus
from datetime import datetime

# BMP280 센서와 통신하기 위한 설정
bus = SMBus(1)
bmp280 = BMP280(i2c_dev=bus)

# 디렉토리 설정
picdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'pic')
libdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib')
if os.path.exists(libdir):
    sys.path.append(libdir)

# 로깅 설정
import logging
import time
import traceback
from waveshare_OLED import OLED_0in96
from PIL import Image,ImageDraw,ImageFont
logging.basicConfig(level=logging.DEBUG)

try:
    # OLED 디스플레이 초기화
    disp = OLED_0in96.OLED_0in96()
    logging.info("\r 0.96inch OLED ")
    disp.Init()
    logging.info("clear display")
    disp.clear()

    # 이미지를 그리기 위한 새로운 이미지 생성
    image1 = Image.new('1', (disp.width, disp.height), "WHITE")
    draw = ImageDraw.Draw(image1)
    font1 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 16)
    font2 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 24)

    # BMP280 센서에서 온도와 기압 읽기
    temperature = bmp280.get_temperature()
    temperature_processed = str(round(temperature,1)) + '°C'
    pressure = bmp280.get_pressure()
    pressure_processed = str(int(pressure)) + 'hPa'

    # 현재 시간 표시
    current_time = datetime.now().strftime("%Y-%m-%d")

    # 화면에 온도, 기압, 날짜 그리기
    draw.text((80, 0), temperature_processed, font = font1, fill=0)
    draw.text((0, 0),pressure_processed, font = font1, fill=0)
    draw.text((5, 24),current_time, font = font2, fill=0)
    disp.ShowImage(disp.getbuffer(image1))

except:
    sys.exit()

라즈베리파이에서 코드 실행 후, OLED 화면에 나타나는 모습

 


RFID (Radio Frequency Identification)

무선 주파수를 사용하여 물체를 인식하고 추적하는 기술

 

RFID-RC522를 이용해서 RFID 기능 구현을 진행해볼 예정

위의 표를 참고해서 RFID와 Rpi를 연결할 것

 

라즈베리파이에서 RFID를 사용하기 위해서는, 라이브러리를 다운로드 받아야 한다.

$ git clone https://github.com/pimylifeup/MFRC522-python
$ cd MFRC522-python
$ sudo python setup.py install
from mfrc522 import SimpleMFRC522
from time import sleep

while True:
    print("Tag your card")
    id = SimpleMFRC522().read()[0]
    print(id)
    sleep(0.3)

위 코드를 실행하면, Rpi에서 RFID용 card나 chip을 인식할 수 있다.