🌟

PythonでArduinoのシリアル通信を送受信する

に公開

はじめに

ArduinoなどのマイコンとPCをシリアル通信でつなぐとき、多くの人はArduino IDEのシリアルモニタを使っていると思います。しかし、IDE付属のモニタはログの全選択ができなかったり(仕様?バグ?)、他のプログラムと連携しづらかったりと制約が多くあります。

そこで本記事では、pySerial を使ってターミナル上で直接シリアル通信を行う方法を紹介します。ログの取り回しが良くなり、さまざまなツールと組み合わせやすくなるため非常に便利です。

準備

環境構築

以下を実行してライブラリをインストール(pip環境)

pip install pyserial

シリアルポートの確認(Mac/Linux)

ターミナルで以下のコマンドを実行してポート名を確認する。

ls /dev/cu.*

たとえば /dev/cu.usbmodemXXXX/dev/ttyUSB0 のようなポート名になる。
Arduino IDEのデバイス選択の欄で確認してもOK(その方が確実)

Windowsの場合

  1. デバイスマネージャーを開く(スタートメニューで「デバイスマネージャー」と検索)
  2. ポート (COMとLPT)」を展開
  3. Arduino Uno (COM3) のようなデバイスを探し、その COM 番号をメモ

実装時、COM10以上の場合は \\\\.\\COM10 と書く必要があるらしいので注意

実装

以下のコードでは、受信スレッドを立てて常に受信するので、送信と受信を並行して行うことができる。
ポートのみ自身の環境に合わせて書き換えればコピペで動くはず。

import serial
import threading
import time

def continuously_read_from_arduino(ser, stop_event):
    while not stop_event.is_set():
        if ser.in_waiting > 0:
            try:
                received = ser.readline().decode('utf-8').strip()
                print(f"\nArduinoからの応答: {received}")
            except UnicodeDecodeError:
                print("\nデコードエラーが発生しました")

def main():
    port = '/dev/cu.xxx'  # ご自身の環境に合わせて変更, Windowsの場合は'COM3'等のみでOK
    baudrate = 9600  # 使用したいバンドを指定

    try:
        ser = serial.Serial(port, baudrate, timeout=1)
        time.sleep(2)  # Arduinoのリセットを待つ
    except serial.SerialException:
        print(f"シリアルポート {port} に接続できません。ポート名を確認してください。")
        return

    stop_event = threading.Event()
    read_thread = threading.Thread(target=continuously_read_from_arduino, args=(ser, stop_event))
    read_thread.daemon = True
    read_thread.start()

    try:
        while True:
            input_data = input("送信データ ('exit'で終了): ")

            if input_data.lower() == 'exit':
                print("終了します。")
                stop_event.set()
                break

            ser.write((input_data + '\n').encode('utf-8'))  # 改行を明示的に送る
            time.sleep(0.1)

    finally:
        ser.close()

if __name__ == '__main__':
    main()

おわりに

さまざまなプログラムと組み合わせてハードウェアを連動させることができるようになった!

Discussion