シリアル通信ってなんだろ?(Arduino詳解)

Arduino詳解その10です。前回の記事はこちらです。
hirocom777.hatenadiary.org

シリアル通信ってなんだろ?

 前回動かしたスケッチは、押したボタンの情報をPC上のシリアルモニターに表示するものでした。それにしても便利ですね。シリアルモニター。データを送ってPCで確認できるのでデバッグにも使えそうです。それに、シリアルモニターからArduinoUNOにもデータを送ることが出来るんじゃないですか?そもそもシリアル通信って何でしょう?今回は、そこのところを紐解いていきましょう!!

シリアル通信とパラレル通信

 シリアル通信とは文字通り通信方法のひとつです。シリアル通信の反対語としてパラレル通信があります。デジタルデバイス間の通信では当然デジタルな値(ピット1か0)をやり取りするわけですが、そのやり取りする方法が異なるのです。 これらの値はある程度まとまって(8ビット、16ビット等)初めて意味を持ちます。

パラレル通信では複数の信号線を用いて一度にまとまったビットをやり取りします。 すべての信号線に値をセットした後にタイミングを見計らって値を伝達します。

シリアル通信では1本(または送信、受信で2本)の信号線だけで全てのデジタル値をやり取りします。

それぞれ長所短所があるのですが現在では半導体技術の進歩などもあり、シリアル通信が主流になっています。ここから先は ArduinoUNOで使用しているシリアル通信を見ていきましょう。

ArduinoUNOのシリアル通信

 いきなりですが、ArduinoUNOの本体のCPU(ATmega328P)自体は直接PCとシリアル通信しているわけではありません。ArduinoUNO内部には本体のCPU以外にATmega16U2というUSBインターフェース付きのマイコンが搭載されています。実際にシリアル通信しているのはこの2つのマイコン間です。ATmega16U2用のドライバー(ArduinoIDEと一緒にインストールされている)をインストールされたPCはArduinoUNOを仮想のシリアル通信対象と認識して通信します。図にすると、以下のようになりますね。

f:id:HiroCom777:20200517132643j:plain

 2つのマイコン間では、お互いのRX(Receive Data:送信)をTX(Transmit Data:受信)に接続してデータのやり取りをします。ATmega16U2は、自身のRXで受信した内容をUSB経由でPCに送信し、PCから受信した内容をTXから送信します。
本体のCPU(ATmega328P)側のRX,TXは、ArduinoUNOのD0,D1が割り当てられています。そういえば、RX,TXってどこかで出てきましたね。以下の写真の右側にRX,TXの表記があります。

f:id:HiroCom777:20200318215242j:plain
ArduinoUNOのD0,D1はシリアル通信に使用されるということです。シリアル通信はPCとArduinoUNOの通信は勿論、スケッチの書込みなんかにも使用します。今まで紹介したスケッチはD2以降のデジタル信号を使用していたのはこのためです。D0,D1も使えないことはないのですが、使わない方が無難です。GROVEのシールドモジュールもD2から始まっていますよね。実は、その隣にUARTと表記されているコネクタがあるのですが、D0,D1はここに出ています。UARTって"非同期シリアル通信"って意味です。
f:id:HiroCom777:20200327203719j:plain
シリアル通信を開始する前に、通信する者同士の設定をそろえておかなければなりません。何点かあるのですがArduinoではデフォルトで固定されている項目が殆んどで、決めなければならないのは通信速度のみです。前回のスケッチのsetupに"Serial.begin(9600)"とあったと思います。また、シリアルモニターの右下にも9600bpsって選択しましたよね。これが通信速度の指定です。bpsは単位でビット/秒です。1秒あたり9600ビットを通信するって意味です。

ArduinoUNOを制御してみる

 前回は、 ArduinoUNOからPCに文字データを送信するだけでした。今回は、更にPCからも送信してみましょう。PCからArduinoUNOを制御できるってことです。
 ハードウェアですが、ベースモジュールのD2,D3.D4のコネクタにそれぞれLEDモジュールを接続します。D2,D3.D4と表示されているコネクタに繋げてください。
そして、今回用意したスケッチは以下になります。

void setup() {
  pinMode(2 , OUTPUT );
  pinMode(3 , OUTPUT );
  pinMode(4 , OUTPUT );
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()) {
    int inputNumber = Serial.parseInt();
    for (int i = 2 ; i  <= 4; i++ ) {
      if (inputNumber  == i  ) {        //対象ポートをONにする。
        digitalWrite(i , HIGH);
        Serial.print("PORT ");
        Serial.print( i );
        Serial.println(" ON");
      } else if (inputNumber  == -i ) { //対象ポートをOFFにする。
        digitalWrite(i , LOW);
        Serial.print("PORT ");
        Serial.print(i);
        Serial.println(" OFF");
      } else if (inputNumber > 9) {   //全ポートをONにする。
        digitalWrite(i , HIGH);
        if (i == 4) {
          Serial.println("ALL PORT ON");
        }
      } else if (inputNumber < -9) {  //全ポートをOFFにする。
        digitalWrite(i , LOW);
        if (i == 4) {
          Serial.println("ALL PORT OFF");
        }
      }
    }
  }
}

動かしてみる

早速書き込んで動かしてみましょう 。書き込みが完了したら、起動しているArduinoIDEのメニューから ツール→シリアルモニターと選択してください。前回と同じですね 。

f:id:HiroCom777:20200504191100j:plain
右下の通信速度も9600 bpsと選択するのは前回と同じです。
f:id:HiroCom777:20200504191208j:plain
この状態で一番上の送信欄に"2"など数字を入力してみてください。LEDモジュールがON/OFFするとともに、シリアルモニターに以下のように表示が出ると思います。
f:id:HiroCom777:20200517155455j:plain
このスケッチは入力した番号のポートをON/OFFできます。"2"と入力するとD2に接続されたLEDモジュールがONとなり、"-2"と入力するとOFFとなります。10以上の数字で全部のLEDモジュールをON、-10以下の数字で全部のLEDモジュールをOFFします。また、確認用として実行した結果をシリアルモニターに表示しています。

スケッチの解説

 さて、setupなんですが、前回とほとんど一緒です。設定が出力に変わっただけですね。loopの中にはSerialオブジェクトのメソッドが使われています。

Serial.available()

 シリアルポートから読み取り可能なバイト数(文字数)を返します。シリアルポートに受信データがあるかどうかを確認するときに使います。今回はif文の条件として使用しています。PCから入力があった時に処理を実行するって感じです。外部からArduinoUNOに入力して制御する時などは必ず使用しますので覚えておきましょう。

Serial.parseInt()

 シリアルポートからlong型の整数値を読み取ります。Serialオブジェクトではデータ型によってメソッドが異なります。(浮動小数点ならSerial.parseFloat()、文字列ならSerial.readBytes()など)

奥が深いシリアル通信

 どうですか?PCからArduinoUNOが制御できるようになりました。実は、今回もっといろいろ書きたかったんですが記事が長くなりすぎてしまうので、今回はここまでとしておきます。また、別の機会にお話しさせてください。次回は、ちょっと趣向を変えてGROVEシステムモジュールの紹介やらなんやら書きたいと思います!!
hirocom777.hatenadiary.org


Arduino UNO入門の連載記事はコチラからどうぞ!!