🌟
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の場合
- デバイスマネージャーを開く(スタートメニューで「デバイスマネージャー」と検索)
- 「ポート (COMとLPT)」を展開
-
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