目次
前
次
RS485通信エミュレート
Arduinoには、RS485通信を扱うライブラリがあります。
RS485は1対Nの通信ですが、これをRS232Cでエミュレート
できるのではないのかと考えて、実験。
ArduinoのRS485通信ライブラリでは、Serialを拡張して
いるのが、ソースコードの閲覧でわかるため、RS232Cの
処理でも、いけるはずと考えました。
1台のマスターを用意し、2台のスレーブと情報
交換する環境を想定します。
1対Nの通信をエミュレートするので、次のような
情報交換仕様を考えました。
マスターがコマンドを送信し、スレーブが情報を返送。
通信シーケンスは、以下。
半二重通信をしているので、受信データを
取りこぼさないように、次の受信割込みで
確実に受信バッファにコマンドが入る仕様
を考えました。
void serialEvent1()
{
byte ch ;
if ( Serial1.available() > 0 ) {
/* get 1 character */
ch = Serial1.read();
/* store */
*(srbuf+srindex) = ch ;
/* increment */
srindex++;
/* judge */
if ( ch == '\r' ) {
srindex = 0 ;
srflag = ON ;
}
}
}
この方式で、コマンドを受信したとき、マスターには
情報返送ができないと、実験でわかりました。
コマンドに応答しているスレーブのIDとコマンドを
返送情報の前に入れたので、コマンドとレスポンス
の区別ができない、デッドロック状態が発生。
はじめのうちは、デッドロックになる理由が不明
でしたが、コマンドおよびレスポンスを書き出し
して、何がおきているか、わかりました。
コマンドとレスポンスを、時系列で書き出してみます。
MASTER R1
↓
SLAVE#1 R1,1234 (send response)
SLAVE#2 R1,1234 (get command)
↓
MASTER R2
↓
SLAVE#1 R2,5678 (get command)
SLAVE#2 R2,5678 (send response)
スレーブが、レスポンスをコマンドと誤解しないように
次の2条件を入れて対応すればよいはず。
- コマンドは英大文字、レスポンスは英小文字で、レスポンスは無視
- IDが一致しなければ、無視
この仕様で、受信割込みを記述すると、以下。
void serialEvent1()
{
byte chx ;
byte ii ;
char xcmd ;
word gid ;
if ( Serial1.available() > 0 ) {
/* get 1 character */
chx = Serial1.read();
/* store */
*(srbuf+srindex) = chx ;
/* increment */
srindex++ ;
/* judge start trigger */
if ( chx == '\r' ) {
/* set event flag */
sslag = ON ;
/* clear pointer */
srindex = 0;
/* default */
cflag = 0 ;
/* ? command */
xcmd = *(srbuf+0);
if ( xcmd == 'R' ) { cflag |= (ON << 1); }
/* ? myid */
gid = *(srbuf+1) ;
gid <<= 8 ;
gid |= *(srbuf+2) ;
if ( gid == myidx ) { cflag |= ON ; }
/* copy command and parameters */
if ( cflag == 3 ) {
for ( ii = 0 ; ii < 12 ; ii++ ) { *(mbcbuf+ii) = *(srbuf+ii); }
}
}
}
}
コマンドもレスポンスも、受信バッファに一時保存し
受信バッファ内のコマンドとIDを確認後、コマンドと
IDを複写し、対応した処理を実行できるようにします。
目次
前
次