Raspberry Pi Zero W를 이용한 Serial 통신 파일 전송(File Transfer) 속도 분석
1. 라즈베리파이에서 Host PC로 다량의 데이터 전송
Host PC 입장에서는 다음과 같이 코드를 작성할 수 있다. Serial 통신을 이용해 계속해서 데이터를 전달 받아 파일에 쓰게 된다. 또한 프로그램이 동작하는 과정에서 주기적으로 통신 속도를 출력하도록 해보았다.
import time
import serial
s = serial.Serial("COM7", 115200)
total = 0
start_time = time.time()
last_time = 0
while True:
# 가져올 데이터가 존재하는 경우에만 처리
len = s.inWaiting()
if len == 0:
continue
# 파일을 열어 로그를 작성
f = open("log.dat", "ab")
data = s.read(len)
f.write(data)
f.close()
total += len
# 주기적으로 출력
passed = time.time() - start_time
if passed > last_time + 1:
print(f"total length: {total} bytes")
print(f"average speed: {total / (1024 ** 2 * passed)} MB/s")
last_time = passed
s.close()
라즈베리파이에서는 다음과 같이 코드를 작성할 수 있다. 크기가 4096 bytes인 배열에 데이터를 담아서 반복적으로 Serial 통신을 통해 데이터를 전송한다.
#include <stdio.h>
int main(void) {
FILE* file;
char buf[4096];
for (int i = 0; i < sizeof(buf); i++) {
buf[i] = i % 256;
}
while (1) {
file = fopen("/dev/ttyGS1", "r+");
fwrite(buf, 1, sizeof(buf), file);
fclose(file);
}
return 0;
}
단순히 데이터를 전달받는 것만 작업을 했더니 약 3MB/s 정도의 전송 속도가 나오는 것을 확인할 수 있다.
다만 필자의 경우 처음에 데이터의 유실이 발생했다. 일단 내가 라즈베리파이에서 데이터를 쓸 때 파일을 "r+" 옵션으로 열었는데, b를 붙여 주는 것을 깜빡 잊어 byte stream으로 데이터를 작성하지 않고 있었다. 그래서 "rb+" 옵션으로 바꾸어주면 해결될 줄 알았다. 하지만 여전히 데이터의 유실이 발생했다.
정확히는 라즈베리파이가 \b10을 보내려고 하면 \b13\b10이 보내지는 것이었다. 다시 말해 \n을 보내려고 하면, 자동으로 앞에 \r가 붙어버리는 문제가 발생했다. 이때 CR(Carriage Return)은 \r을 의미한다. (아스키코드 13번) 또한 LF(Line Feed)는 New Line와 같은 말로 \n을 의미한다. (아스키코드 10번) 콘솔에서는 CRLF 한 쌍을 줄 바꿈으로 인식하는 경우가 많아서, 시리얼로 LF만 보내도 자동으로 앞에 CR를 붙여 버리는 것이다.
따라서 라즈베리파이에서 다음과 같은 명령어를 입력한 뒤에 문제가 해결되었다. raw 데이터 자체를 보내도록 하는 것이다.
sudo stty -F /dev/ttyGS1 raw
이렇게 raw 모드로 바꾼 이후에는 속도를 확인한 결과 다음과 같이 5MB/s 정도의 전송 속도가 나오는 것을 확인할 수 있었다. 속도에 영향을 미치는 부분으로 raw 모드만 작용했는지는 명확하지는 않은데, 아무튼 이 정도 속도까지는 뽑을 수 있다.
아무튼 속도가 빠르기 때문에 3분이면 1GB 정도의 데이터를 보낼 수 있었다. 추가적으로 데이터의 유실이 발생하는지 여부를 체크하는 코드를 짜보자. 데이터를 받는 쪽에서 이용하면 된다.
f = open("log.dat", "rb")
data = f.read()
for i in range(len(data) - 1):
if (data[i] + 1) % 256 != data[i + 1]:
print("(Invalid) 데이터가 부정확합니다.")
if i % (1024 ** 2) == 0:
print(f"{i // (1024 ** 2)}MB checked.")
실행 결과 약 800MB 정도의 데이터를 전달받았으나, 한 치의 오차도 없이 데이터가 모두 전송된 것을 확인할 수 있었다.
2. Host PC에서 라즈베리파이로 다량의 데이터 전송
Host PC 입장에서도 Serial 통신을 이용해 대량의 파일을 라즈베리파이에게 전송할 수 있다.
'기타' 카테고리의 다른 글
Ubuntu 16.04 호스트(Host) PC에 Oracle VM VirtualBox를 설치하여 Ubuntu 16.04 게스트(Guest) 설치하기 (0) | 2020.11.15 |
---|---|
리눅스 오픈소스 랜섬웨어(Ransomware) CryptoTrooper 분석 환경 구축 (0) | 2020.11.15 |
Raspberry Pi Zero W를 이용해 2개의 USB Configuration을 재부팅마다 교체하기 (0) | 2020.11.15 |
무료 파일 공유 서비스: 미디어파이어(MediaFire) 사용 방법 (0) | 2020.11.15 |
Raspberry Pi Zero W를 이용한 USB Gadget Serial 데이터 전송 예제 (0) | 2020.11.15 |