---
# System prepended metadata

title: 系統簡章：使用 Python 進行非同步 Arduino 通信

---

### 系統簡章：使用 Python 進行非同步 Arduino 通信

這份簡章介紹了如何利用 Python 與 asyncio 框架結合 serial_asyncio 庫，實現對 Arduino 的非同步串行通信。該系統旨在提供一個高效的方法來從 Python 程式控制和監測 Arduino。

#### ArduinoProtocol 類別

- **功能概述**：
  - **`connection_made`**: 當連接成功建立時被呼叫，並儲存傳輸對象。
  - **`data_received`**: 接收到數據時被呼叫，並打印數據內容。
  - **`connection_lost`**: 連接丟失時被呼叫，並打印錯誤信息。

```python
class ArduinoProtocol(asyncio.Protocol):
    def connection_made(self, transport):
        self.transport = transport
        print("Connection established with Arduino.")

    def data_received(self, data):
        print("Data received:", data.decode())

    def connection_lost(self, exc):
        print("Connection lost:", exc)
```

#### ArduinoConnector 類別

- **功能概述**：
  - **`find_port`**: 掃描並找到連接到計算機的 Arduino 裝置端口。
  - **`connect`**: 建立串行連接到 Arduino。如果找到適當的端口，則建立連接，並返回連接的端口名稱；如果未找到，則返回 None。
  - **`send`**: 向 Arduino 發送命令。如果連接已建立，則發送數據；否則，打印連接未建立的警告。

```python
class ArduinoConnector:
    def __init__(self, loop):
        self.port = None
        self.loop = loop
        self.transport = None
        self.protocol = None

    async def find_port(self):
        arduino_ports = [
            p.device for p in list_ports.comports() if "Arduino" in p.description
        ]
        return arduino_ports[0] if arduino_ports else None

    async def connect(self):
        self.port = await self.find_port()
        if self.port is None:
            print("No Arduino port found.")
            return
        try:
            self.transport, self.protocol = (
                await serial_asyncio.create_serial_connection(
                    self.loop, ArduinoProtocol, self.port, baudrate=9600
                )
            )
            print(f">> Connected to Arduino on {self.port} <<")
        except Exception as e:
            print(f"Failed to connect to Arduino port: {e}")

    def send(self, command):
        if self.transport:
            self.transport.write(command.encode())
            print(f"Command sent: {command}")
        else:
            print("Connection is not established.")
```

### 使用方法

1. 確保 Arduino 裝置已正確連接到計算機。
2. 在主函數中呼叫 `ArduinoConnector` 的 `connect` 方法來嘗試建立連接。
3. 通過 `send` 方法向 Arduino 發送指令。

```python
async def main():
    loop = asyncio.get_running_loop()
    arduino = ArduinoConnector(loop)
    await arduino.connect()
    arduino.send("Your command here")

if __name__ == "__main__":
    asyncio.run(main())
```

這個系統提供了一個簡單而有效的方式來從 Python 控制 Arduino 設備，適用於需要實時數據交互的應用場景。

```python
import asyncio
import serial_asyncio
from serial.tools import list_ports


class ArduinoProtocol(asyncio.Protocol):
    def connection_made(self, transport):
        self.transport = transport

    def data_received(self, data):
        print("Data received:", data.decode())

    def connection_lost(self, exc):
        print("Connection lost:", exc)


class ArduinoConnector:
    def __init__(self, loop):
        self.port = None
        self.loop = loop
        self.transport = None
        self.protocol = None

    async def find_port(self):
        arduino_ports = [
            p.device for p in list_ports.comports() if "Arduino" in p.description
        ]
        try:
            return arduino_ports[0]
        except IndexError:
            return None

    async def connect(self):
        self.port = await self.find_port()
        if self.port is None:
            print("No Arduino port found.")
            return

        try:
            self.transport, self.protocol = (
                await serial_asyncio.create_serial_connection(
                    self.loop, ArduinoProtocol, self.port, baudrate=9600
                )
            )
            print(f">> Connected to Arduino on {self.port} <<")
            return self.port
        except Exception as e:
            print(f"Failed to connect to Arduino port: {e}")
            return None

    def send(self, command):
        if self.transport:
            self.transport.write(command.encode())
            print(f"Command sent: {command}")
        else:
            print("Connection is not established.")


async def main():
    loop = asyncio.get_running_loop()
    arduino = ArduinoConnector(loop)
    await arduino.connect()
    arduino.send("Your command here")

if __name__ == "__main__":
    asyncio.run(main())

```