2017年3月2日木曜日

Raspberry Pi と Arduino で楽器作り(5) - シリアル通信後の処理

Arduino と Raspberry Pi のシリアル通信について、結構細かく書きました。


1. 実際にシリアル通信してみる

前回の記事で書いたことを実践してみます。まず Arduino 側から情報をシリアルに書き出します。

#test.ino
void setup() {
  Serial.begin(9600);
}
void loop() {
  int hoge;
  hoge = analogRead(PIN);
  Serial.println(hoge);
}
Serial.begin(speed) でシリアル通信を開始できます。引数にはボーレートを入れます。Serial.print() でシリアルモニタに情報を送信できます。今回はピン番号 PIN のアナログ入力を出力し改行しています(Serial.println()は改行して出力する)。
一方、Raspberry Pi 側では Python でコードを書く必要があります。

#test.py
import serial

ser = serial.Serial('/dev/ttyACM0', 9600)
input = ser.readline()
print(input)
import serial をしたら上記のように ser に代入しておくといいみたいです。'/dev/ttyACM0'は、Raspberry Pi が Arduino のUSBをこう認識しているということらしいです。9600はボーレートなので、Arduino でさっき指定した速度と合わせなければなりません。ser.readline() はシリアル通信から一行読むという関数です。
とりあえずこれで、「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秒遅らせているのは、そうしないと動かなかったためです。シリアル通信し始めてから書き込めるようになるまでにはタイムラグがあるらしく、すぐに書き込むとだめっぽいですね。
といった感じにしたら安定してセンサからの情報を得ることができました!今後はこの方式でやっていきます。
まとめの図です
次は python-sonic を使って、読み取った情報をもとに音を出していきます。

参考
Arduino 日本語リファレンス
Raspberry PiとArduino間でUSB経由のシリアル通信

0 件のコメント:

コメントを投稿