Imaginary Code

from kougaku-navi.net

Arduinoのシリアル通信でint型のデータをやりとりする

Arduinoのシリアル通信のメモです。1回のSerial.write()で送れるデータは1バイト、すなわち数値として表現できる範囲は0〜255です。int型ならもっと広い範囲の数値(-32768〜32767)を扱えるわけですが、intは2バイトなのでこれを送受信するにはちょっと工夫が必要です。

要点

送信側では、

  • int型のデータを上位バイトと下位バイトに分けて送信する
  • データを正しい順序で受信するためにヘッダをつけて送信する

受信側では、

  • 3バイト(ヘッダ+int)以上のデータが着ているか確認
  • データが着てたらまずヘッダがあるか確認
  • ヘッダがあったら、下位バイトと上位バイトを読み取り、その値を合体してint型のデータを復元

Arduino同士の通信

例として、2個のArduino間のデータの送受信を考えます。配線はこんな感じです。

GNDとGND、VinとVin(または5Vと5V)をつなぎます。これで片方のArduinoからもう片方のArduinoに向かって電力供給されます。通信線は送信側のTxが受信側のRxにつながるようにします。なお、通信線の配線はArduinoにプログラムを書き込んでから行ってください(書き込み時に干渉が起こるからです)。


プログラム例を以下に示します。きちんとint型のデータが送受信できているかを確かめるために、Arduino1から「12345」と「-12345」の2種類のデータを交互に送り、受け側のArduino2でどちらのデータがきたかチェックして13番ピンに繋がっているLEDをON/OFFします。500ms間隔でLEDが点滅すればOKです。

送信側プログラム(Arduino1)
void setup() {
  Serial.begin(9600);
}

void loop() {
  sendIntData(12345); // int型データの送信
  delay(500);
  
  sendIntData(-12345); // int型データの送信
  delay(500); 
}

// int型のデータを送信する関数
void sendIntData(int value) {
  Serial.write('H'); // ヘッダの送信
  Serial.write(lowByte(value)); // 下位バイトの送信
  Serial.write(highByte(value)); // 上位バイトの送信
}
受信側プログラム(Arduino2)
int recv_data; // 受信データ

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

void loop() { 

  // 受信バッファに3バイト(ヘッダ+int)以上のデータが着ているか確認
  if ( Serial.available() >= sizeof('H') + sizeof(int) ) {
    // ヘッダの確認
    if ( Serial.read() == 'H' ) {
      int low = Serial.read(); // 下位バイトの読み取り
      int high = Serial.read(); // 上位バイトの読み取り
      recv_data = makeWord(high,low); // 上位バイトと下位バイトを合体させてint型データを復元
    }
  }

  // 受信したデータに基づいてLEDをON/OFF
  if ( recv_data == 12345 ) {
    digitalWrite(13, HIGH);
  }
  if ( recv_data == -12345 ) {
    digitalWrite(13, LOW);
  }
}

参考文献

Arduinoならいい感じの関数がありそうな気がしますが、本にこのテクの記載があるくらいなので、ないのかな。

Arduino Cookbook

Arduino Cookbook

追記

こちらもあわせてご覧ください。

Processing・Arduino間でのint通信の説明ですが、「ヘッダと数値が同じ値になる問題」についての解決策について書きました。Arduino同士の場合にも使えるテクです。