라즈베리파이(raspberry pi)에서 serial to ttl usb 컨버터 장치를 통해 통신을 하기 위해서는 장치명이 아닌 포트위치가 필요하다.
포트 위치는 /dev/ttyUSB1과 같이 디렉터리이며, 여기서 USB0, USB1...의 장치는 연결되는 USB 장치의 개수에 따라 달라진다.
물론 이 포트 위치는 제조사와 장치 명칭을 통해서 고정하여 쓸 수 있다. 하지만 장치는 언제나 동일 기능을 수행하는 다른 장치로 변경할 수 있으므로 나는 Device ID를 이용해서 해당 장치의 포트를 알아내는 방식을 선택했다.
우선 크게 동작하는 방법을 알아보면,
1) Device 입력 및 해당 device가 존재하는지 확인
configuration파일을 통해서 장치ID를 입력 받을 것이므로, 입력받은 ID 값이 실제 라즈베리파이에서 인식된 USB 장치인지 확인한다.
2) ls /dev/ttyUSB* 명령을 통하여 모든 포트 위치 확인
실제 시리얼 통신이 가능한 장치들은 /dev/ttyUSB[0-9]+와 같이 포트 명을 부여 받기 때문에, 모든 포트명을 읽어온다. 더 나은 방법이 있는 것 같긴한데 자세히 안찾아봐서 모르겠다.
3) grep PRODUCT= /sys/bus/usb-serial/devices/ttyUSB0/../uevent를 통하여 장치 device id와 일치하는 포트 확인
명령어를 실행해보면 알겠지만, 해당 포트에 연결된 장치 정보를 담고 있다. 이 정보에서 PRODUCT열의 값을 가져오면 장치 ID가 포함되어 있는 것을 알 수 있다.
이 세개의 플로우를 통해서, 입력된 device id와 매칭되는 포트값을 찾아낸다.
코드는 파이썬3으로 작성되었다.
<figure class="ad-wp" contenteditable="false" data-ke-type="revenue" data-ad-vendor="adfit" data-ad-id-pc="15272" data-ad-id-mobile="15275"></figure>
## lsusb 명령어를 통해서 device id를 가진 장치가 있는지 확인
deviceID = "1234:1234"
result = ""
try:
result = subprocess.check_output("lsusb | grep "+deviceID,
shell=True,
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e :
result = ""
if(len(result) == 0):
print("장치가 발견되지 않았습니다.")
exit(1)
# 모든 포트 위치 검색
try:
result = subprocess.check_output("ls /dev/ttyUSB*",
shell=True,
stderr=subprocess.STDOUT)
# 바이트 배열로 리턴되는 값을 문자열로 변경
result = str(result)
# 배열이 b'ABCD'의 형식이므로 앞, 뒤 불필요한 문자 제거
result = result[2:len(result)-1]
except subprocess.CalledProcessError as e :
result = ""
# 다수의 행이 반환되므로 개행문자로 문자열 분리
result = res.split('\\n')
found = False
for path in result:
# 포트 패턴 정규식
portPattern = re.compile("^/ttyusb[0-9]+$")
if(portPattern.match(path)):
#올라온 값이 포트값이면, 포트의 PRODUCT정보를 읽어서 장치값 비교
try:
result2 = subprocess.check_output("grep PRODUCT= /sys/bus/usb-serial/devices/"+path[4:]+"/../uevent",
shell=True, stderr=subprocess.STDOUT)
# 문자열로 변경
result2 = str(result2)
# 배열이 b'PRODUCT=1234/1234/100'과 같은 형식이므로 앞, 뒤 불필요 문자열 제거
result2 = result2[10:len(result2)-1]
except subprocess.CalledProcessError as e :
result2 = "GGGG/GGGG\n"
# 개행문자와 /으로 문자열 분리
result2 = result2.split('\\n')[0].split('/')
# 입력받은 device ID를 :으로 분리
didHexList = deviceID.split(':')
# 16진수로 변경하여 확
if(int(result2[0],16)==int(didHexList[0],16) and
int(result2[1],16)==int(didHexList[1],16)):
print("장치의 포트를 찾았다.")
found = True
break
'라즈베리파이, 아두이노' 카테고리의 다른 글
[간단한 아두이노 코딩] 2. LED 깜박이기 (0) | 2020.11.17 |
---|---|
[간단한 아두이노 코딩] 1. IDE 설치 하기 (0) | 2020.11.16 |
[라즈베리파이 / 리눅스] init.d 서비스 스크립트 작성을 통한 시작 프로그램 만들기 (0) | 2019.04.03 |
[라즈베리파이] USB 컨버터(RS485/RS232)를 이용한 시리얼 통신 읽/쓰기 파이썬 예제 (11) | 2019.03.27 |
[아두이노] 두개의 아두이노 사이의 RS485 통신 (0) | 2019.03.23 |