第47回 補足 – !Serial

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

シリアルモニタ

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

シリアルモニタの基本的な使い方は第21回の記事で説明した通りなのですが、Arduino Microでシリアルモニタを使用する際は注意点があります

この補足記事ではその問題の中身と対処方法を説明します。

Arduino Microのシリアルの問題点

Arduino Microでシリアルモニタを使おうとして、次のようなスケッチを書いても実はうまく動きません。

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

void setup() {

  Serial.begin(9600);  // シリアル初期化

  Serial.println("シリアルモニタを開始しました!");  // シリアルモニタにテキストを表示

}

void loop() {
  // loopでは何もしない
}

このスケッチでは、setup関数の中でSerial.printlnを使って「シリアルモニタを開始しました!」というテキストを表示する、とてもシンプルな制御をしています。

もしお手間でなければ、実際にこのスケッチをコピペしてArduino Microで動作させてみてください。おそらくシリアルモニタに何も表示されないと思います。

しっかりとSerial.begin(9600);と書いたあとにSerial.println関数でテキストを表示しているのに、表示されないのは謎ですよね。

これから、この問題の原因と対処方法について説明していきます。

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

シリアルモニタはUSB経由でデータ通信を行っています。

ArduinoボードのUSBの通信方法は、大きく分けて2種類あるんです

これからその2種類の特徴について説明します。


次のArduinoボードは「Arduino Uno R3」という製品で、2023年までは定番のボードでした。(現在は後継の「Arduino Uno R4」が定番ボードになっています)

このボードには、本体部品(マイコン)のほかに、外部とUSBで通信するためのUSB通信モジュールが搭載されています。

このように専用のUSB通信モジュールが搭載されているArduinoボードでは、先ほどのスケッチでシリアルモニタに文字が表示されない、ということはありません。


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

Arduino Uno R3にくらべると、ずいぶんスッキリしてますよね。

Arduino MicroにはUSBで通信するための専用の通信モジュールが搭載されていないんです。

でも今まで、Arduino MicroをUSBケーブルでPCに接続してスケッチを送ったり、シリアルモニタに文字を表示したりしてましたよね。

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

ただ、シリアルモニタでUSB通信をする場合、この組み込まれているUSB通信機能はすぐに使えない状態になっています。

このUSB通信機能をシリアルモニタで使うには、Serial.begin関数によりUSB通信の機能が動作を開始して使えるようになります。

ただし、Serial.begin(9600);の後、ほんのちょっとの時間(せいぜい数ms)、準備に時間がかかります

このほんのちょっとの準備時間が、シリアルモニタに表示できない原因になっています。そこで、もう一度スケッチを確認してみましょう。


先ほどのスケッチがうまく動かなかった原因は、次のようにSerial.begin(9600)でUSB通信機能を準備しますが、その準備が終わる前にSerial.println関数でテキストを表示しようとしたため、シリアモニタに何も表示されませんでした。

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

それでは次に、「USB通信機能の準備が終わるまで待つ」という処理をスケッチにどのように書けばよいのか説明します。

シリアルが準備できるまで待つ処理

Arduino Microでシリアルを使用する場合、スケッチには次のように書きます。(setup関数のみ示しています)

setup() {

  Serial.begin(9600);  // シリアル初期化

  // USB通信機能の準備ができるまで待つ
  while( !Serial ) {
  }

  Serial.println("シリアルモニタを開始しました!");  // シリアルモニタにテキストを表示

}

「USB通信機能の準備ができるまで待つ」という処理は、このスケッチの6〜7行目の部分です。

つまり、Serial.begin関数のあと、Serial.println関数を使う前に次の2行を追加すればOKです!

while( !Serial ) {
}

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

whileの条件として、Serialという変数(のようなもの)を使っています。

Serialはスケッチでは宣言していませんが、これはArduino IDEが裏で宣言してくれていますので、どのようなスケッチでも使うことができます。

このSerialは、USB通信機能の準備ができていない場合は「0」、準備ができた場合は「1」になります

また、Serialの前についている!は否定の意味の記号です。

ちょっとややこしくなりますが、USB通信機能の準備ができていないとき、Serialの値は「0」ですので、!Serialその否定で「1」になります。

whileは条件が0以外の時に繰り返す制御をしますので、while( !Serial )は、準備ができていない間繰り返す、という意味になります。

つまり、次の処理は「USB通信機能の準備ができていない場合、何もしないをずっと繰り返す」という動作になります。

while( !Serial ) {
}

なんだかややこしいですが、Arduino Microでシリアルモニタを使う場合、深いことは考えずにこの2行が必要って覚えておけばOKです!

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

第21回のシリアルモニタの解説記事で使用した次のスケッチでは、シリアルモニタの準備ができるまで待つ、ということをしていませんでした。

/*
* 内容: シリアルモニタのテスト
*      1秒に1回データを送信する
*/

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

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

でもこのスケッチをArduino Microボードに送ってシリアルモニタを動作させると、問題なく「シリアルモニタのテスト」という文字が表示されます。

これはloop関数により何度もSerial.println関数で文字を表示しているためです。上のスケッチのケースでは、初めてのloop関数の処理のSerial.printlnによる表示は失敗しています。

もう少し詳しく処理を追うと、次のようになっています。

  1. setup関数の中でSerial.begin(9600);によりUSB通信機能の準備を開始します。
    この段階ではUSB通信機能によるシリアルは使えません。
  2. 次にloop関数を実行します。
    loop関数の最初はSerial.println関数によりシリアルモニタに文字列を表示しようとしますが、この段階ではまだUSB通信機能の準備できていませんので、この文字列は表示されません。
  3. 次にdelay(1000);で1秒待ちます。
    この間にUSB通信機能の準備が完了し、Serail.printlnが正しく動作するようになります。
  4. loop関数は繰り返されますので、再度Serial.println関数が処理されて文字が表示されます。
  5. delay(1000);で1秒待ちます
  6. このあと、の動作の繰り返しなります

更新履歴

日付内容
2020.1.18新規投稿
2021.8.27新サイトデザイン対応
2025.1.17説明内容一部変更
通知の設定
通知タイミング
guest


1 コメント
新しい準
古い順 一番投票が多い
本文中にフィードバック
全てのコメントを見る
あああ
あああ
3 年 前

とてもわかり易いです!ありがとうございます!

最終更新日 3 年 前 ( あああ )