簡體   English   中英

如何使用python從Windows串口讀取數據?

[英]How to read data from a serial port in Windows using python?

在 windows 10 我正在嘗試讀取連接的串行設備的 output。

使用hterm我能夠看到串行端口COM5上的數據。 所以串口工作正常。

現在使用 WSL2 (Ubuntu 20.04.3) 我正在運行以下 python 腳本

import serial

ser = serial.Serial("COM5", baudrate=115200)

失敗並出現錯誤

Traceback (most recent call last):
  File "test1.py", line 6, in <module>
    ser = serial.Serial("COM5", baudrate=115200)
  File "/usr/lib/python3/dist-packages/serial/serialutil.py", line 240, in __init__
    self.open()
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 268, in open
    raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
serial.serialutil.SerialException: [Errno 2] could not open port COM5: [Errno 2] No such file or directory: 'COM5'

我還嘗試使用本文中發布的建議,將串行設備連接到的 USB 端口附加到 WSL。

命令usbipd wsl list in a windows powershell 顯示

8-3    0403:6001  USB Serial Converter                                          Attached - Ubuntu-20.04

但是當在 WSL2 中運行相同的 python 代碼時,會出現相同的錯誤。

那么如何解決這個問題,以便我能夠使用 python 從串行端口讀取所有數據?

我通常使用一種解決方案,我只從 USB VID:PID 數據中識別端口名稱。 這允許我不對任何 com 端口名稱進行硬編碼。

您必須開始搜索與您的 USB 設備對應的端口名稱(請參閱下面的find_device() )。

您還應該在讀取時在串行端口上使用鎖,這樣您就不會獲得多個並發訪問,尤其是在 Windows 上會產生權限錯誤。 請參閱_with_lock()上下文管理器以鎖定串行讀取。

另外,以管理員身份運行代碼,以獲得串行讀取權限(不是必需的,但是嘿,先調試)。

以下示例同時兼容 linux 和 windows

import serial.tools.list_ports
import serial
from contextlib import contextmanager
from threading import Lock

# Your USB DEVICE
USB_VID = "0x0403"
USB_PID = "0x6001"

SERIAL_SETTINGS = {
    "baudrate": 115200,
    "bytesize": 8,
    "parity": "N",
    "stopbits": 1,
}

@contextmanager
def _with_Lock():
    # This is a singleton, pylint: disable=global-statement
    global LOCK

    if LOCK is None:
        LOCK = Lock()

    LOCK.acquire()
    yield
    if LOCK is not None:
        LOCK.release()

def find_devices():
    # type: () -> List[str]
    """
    Find all COM ports corresponding to your USB device
    """
    _device_ports = []
    for port in serial.tools.list_ports.comports():
        if port.vid == int(USB_VID, 16) and port.pid == int(USB_PID, 16):
            _device_ports.append(port.device)
    return _device_ports

def read_device(device: str) -> str:
    try:
        with _with_lock():
            with serial.Serial(device_port, timeout=1, **SERIAL_SETTINGS) as ser:
                result = ser.read(size=64).decode('utf-8')
                if len(result) == 0:
                    return None
                else:
                    return result.strip("\r\n")
                return result
    except serial.SerialException as exc:
        error_message = "Cannot read serial port {}: {}".format(device_port, exc)
        print(error_message)  # or log it
        raise OSerror(error_message)


for port in find_devices():
    data = read_device(port)
    print(data)

希望這可以幫助。 更多串口讀取的例子可以參考我寫的一個讀取USB溫度傳感器的庫,看這個

您可以嘗試使用以下腳本。

import serial

ser = serial.Serial("COM5", baudrate=115200, timeout=1)`
while True:
   data = ser.readline()
   print(data)

我個人首先會讓它在 Ubuntu 20.04.3 中運行。

只需下載一個 Ubuntu 的虛擬機,安裝它(在 VM 環境中(或真機,如果有備用的話))並進行測試。

WSLx 確實不錯,但它仍然存在一些初期問題。

如果您知道它通過真實(或虛擬機)Ubuntu 安裝,那么您就完成了大部分工作。

我總是這樣做,因為我發現 WSLx 可能有一些奇怪的怪癖。 它不應該引起注意,但確實如此,尤其是當涉及到外部硬件時。

由於您使用的是 Ubuntu,因此您不能使用 Windows 使用的端口名稱。在 Ubuntu 中,端口名稱的格式通常為dev/ttyUSB后跟端口號 ( dev/ttyUSB0 )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM