1. 実際にシリアル通信してみる
前回の記事で書いたことを実践してみます。まず Arduino 側から情報をシリアルに書き出します。#test.ino void setup() { Serial.begin(9600); } void loop() { int hoge; hoge = analogRead(PIN); Serial.println(hoge); }
一方、Raspberry Pi 側では Python でコードを書く必要があります。
#test.py import serial ser = serial.Serial('/dev/ttyACM0', 9600) input = ser.readline() print(input)
とりあえずこれで、「Arduino のセンサが読んだ数値を Raspberry Pi の画面上に出力する」プログラムがかけたように思います。実際に実行してみると……
できたりできなかったりします。なぜなんだろう……。できたときにも
b'(数値)\r\n
2. 原因を考える
うまく表示されたときの「b'」は Python ではバイト列を表すらしいです。Arduino からはバイト列で数値が送信されるってことですね。これは後から int に変換すればすむでしょう。\r\n は改行とかの処理ですが、Python の文字列処理でなんとかできました。input = input.strip()
(数値)\r\n(数値)みたいに表示されてます。おそらく、中途半端なところから読み始めた、ってことではないでしょうか……。
3. 解決策
先ほど Arduinoに書き込んだコードだと、常にシリアル通信が行われていて、それを読みだそうとするから中途半端な部分を読んでしまう。ということは、読みだすときにだけセンサ情報を出力してもらえばいいのではないか?と考えて次のように改良しました。#test.ino void setup() { Serial.begin(9600); } void loop() { int hoge; if(Serial.available() > 0) { hoge = analogRead(PIN); Serial.println(hoge); }Serial.abailable() は、シリアルに入力があるときにそのデータのバイト数を返す関数です。つまりこの if文は、何か出力があったときにシリアルに書き込むということです。
#test.py import serial import time ser = serial.Serial('/dev/ttyACM0', 9600) time.sleep(2) ser.write(b'R') input = ser.readline() input = input.strip() print(input)ser.write()はシリアルに書き込む関数です。Rというバイト列を送っていますが、これは適当でよくて、ようはこの書き込みがセンサの情報をちょうだいねという要求のつもりです。なお、import time をして2秒遅らせているのは、そうしないと動かなかったためです。シリアル通信し始めてから書き込めるようになるまでにはタイムラグがあるらしく、すぐに書き込むとだめっぽいですね。
といった感じにしたら安定してセンサからの情報を得ることができました!今後はこの方式でやっていきます。
まとめの図です |
参考
Arduino 日本語リファレンス
Raspberry PiとArduino間でUSB経由のシリアル通信
0 件のコメント:
コメントを投稿