以前「Arduino シリアル通信でLチカを試す」で Arduino とパソコン間のシリアル通信を試してみたことがありました。でも、やってみたらできたって感じでよくわかっていなかったので、今回はもう少しちゃんと調べてみようと思います。
まず、Reference の Serial.available() にあるサンプルスケッチで試してみましょう。
-
int incomingByte = 0; // for incoming serial data
-
void setup() {
-
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
-
}
-
void loop() {
-
// reply only when you receive data:
-
if (Serial.available() > 0) {
-
// read the incoming byte:
-
incomingByte = Serial.read();
-
// say what you got:
-
Serial.print("I received: ");
-
Serial.println(incomingByte, DEC);
-
}
-
}
シリアルインターフェースから受信したデータをそのまま送り返すスケッチです。シリアルモニタを開いて試してみました。
入力 | 出力 |
123 | I received: 49 I received: 50 I received: 51 I received: 10 |
ABC | I received: 65 I received: 66 I received: 67 I received: 10 |
シリアルモニタから「123」と入力して送信すると、出力のように表示されます。ここで、あれ?と思っちゃう。そのまま送り返しているはずなのに、違うじゃん (^_^;)
よーく考えてみると、文字「1」の ASCII コードは「49」、文字「2」は「50」です。入力したデータが ASCII コードとしてやり取りされている、ということですね。
最後の「10」は改行コードの LF を表します。シリアルモニタでは送信ボタンをクリックすると LF が送られるんです。シリアルモニタの右下の「LFのみ」を「CRのみ」とすると改行コード CR の「13」が表示されます。
シリアルモニタから入力された文字列は Arduino に送られてシリアルバッファに格納されます。Serial.read() を実行するとバッファの最初の 1 バイトが読み取られます。そして最初の 1 バイトはクリアされる (のじゃないかと思います) 。Serial.read() を繰り返すたびに 1 文字ずつ読み取っていき、読み取れるデータがなくなったら次のデータを待ちます。
そんな仕組み。間違っているかもしれません。間違っていたら笑ってやってください。
ところで、これを文字列にしようと思ったら 1 文字ずつ配列変数に格納するなどしなくてはいけません。Serial.available() で文字数を取得して配列変数を定義し、1 文字ずつそこに格納していくって感じかな。難しくはないけれど、面倒くさい (^_^;)
文字列を簡単に読み取れないのかなぁとググってみたら、Serial.readString() という関数があることがわかりました。ただ、この関数はタイムアウト (デフォルトは 1000ms) で終了するので、処理が遅いのが欠点。実際試してみると、データを送信して 1 秒後に表示されます。
そこで、Serial.readStringUntil( terminator ) 関数を使うことにしました。terminator に ‘¥n’ を指定すると、改行コードを受信した時点で終了してくれます。
作り直したスケッチはこんな感じ。変数名やコメントは変えてないので、ちょっと違和感もありますが、ご容赦。
-
String incomingByte; // for incoming serial data
-
void setup() {
-
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
-
}
-
void loop() {
-
// reply only when you receive data:
-
if (Serial.available() > 0) {
-
// read the incoming byte:
-
incomingByte = Serial.readStringUntil('¥n');
-
// say what you got:
-
Serial.print("I received: ");
-
Serial.println(incomingByte);
-
}
-
}
これで入力した文字列と同じ文字列が出力に表示されるようになりました。