1対多シリアル通信
Arduinoを使った1対多のシリアル通信をやってみました.Arduino Duemilanove(UNO)はI2C通信が使えるのです が,この場合アナログ4,5ピンが使用されるので,アナログを6ポートとも使い たい場合には使えません.
それでシリアル通信を使って1対多の通信をやってみました.
その様子↓
手書きメモ
ホストはハードウェアシリアルを使う.
ターゲットはハードウェアシリアルの受信と,ソフトウェアシリアルの送信を使う. ホスト側のTXをターゲットのRXに並列接続. ターゲットのTX(ソフトウェアシリアルでデジタル3ピン)は100Ωの抵抗を 介してホストのRXに並列接続.
ホストからの送信は,ターゲットが並列に受信.
ターゲットは自分が呼ばれたら応答をソフトウェアシリアルで返す.
ターゲットのソフトウェアシリアルのTXは, 通常はピンモードを強制的にINPUTにしてハイインピーダンス状態.
送信時だけピンモードをOUTPUTにして送信. 送信後にピンモードをINPUTに戻して,ターゲットデバイスの並列なTXとの 干渉を防ぐ.
※このモード切替がハードウェアシリアルではできなかったのでターゲットからの 送信にはソフトウェアシリアルを使った.
ホスト側のスケッチ
#include < MsTimer2.h> int ch=0; void recvStr(char *buf) { int i = 0; char c; while (1) { if (Serial.available()) { c = Serial.read(); buf[i] = c; if (c == '\n') break; i++; } } buf[i] = '\0'; // \0: end of string } // ---------タイマー処理 ---------- void fTimer() { if (ch==0) ch=1; else ch=0; // チャンネルの切替 sendRequest(ch); } void sendRequest(int num){ Serial.print("Q"); Serial.println(num); } void setup(){ // 状態表示のためにタイマーセット MsTimer2::set(2000, fTimer); // 2s 周期でタイマー割込み MsTimer2::start(); Serial.begin(9600); } void loop() { char str[90]; // string buffer if (Serial.available()) { recvStr(str); Serial.println(str); } }ターゲット側のスケッチ
#include < SoftwareSerial.h> char ch[]="Q0"; // ここでデバイス側のチャンネルを指定 char rs[]="R0"; // 受信文字列をそのまま返すとループに陥るので応答を変える SoftwareSerial mySerial=SoftwareSerial(2,3); // 3のTXしか使わない void recvStr(char *buf) { int i=0; char c; while (1) { if (Serial.available()) { c = Serial.read(); buf[i] = c; if (c == '\n') break; i++; } } buf[i] = '\0'; // \0: end of string } void setup(){ Serial.begin(9600); mySerial.begin(9600); pinMode(3,INPUT); // 一旦TXを絶縁状態にする } void loop() { char str[90]; // 文字列バッファ if (Serial.available()) { recvStr(str); if(strncmp(str,ch,2)==0) { pinMode(3,OUTPUT); mySerial.print(rs); mySerial.println(" response"); pinMode(3,INPUT); } } }
ESP32 Wifi Bluetooth開発ボード |
Arduino Nano Every |
Raspberry Pi pico |
FPGA XILINX Artix-7 |