🚚
PC←→Arduino間のデータ送受信
使用するライブラリ
ポートの名前はどこでわかる?
- ポートの名前は Arduino IDE から確認できる
- 1414401 がなんのことなのかはわからない
Arduino → PC
いきなり送受信のコードを書き始めたら混乱してきたので最初は一方通行の確認だけする。
Arduino (送信)
void setup() {
Serial.begin(9600);
}
int count = 0;
void loop() {
Serial.println(count);
count++;
delay(1000);
}
PC (受信)
require "serialport"
SerialPort.open("/dev/cu.usbmodem1414401", 9600) do |sp|
loop do
puts sp.gets
end
end
これで次のようにRuby側で1秒毎に連番が表示されれば次へ。
$ ruby main.rb
30
1
2
3
試してわかったこと。
- ポートファイルは排他的?
- Arduino IDE のシリアルモニタを起動していると Ruby 側が起動できない
Resource busy - /dev/cu.usbmodem1414401 (Errno::EBUSY)
- Arduino IDE のシリアルモニタを起動していると Ruby 側が起動できない
- Ruby 側を実行するたびに Arduino 側がリセットされている?
- 毎回カウンタ 0 から始まるのは想定外だった
PC → Arduino → PC
今度は Arduino 側の受信を確認したい。ただ簡単に確認する方法がないため受信したデータをそのまま送り返すとする。
Arduino (送信)
void setup() {
Serial.begin(9600);
}
int count = 0;
void loop() {
while (true) {
char ch = Serial.read();
if (ch < 0) {
break;
}
Serial.print(ch);
}
Serial.println(count);
count++;
delay(1000);
}
裏で受信するためスレッドを使って工夫する。
PC (受信)
require "serialport"
sp = SerialPort.new("/dev/cu.usbmodem1414401", 9600)
t = Thread.start do
loop do
p ["受信", sp.gets]
end
end
loop do
s = gets
p ["送信", s]
sp.write(s)
end
t.join
sp.close
これで次のようにカウンタを受信しつつ、入力した内容が返ってくれば成功。
$ ruby main.rb
["受信", "3\r\r\n"]
["受信", "0\r\n"]
["受信", "1\r\n"]
["受信", "2\r\n"]
["受信", "3\r\n"]
abc["受信", "4\r\n"]
["受信", "5\r\n"]
["送信", "abc\n"]
["受信", "abc\n"]
["受信", "6\r\n"]
["受信", "7\r\n"]
["受信", "8\r\n"]
["受信", "9\r\n"]
ポートファイルを直接読み書きできた
cat してみたら Ruby で書いたのと同じ挙動になった。
$ cat /dev/cu.usbmodem1414401
106
1
2
3
端末が壊れそうに思えたが普通に表示された。その上、書き込みもできた。
$ echo ok > /dev/cu.usbmodem1414401
echo の内容は cat 側に返ってくる。どこにも指定してないけど 9600 bps だったってどこでわかったんだろう?
さっきからカウンタの前に受信しているマジックナンバーは何?
何回も試したところ前のが残ってるっぽい。
- Ruby 側でカウンタ 3 を受信したときにプログラムを終了する
- Arduino 側も連動して止まる
- でも Arduino 側のカウンタは 5 ぐらいまで進んでいる
- Ruby 側のプログラムを実行する
- Ruby 側はまず 5 を受信してしまう
そんな感じだけど実際のところよくわかっていない (TODO)
参照
Discussion