前提・実現したいこと
一つの受信用Arduino(親Arduino)に対して,4つの送信用Arduino(子Arduino)を接続します.
このとき,いつどんな順番で送信されるかわからない子ArduinoからのSerial通信を親Arduinoで受信したいと考えています.
ただし,複数の子Arduinoからの通信は同時に来ることはなく,同時に送信される通信は一つだけです.
最初の方法とその結果
まず行ったのは,下のサンプルコードを実行することです.
Two Port Receive | Arduino
このサンプルでは2つのSoftwareSerialポートを定義し,2つのSerial通信を受信しようとしています.
実験に使った送信側・受信側のソースコードは以下のとおりです.
実験なのでArduinoの数を減らし,送信側・受信側それぞれ一つずつのArduinoで2ポートのSerial通信を試みました.
ほぼサンプルを変更していませんが,うまく受信できていないようです.
ほとんどの場合は,送信側のボタンを押して送信したにも関わらず,受信側のシリアルモニタには何も表示されません.
たまに受信に成功し表示されることはありますが,割合としては20回に1回くらいだと思います.
考えた方法とその結果
そこで,いくつかの解決策を考えて実験してみました.
1. Arduinoの外部にAND回路を追加
前提に書いたように同時に複数の通信が来ることはないので,親Arduinoに接続する4本の線をダイオードで作成したAND回路に接続し,4つの電圧のANDをとった結果を親Arduinoに接続する方法です.実際にこの方法で実験をしてみると正しく受信することができました.しかし,Arduinoの外部にAND回路を作る必要があるという欠点があります.
2. MultiUARTライブラリの利用
このライブラリは,SoftwareSerialでできなかった複数ポートからの同時受信を,最大4ポートまで可能にしてくれます.確かにこのライブラリを利用することで目的は達成されるのですが,下の注意書きが少し心配です.同時に受信するわけでないならもっとシンプルな方法があるのではないかと考えました.
調歩同期のための受信割込処理は非常に重く、16Mhz駆動時でも40%以上の CPUタイムを常に消費する。 16Mhz未満の、あるいは内蔵RC発振器を使用している場合、多くは期待通りに動作しない。 この点で SoftwareSerial の割り切った実装は理に適っている。
3. SoftwareSerialを書き換え
そこで考えたのがSoftwareSerialの受信用ピンを複数設定可能な仕様に変更する方法です.改変したソースコードとそれを使った受信用のソースコードを下に示します.
受信ピンを複数設定可能なSoftwareSerialのソースコード
主な変更点は以下のとおりです.
#define PIN_NUM 4
のように,設定するピンの数を示すPIN_NUM
を定義uint8_t _receivePin[PIN_NUM]
のように,メンバ変数の_receivePin
などを配列に変更SoftwareSerial(uint8_t *receivePins, bool inverse_logic = false);
のように,コンストラクタでは受信に使うピンを配列で渡し,送信はしないため送信用ピンは渡さない- メソッド
rx_pin_read()
では,各ピンのANDをとった結果を返すように変更
このような変更を加え,まずPIN_NUM
を4に設定して実験を行いました.
利用した送信用のソースコードを下に示します.
送信用ソースコード
PIN_NUM
が4だと受信に失敗しました.
下のように,ポート1とポート2から送信されたデータは正しく受信できていますが,ポート3とポート4では失敗しています.
どうやら,ポート3,4では最上位ビットに1が入ってしまうようです.
PIN_NUMが4のときの受信結果 1 10 10000011 10000100 求めている結果 1 10 11 100
ここで言っているポート1やポート2というのは送信用のポートのことですが,今回のソースコードではSoftwareSerialを初期化するときに与えたピンの配列と対応しています.つまりこの場合は,ピン16とピン14で受信した場合は最上位ビットに1が入って,受信に失敗してしまうということです.
ちなみに,この16,14というピン番号が問題なのかと考え,配列内でピンの順番を入れ替えてもpins
の2番目3番目に設定したピンで受信すると失敗します.おそらく,コンストラクタ内でsetRX
が呼ばれる順番が関係しているのだと思います.
Arduino
1uint8_t pins[] = {8, 10, 16, 14}; 2SoftwareSerial portOne(pins);
次にPIN_NUM
を3に変更して実験を行いました.
PIN_NUM
が3の場合は,正しく通信することができました.
質問内容
- Two Port Receive | Arduino このサンプルがうまく動作しないのはなぜか?
PIN_NUM
が4だとダメで,3だとうまくいくのはなぜか?- 目的を達成するために一番良いのはどの方法か?(ここにない方法があれば教えて下さい.)
補足情報(FW/ツールのバージョンなど)
Arduino IDEのバージョン:1.8.15
利用しているArduino:Pro Micro
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/05/28 22:55