【pySerial-asyncio】pySerialでArduinoの非同期I/Oを実現していく
はじめに
こんにちは、がんがんです。
最近はRaspberry Pi to Arduinoの実験をコツコツと行っています。
pySerialを用いてArduinoへのシリアル通信を行っているのですが、試しに非同期で処理を出来ないかなと考えました。
そこで試しに「pyserial asyncio」で検索をかけてみると、なんとpipでインストールできるバージョンに遭遇することが出来ました。
Welcome to pySerial-asyncio’s documentation — pySerial-asyncio 0.4 documentation
そこで今回はこちらを試していこうと思います。
以前asyncioを試してみた記事はこちらです。
【メモ】Pythonの非同期I/Oライブラリ「asyncio」について触ってみる - ganganの技術備忘録
目次
環境
- 送信側:Raspberry Pi(Raspbian Stretch)
- 受信側:Arduino Uno
- Python3.4以上(asyncioが使用できないため)
調査を進めてみると…
いろいろと調査を進めてみると、本ライブラリはpySerialの制作人が作成したリポジトリでした。
github.com
そのため、試しにpySerialのドキュメントをいろいろあさってみると
pySerial API — pySerial 3.0 documentation
予想通りありました。
ただ、この一文がこわいですね。自己責任か…
Warning This implementation is currently in an experimental state. Use at your own risk.
Exampleをみてみる
まずはExampleをみていきます。コードは以下の通りです。
import asyncio import serial_asyncio class Output(asyncio.Protocol): def connection_made(self, transport): self.transport = transport print('port opened', transport) transport.serial.rts = False transport.write(b'hello world\n') def data_received(self, data): print('data received', repr(data)) self.transport.close() def connection_lost(self, exc): print('port closed') asyncio.get_event_loop().stop() loop = asyncio.get_event_loop() coro = serial_asyncio.create_serial_connection(loop, Output, '/dev/ttyUSB0', baudrate=115200) loop.run_until_complete(coro) loop.run_forever() loop.close()
クラスの中に分からない関数があるので1つずみ見ていきます。
connection_made()
コネクションが作成されたときに呼び出される関数です。今回の場合だと、Serial通信の接続が完了した時に呼び出される関数です(イメージ的には__init__的な感じ)。
data_received()
名前の通り、データ受信時の対応を決める関数です。exampleでは、portを閉じるようになっています。
connection_lost()
コネクションの接続が解除されたときに呼び出される関数です。exampleでは、loop.stop()を実行するようになっっています。
実際に実験してみる
次にArduinoで実験を行ってみます。実験としては以下の通りです。
・接続時にラズパイからbytes("1;")を送信 ・Arduino側は受信文字列に合わせてLEDが点滅
ラズパイ側のコード
Arduino側のコード
おわりに
今回はPythonの非同期I/Oライブラリを利用したpyserial-asyncioを試してみました。
data_received()部分をもう少し改良すれば非同期的にラズパイとの処理を行うことが出来るかなと思います。
改めてasyncioのドキュメントを読む必要がありそうですね。頑張ります。