つれづれなる備忘録

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

TinkercadによるArduinoシミュレーション6 ~ Arduino同士のシリアル通信

 前回はArduinoのシリアル通信で、シリアルモニターとの入出力の方法やTXポートからの出力波形がシリアル通信の信号になっていることを確認した。今回は、Arduino同士を接続してシリアル通信する方法について説明する。

1. Arduinoから別のArduinoへ送信

 1台目のArduinoの情報を2台目のArduinoへ送信するための構成を下図に示す。Tinkercad上でArduinoを2台配置し、1台目のTXピンと2台目のRXピンを接続し、GND同士も接続しておく。Arduinoが2台ああり、コードは右上のメニューから1台目と2台目を切り替えることができる。

f:id:ATATAT:20200114231337j:plain
Arduino同士のシリアル通信
ここではArduino1内でカウンタをカウントアップしていき、カウンタの値をArduino2へ送信し、Arduino2のシリアルモニタで受信したArduino1のカウンタ値を表示するスケッチを考える。Arduino1のloop関数内でcount++としてカウントアップしていき、Serial.write(count)とすることでcountの値を送信する。Arduino2では前回と同様にSerial.read()とすることで受信したデータ1バイトを読み出しrecByteに格納するが、データを受信していないときは-1を返すので、if文内でrecByteが-1でないときに処理に入るようにしてSerial.println(recByte)とすれば受信したデータであるArduino1のカウント値を表示することができる。なお1バイトで送受信しているためカウント値は255を超えると1に戻る。

//送信側Arduino1のスケッチ
int count=0;

void setup(){
 Serial.begin(300);
}

void loop(){
  count++;
  Serial.write(count);
  delay(500);
}
//受信側Arduino2のスケッチ
int recByte;

void setup(){
  Serial.begin(300);
}

void loop(){

 recByte=Serial.read();
 if(recByte != -1){
   Serial.println(recByte);
  }
}

2. Arduinoのアナログピンから読み取った電圧を別のArduinoへ送信

 今度はArduino1のアナログピンで読み取った電圧値をArduino2へ送信し、Arduino2のシリアルモニタに表示する。今回はArduino1のアナログピンには(定電圧)電源を接続する。Tinkercadで扱えるセンサは出力が小さく、アンプ回路を別途組む込む必要があるので、単純に定電圧電源を接続してセンサとして見立てることにする。なおアナログ入力は5Vまでが有効な電圧範囲である。基本的には上と同じ構成で、電源の出力をArduino1のアナログ入力ピンA0に接続している。

Arduinoへの入力を別のArduinoへシリアル通信する構成
Arduinoへの入力を別のArduinoへシリアル通信
スケッチは以下のようにした。送信側Arduino1ではanalogRead(A0)として電圧を読み取り、その値をSerial.write()で送信することができるが注意点が1つある。それはアナログ入力ピンは10bitつまり5Vを0~1023の範囲で読み取るのに対してSerial.write()は1バイト(8bit)で5Vを0~255の範囲で表現しなければならないという点である。スケッチではanalogRead(A0)で読み取った値を4で割った値をunsigned int8型(uint8_t)の変数で取り扱うようにした。また送信の処理を関数send()として定義してloop関数内で呼び出す。
 次に受信側のArduino2のスケッチではデータを受信の有無の判定についてはSerial.available()を用いている。Serial.available()は受信したデータのバイト数を返す関数で、if文により0よりも大きければSerial.read()でデータを読み取る。読み出しdata自体は0~255の整数なので、まずfloat型にキャストした後に5/255を乗算することで電圧に変換し、シリアルモニタに表示させるようにしている。以上の処理を受信用の関数Read()として定義してloop関数内で呼び出す。

//送信側Arduino1のスケッチ
void setup()
{
  Serial.begin(9600);
}

void send() // 送信用の関数
{
  uint8_t data=analogRead(A0)/4; //1024→256へ変換
  Serial.write(data);
}

void loop()
{
  send();
  delay(500);
}
//受信側Arduino2のスケッチ
void setup()
{
  Serial.begin(9600);
}
void read() //受信用の関数
{
  if(Serial.available()){    //受信データが0バイトよりも大きいか
     uint8_t data=Serial.read();
     float val=(float)data*5/255; // uint8_t→float型にキャストしてから、電圧に変換
     Serial.println(val);
  }
}
void loop()
{
  read();
}

Tinkercadのシミュレーションを実行しArduino2のシリアルモニタの表示される値がArduino1に入力されている電源のノブを動かすのと連動していることが確認できる。

3. まとめ

 今回はArduinoから別のArduinoにデータを送信・受信する方法を取り上げた。またアナログ入力ピンの電圧値を取得して、シリアル通信で別のArduinoに送信する方法についても説明した。今回はアナログピンへの入力は定電圧電源を用いたが、センサをアナログピンへ入力する場合も同様の方法が使える。(実際にはセンサへの給電やセンサ出力の増幅等のレベル合わせが必要)ここまでで、有線ではあるがセンサの出力を取得しシリアル通信で別のデバイスへ送信するというIoTデバイスの実装の基礎になっている。