라즈베리 파이 4와 HiFive1 보드 간 UART 통신 구축
이 랩에서는 라즈베리 파이 4와 HiFive1 간 신뢰할 수 있는 UART 링크를 설정하고, HiFive1을 프로그래밍하여 수신 데이터 에코, 파이에서 조향 각도를 보드로 전달하는 파이썬 스크립트 생성을 다룹니다.
파트 0: 라즈베리 파이 4에서 UART 활성화
파이 4에는 4개의 UART 컨트롤러가 탑재되어 있습니다. 이 연습에서는 uart2와 uart3을 사용합니다. /boot/config.txt에 다음 줄 추가 후 재부팅:
dtoverlay=uart2,115200
dtoverlay=uart3,115200
재부팅 후 디바이스 노드 /dev/ttyAMA1 (uart2)와 /dev/ttyAMA2 (uart3) 사용 가능.
보드 연결 방법:
- HiFive1 UART1 RX (핀 7) ↔ Pi 4 UART2 TX (핀 27) – 조향 명령용 데이터 경로
- HiFive1 UART0 TX (핀 1) ↔ Pi 4 UART3 RX (핀 29) – 콘솔 출력용 디버그 채널
파이에서 /dev/ttyAMA1 (HiFive1로 전송)과 /dev/ttyAMA2 (HiFive1 콘솔 수신)로 이 채널들에 접근 가능.
파트 1: HiFive1 프로그래밍
PC(파이 아님)에서 스켈레톤 프로젝트 다운로드:
$ cd ~/Documents/PlatformIO
$ wget https://ittc.ku.edu/~heechul/courses/eecs388/l10-comm.tar.gz
$ tar zxvf l10-comm.tar.gz
l10-interrupt 폴더를 VSCode 워크스페이스에 추가. 목표는 UART1에서 데이터 읽고, UART0으로 에코, 콘솔에 결과 출력.
간결한 알고리즘:
while (1) {
if (ser_isready(1)) {
char data = ser_read(1);
ser_write(0, data);
ser_printline(0, "Received: ");
/* 필요시 포맷 조정 */
}
}
시리얼 API는 eecs388_lib.h/c에 정의:
void ser_setup(int devid);
int ser_isready(int devid);
void ser_write(int devid, char c);
void ser_printline(int devid, char *str);
char ser_read(int devid);
int ser_readline(int devid, int n, char *str);
devid = 0은 UART0, devid = 1은 UART1 선택. ser_isready 함수는 UART IP 레지스터에서 대기 중인 데이터 확인:
int ser_isready(int devid) {
uint32_t regval = *(volatile uint32_t *)(UART_ADDR(devid) + UART_IP);
return regval;
}
컴파일 및 플래싱 후 파이로 전환하여 두 터미널 열기:
- 데이터 발신자:
screen /dev/ttyAMA1 115200
- 디버그 뷰어:
screen /dev/ttyAMA2 115200
발신자 터미널에 아무 문자열이나 입력; 같은 문자열이 디버그 터미널에 나타나면 정상 동작 확인.
파트 2: 라즈베리 파이 4 파이썬 스크립트
수동 터미널 대신 다음을 수행하는 파이썬 프로그램 작성:
/dev/ttyAMA1을 조향 각도 전송용으로 열기
/dev/ttyAMA2를 디버깅용으로 열기
- 카메라 프레임 캡처, DNN 추론 실행, 결과 각도를 HiFive1로 전송
pySerial 사용 예제 스켈레톤:
import serial
import time
import cv2 # 또는 카메라 인터페이스
# 시리얼 포트 열기
ser1 = serial.Serial('/dev/ttyAMA1', 115200, timeout=1)
ser2 = serial.Serial('/dev/ttyAMA2', 115200, timeout=1)
while True:
# 프레임 캡처
frame = cv2.imread('frame.jpg') # 실제 카메라 읽기로 교체
# DNN 추론 실행
angle = dnn_inference(frame) # float32
# float를 4바이트 표현으로 변환
angle_bytes = angle.to_bytes(4, byteorder='little', signed=True)
ser1.write(angle_bytes)
# 선택적: 디버그 출력 읽기
debug = ser2.readline().decode().strip()
if debug:
print('HiFive1:', debug)
# 타이밍 제어 (예: 30fps)
time.sleep(1/30)
# 정리
ser1.close()
ser2.close()
참고: 전송 전 float를 바이트로 변환, HiFive1에서 값을 해석할 때 같은 바이트 순서 사용.
부록: 라즈베리 파이 4 GPIO 및 주변장치 개요
파이 4는 기존 파이 모델을 넘어 확장된 I²C, SPI, UART 인터페이스 제공. pinout 명령으로 모든 핀 보기:
pinout
주요 주변장치:
- I²C - 최대 6개 버스,
sudo i2cdetect -y 1로 장치 검색.
- SPI -
raspi-config로 활성화, 표준 SCLK/MOSI/MISO 라인 사용.
- UART - 비동기 시리얼, 헤드리스 통신이나 HiFive1 같은 마이크로컨트롤러 연결에 이상적.
자세한 구성은 공식 라즈베리 파이 문서 참조: Config-txt 가이드.