JUGEMテーマ:電子工作
有線のリモコンとかで使えそうな技術の検証です。
1対1の通信で大丈夫なので、RS485はオーバースペックなんですが、
RS485で実現しておけば、他にも1対多とか多対多とかでも
応用効きそうなので、実験しておきました。
今回使用するのはLTC485CN8です。
データシート
https://www.mouser.jp/datasheet/2/609/485fm-2955265.pdf
電源電圧は5Vで動く。
+14V~-14Vまでバスに電圧かかってもOK
出力はVCCが基準になるって事ですね。
あと、RS485らしく、終端抵抗の事とか書いてるなー
という訳で、ARDUINOとARDUINO互換機の5V版で試験をする。
写真
左下がARDUINO-UNOで、これがマスターです。
左上がUNO互換機で、これがスレーブです。
で、マスターから送信するときの伝送経路
UNO→LTC485→LAN線→LTC485→UNO互換機
で、マスターが受信するときの伝送経路
UNO互換機→LTC485→LAN線→LTC485→UNO
となり、
シーケンス図を書くとこんな感じです。
間にあるLAN線の長さが7メートルになっております。
■回路図
UNO→LTC485→LAN線 が2セットになるので、
片方だけ書きましたが、
間の接続はAはAにBはBに接続します。
■プログラム
プログラムはD13を使ってLTC485のREとDEに接続してあるので、
送信時にHIGHにします。
あとは、普通にSoftSerialですので、
比較的手軽に通信できるみたいです。
1対多に対応する場合はマスターを一つ置いておいて、
マスターさんがスレーブさんの送信権管理して、
1本しかない物理ケーブルの時間割をしてあげればいいと思います。
多対多に対応する場合はスレーブ同士での通信が必要になると思いますが、
この場合でもやっぱマスターさんがうまく
1本しかない物理ケーブルの時間割をしてあげればいいと思います。
□マスター側プログラム
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX,TX
int txden = 13;
void setup(){
pinMode( txden, OUTPUT );
Serial.begin(115200);
mySerial.begin(9600);
digitalWrite(txden, LOW);
Serial.println("start:");
}
int count = 0;
void loop(){
char buf[256];
digitalWrite(txden, HIGH);
sprintf(buf, "com4 write %d¥r¥n", count);
mySerial.print(buf);
Serial.println("point : A000");
delay(10);//送信が終わるまで待つ
digitalWrite(txden, LOW);
count++;
//
unsigned long t1 = millis();
while(1){
unsigned long t2 = millis();
if((t2-t1)>3000){
t1 = t2;
break;
}
if(mySerial.available()>0){
Serial.println("point : A100");
memset(buf, '¥0', sizeof(buf));
int i = 0;
while(mySerial.available()>0){
char val = mySerial.read(); // 受信したデータを読み込む
buf[i]=val;
i=i+1;
if(val=='¥n'){
break;
}
delay(10);
}
Serial.println(buf);
break;
}
}
}
□スレーブ側プログラム
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX,TX
int txden = 13;
void setup(){
pinMode( txden, OUTPUT );
Serial.begin(115200);
mySerial.begin(9600);
digitalWrite(txden, LOW);
Serial.println("start:");
}
int count = 0;
unsigned long t1 = 0;
void loop(){
int nDataExist = 0;
if(mySerial.available()>0){
while(mySerial.available()>0){
int val = mySerial.read(); // 受信したデータを読み込む
Serial.write(val);
nDataExist = 1;
delay(10);
}
}
//
if(nDataExist == 1){
Serial.println("point : 100");
char buf[256];
digitalWrite(txden, HIGH);
sprintf(buf, "ack %d¥r¥n", count);
mySerial.print(buf);
delay(10);//送信が終わるまで待つ
digitalWrite(txden, LOW);
count++;
}
}
■実験結果
オシロで取得した差動信号の模様
思うようにできているみたいですね。
AとBで±逆側に信号が出ています。
試しに7メートルのケーブルはそのままで、
UARTで直結したところ、まったく通信できませんでしたので、
こんな時はRS485が役に立ってくれそうです。
通信速度ですが、今回9600bps設定にして上のサンプルのままで、
電文が100回往復する時間を測定したところ、24秒かかっておりますので、
1回あたりだと、0.24秒です。
電気のリモコンならボタンを押して電気がつくまで0.24秒かかる事になりますが、
ま、こんなもんなのかな?
通信速度9600bpsを早くしていけばそれなりに速度は上がるとも思いますし、
応用次第ですね。
ちなみに、終端抵抗は無しでやってます。
JUGEMテーマ:Arduino