第47回 補足 – シリアルモニタ

今回はArduino Microでシリアルモニタを使用する際の注意点を説明します。

シリアルモニタの復習

第21回の記事で「シリアルモニタ」の使い方を習得しました。

Arduino Microでシリアルモニタを使用する際、注意点がありますのでこの補足記事では問題とその対応方法を説明します。

 

Arduino Microシリアルモニタの問題点

Arduino Microのシリアルモニタを使おうとして以下のようなスケッチを書くとうまく動きません。以下のスケッチは、setup関数の中でSerial.printlnを使って「シリアルモニタ開始」という文字を表示する内容です。

/*
 * シリアルモニタの動作確認用スケッチ
 */

void setup() {

  // シリアルモニタ利用開始
  Serial.begin(9600);

  // シリアルモニタに文字を表示
  Serial.println("シリアルモニタ開始");

}

void loop() {

  // loopでは何もしない

}

このスケッチでは、setup関数の中で、最初にシリアルモニタを使用するために「Serial.begin(9600);」、そのあとシリアルモニタに文字を表示するために「Serial.println(“シリアルモニタ開始”);」としています。

実際にこのスケッチをコピペしてArduino Microで動作させてみてください。おそらくシリアルモニタに何も表示されないと思います。ちゃんとSerial.begin(9600);と書いた後にSerial.println関数で文字を表示しているのに、なぜ表示されないのでしょうか。

これから、この原因と対応方法について詳しく説明します。

 

シリアルモニタに文字が表示されない原因

Arduinoのシリアルモニタの通信方法として、大きく分けて2種類あります。

以下の画像は「ESP32-DevKitC」というWi-FiやBluetoothなどさまざまな機能が搭載されているArduino互換ボードです。

ESP32-DevKitCボード

このボードには、ESP32-DevKitCを動かしている本体モジュールとは別に、外部とUSBで通信するためのUSB通信モジュールが搭載されています。

ESP32-DevKitCモジュール

このように通信モジュールが搭載されているArduinoボードでは、先ほどのようなSerial.println関数でシリアルモニタに文字が表示されない、ということはありません。

次に、Arduino Microボードを確認してみましょう。

Arduino Micro USB

Arduino Unoにくらべるとずいぶんスッキリしてますよね。実は、Arduino MicroにはUSBで通信するための通信モジュールが搭載されていないんです。でも今までArduino MicroをUSBケーブルでPCに接続してスケッチを送ったり、シリアルモニタで文字を表示したりしてましたよね。

これは、Arduino Microのモジュール本体の中に、外部とUSBで通信する機能が入っているためです。

Arduino Micro 32u4 USB機能

ただ、この機能は常に動作しているわけではなく、Serial.begin関数によりUSB通信の機能が動作を開始して使えるようになります。Serial.begin(9600);の後、ほんのちょっとの時間(せいぜい数ms)、準備に時間がかかります。

先ほどのスケッチがうまく動かなかった理由は、「Serial.begin(9600);」によりArduino MicoroはUSBで外部と通信する機能を使えるように準備しますが、その準備が終わる前にSerial.println関数を処理したため、シリアモニタに文字列がきちんと表示されなかったわけです。

Arduino Micro Serial.begin

つまり、Arduino Microボードでシリアルモニタを使用する場合、Serial.begin関数で「シリアルモニタを使いますよ!」と伝えた後、Arduino Microが通信モジュールの準備が終わるまで待つ必要があるんです。

それでは、具体的にスケッチではどのように書けばいいのか説明します。

 

対策

Arduino Microでシリアルモニタを使用する場合、スケッチには以下のように書きます。以下は先ほどのsetup関数部分です。

void setup() {

  // シリアルモニタ利用開始
  Serial.begin(9600);

  // シリアルモニタの準備ができるまで待つ
  while( !Serial ) {
  }

  // シリアルモニタに文字を表示
  Serial.println("シリアルモニタ開始");

}

シリアルモニタの準備ができるまで待つためには、以下のようにスケッチに追加すればOKです。

while( !Serial ) {
}

この具体的な動作を完全に理解するには新しい知識が必要になりますので、ここでは簡単に説明しておきます。

このwhile文では、「Serial」という変数を使っていますが、これはArduino IDEが裏で宣言してくれているものです。この変数はシリアルモニタの準備ができていない場合は「0」、準備ができた場合は「1」になります。

また、「Serial」の前についている「!」は否定の意味の記号です。つまり、準備ができていない場合の「Serial」の値は0ですので、その否定で「1」になります。while文はかっこの中が0以外の時に繰り返す命令でしたので、「while( !Serial )」は、準備ができていない間繰り返す、という意味になります。

このようなスケッチにより、Arduino MicroのUSB通信モジュールが準備できるまでの間、while文で何もしないで待つ、ということをしています。

 

第21回の記事のスケッチはなぜ動いていたのか

かなり前の記事になりますので、すっかり忘れてしまっているかもしれません。第21回のシリアルモニタを使用した記事では、シリアルモニタの準備ができるまで待つ、ということをしていませんでした。

/*
* 内容: シリアルモニタのテスト
*      1秒に1回データを送信する
* 変更履歴:
*   2019.8.15: 新規作成
*/

void setup() {
  Serial.begin(9600); // シリアルモニタの設定(データの速度は9600)
}

void loop() {
  Serial.println("シリアルモニタのテスト"); // シリアルモニタにデータを送信する
  delay(1000); // 1秒待つ
}

でもこのスケッチをArduino Microボードに送ってシリアルモニタを動作させると、問題なく「シリアルモニタのテスト」という文字が表示されていましたよね。これはなぜだかわかりますか? 答えを読む前にちょっと考えてみてください。

 

Arduino Microがこのスケッチをどのように実行するか順を追って確認してみましょう。

  1. setup関数で「Serial.begin(9600);」によりシリアルモジュールの準備を開始します。この段階ではUSBモジュールはまだ動作していません
  2. 次にloop関数を実行します。loop関数の最初はSerial.println関数でシリアルモニタに文字列を表示しようとしますが、この段階ではUSBモジュールがまだ準備できていませんので、この文字列は表示されません
  3. 次にdelay(1000);で1秒待ちます。この間にUSBモジュールの準備が完了します
  4. loop関数は繰り返されますので、またSerial.println関数に戻って文字列の表示をします。この時USBモジュールの準備は完了していますので、シリアルモニタに文字列が表示されます
  5. delay(1000);で1秒待ちます
  6. 以下、(4)と(5)の動作の繰り返しなります

まとめると、1回目のSerial.println関数は失敗していたのですが、2回目以降はUSBモジュールが動作しているためうまく出力されているように見えた、というわけです。

本来でしたら第21回の記事で説明すべきですが、while文の説明がその後でしたので、この説明は補足記事にしました。すみません。

 

 

更新履歴

 

日付 内容
2020.1.18 新規投稿