라즈베리파이, 아두이노

[라즈베리파이/리눅스/우분투] RS232/RS485 to USB 장치 포트(ttyUSB) 검색 방법 및 코드

포도알77 2019. 4. 2. 08:41

 라즈베리파이(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
        

페이스북으로 공유카카오톡으로 공유카카오스토리로 공유트위터로 공유URL 복사