つれづれなる備忘録

日々の発見をあるがままに綴る

TinkercadによるArduinoシミュレーション5 ~ Arduinoでのシリアル通信

 前回アナログ入力の結果を表示するために、シリアルモニタに値を表示するSerial.println()を使用した。C言語でのprintf()に相当する機能だが、モニタに出力すると同時にシリアル通信の信号がArduinoのTXピンから出力されている。実際にはPCとArduino間でUSBを介して通信している信号をTXピンで観測できるというもの。ここではArduinoのシリアル通信について説明したい。

1. シリアル通信

 シリアル通信とは1本の導線上に1bitづつデータを送受信する通信方式。一方で複数線上を同時にデータを送受信する方式がパラレル通信で、昔のコンピュータの周辺機器(プリンタなど)に用いられている。(現在はシリアル通信が主流になっている。*1 ) シリアル通信には通信デバイス間で通信タイミングを同期する同期式シリアル通信と同期をしない非同期シリアル通信がある。同期式シリアル通信にはI2CやSPIが代表的な方式でArduinoでもサポートされている。非同期シリアル通信を行うデバイスはUART(Universal Asynchronous Receiver Transmitter)と呼ばれるが、UARTと非同期シリアル通信はほぼ同義として扱われることがある。ここではTinkercad上のArduinoを用いた非同期シリアル通信の方法について話を進めていく。 なお非同期シリアル通信に関する解説は、シリアル通信 -第1回:シリアル通信とは: Arduinoで遊ぶブログ技術レポート「シリアル通信とは?」|ソフテックだより|株式会社ソフテックなどを参照するとよい。

2. シリアル通信時にTXピンから出力される波形

 まずシリアル通信の波形をみるためにTinkercadArduinoのデジタルピン1(TX)をオシロスコープ(分割当たりの時間:10ms)に接続し、下のスケッチでシミュレーションを実行した。シリアル通信開始時のボーレートは300bpsとして、文字Aを改行なしでシリアルモニタに100msおきに出力するようにした。シリアル通信の設定はデフォルトで8bit、 パリティなし、ストップビット1となっている。なお文字Aは文字コード(8bitバイナリ表記)で01000001であり下位ビット(一番右の1)から順番に送信される。TXの信号をオシロスコープの波形で観測すると通信前は常に5V(HIGH)になっており、スタートビット0(LOW)になってから10000010でLOW-HIGHのパターンが変化している。最後にストップビット1bitで1を出力する。(Serial.print("A")を2回行うとストップビットが確認できる) 1bit当たりのパルス幅は設定した300bpsの逆数で約3msとなっている。なおシリアルモニタの表示としてSerial.print()を用いたがSerial.println()は表示データに改行コード(\r+\n)が入り、シリアルモニタの表示では改行される。

void setup(){
   Serial.begin(300);
}
void loop(){
  Serial.print("A");
  delay(100);
}

f:id:ATATAT:20200108232221j:plain
シリアル通信時の波形

3. シリアル通信:送信方法

 上の例ではシリアルモニタの表示がTxポートの出力と連動していることと、シリアル通信の波形がどのようなものかを示すためにSerial.print()を用いた。通常のデータ送信ではSerial.write(val)を使うのが一般的で、valをバイナリ形式でTXピンから波形を出力する。Serial.print()についてはデータをASCIIテキストとしてTXピンから出力するので、数値を文字として送信する場合はこちらを用いる。

4. シリアル通信:受信方法

 データを受信するには、他の機器からの送信信号線をデジタルピン0(RX)に接続する。機器同士の通信は複雑なので次回以降に扱うとして、今回はもっと簡単なシリアルモニタ上からの送信を読み込む方法について示す。 シリアルモニタ下の入力窓からデータを入力して、右の送信ボタンをクリックすることでArduinoへデータを送信できる。(下図参照)

f:id:ATATAT:20200111191139j:plain
シリアルモニタからArduinoへのデータ送信
シリアルモニタから'o'を送信するとオンボードLEDが点灯し、シリアルモニタ上に"LED ON"が表示され、'p'を送信するとオンボードLEDが消灯し"LED OFF"と表示するスケッチを下に示す。

void setup(){
    pinMode(13,OUTPUT);
    Serial.begin();
}

void loop(){
   int inputchar;
   inputchar=Serial.read();
   if(inputchar !=-1){
    switch(inputchar){
      case 'o':
        Serial.print("LED ON\n");
        digitalWrite(13,HIGH);
        break;
      case 'p':
        Serial.print("LED OFF\n");
        digitalWrite(13,LOW);
        break;
    }
  }else{}
}

Serial.read()はデータの最初の1byteを読み込み、データが存在しない場合は-1を返す。何か入力があった場合にinputcharが-1以外になりif文内の処理に入る。入力された文字が'o'であれば"LED ON"を表示して13ピンをHIGHとしてbreakで処理を抜ける。同様に入力された文字が'p'であれば"LED OFF"を表示して13ピンをLOWとしてbreakで処理を抜ける。

5. まとめ

 今回はシリアル通信の概要とArduinoのTXピン上でシリアル通信時の波形を確認した。またシリアル通信でデータを送信する方法と受信する方法のスケッチ例を示した。Arduinnoのシリアル通信はいろいろな関数や方法があるので追って紹介していきたい。今回はシリアルモニタとArduino間の通信を取り上げたが次回からはArduino同士のシリアル通信について説明したい。