半田付けしてます

よくわからないまま半田付けしてます

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
  1. --/--/--(--) --:--:--|
  2. スポンサー広告

RS485 と 複数UART とAVR

はい、というわけで、苦手な通信関係ですw

ボート制御で船外機用マイコンと、姿勢制御マイコンを通信させないといけないんですが
はじめは、CAN通信させようと思ったんですが、やろうと思った事に対してオーバースペックかなと思い
もう少しお手軽なRS485を使ってみようということで。

UARTが足りない!!


で、姿勢制御マイコンの方なんですが、GPSとRS485とAVRをUARTで結ばないといけないんですね。
で、使おうとしてるのはmega328で、ハードUARTが1本しかないです。

えー? UARTって複数と通信できたっけ? あ、できないっすかw

で、同様なニーズがよくあるようで、ソフトでGPIOからシリアル通信するライブラリを皆さん書いてるようです。
元々が、シフトレジスタみたいなもんですから、ハードでやらなくても良いわけです。
割り込みは使えないのでポーリングしないといけないわけですが。

で、そんなライブラリはまた例によってChaNさんのとこにありました。

ソフトUARTライブラリ


CHANさんのライブラリはなかなか優秀で
・2線のフツーのUART
・送信受信を1本で済ます1線式
・アセンブラで記述の極小コード 元々がデバッグ用で作ったぽいです

●使い方
・使うポートを設定
・ボーレートを設定
・反転入力、反転出力らしいので、反転バッファを噛ます
これで大体動きました。

・使うポートを設定
ソースコードsuart.Sに

#define OUT_1 cbi _SFR_IO_ADDR(PORTB), 0 /* Output 1 送信ポートを0*/
#define OUT_0 sbi _SFR_IO_ADDR(PORTB), 0 /* Output 0 */
#define SKIP_IN_1 sbic _SFR_IO_ADDR(PINB), 1 /* Skip if 1 受信ピンを1*/
#define SKIP_IN_0 sbis _SFR_IO_ADDR(PINB), 1 /* Skip if 0 */

とありますので、ここらへんを適当にいじります。
オリジナルはプログラムIOを利用して省ピンを狙ってたりします。

・ボーレートを設定
通信速度を設定します。上記のソースコード冒頭にシステムクロックと通信速度の対応表があるので
この表の値を入れます。

#define BPS 138 /* Bit delay. (see above table) */

AVRのストックのクロック1MHzだと、2.4kbpsくらいにしとくと成功しやすいっぽいです。
システムクロックに対してなるべく遅くしておくと良いです。

・反転入力、反転出力らしいので、反転バッファを噛ます
直にマイコンポートにつなげるのも少ないのでこういう仕様かもしれません。
トランジスタなり、汎用ロジックの540かなんかを入れましょう。

実際のコード



mega328にLCDを付けて、tiny2313から適当な文字列を送って表示させます。

●送信側のキモの部分

ほとんどサンプル通りです。1秒おきに送りたいのでディレイ入れてます。

for (;;) {

_delay_ms(1000);//一秒待つ

/* Send message */
s = mess1;
for (;;) {
c = pgm_read_byte(s++);
if (!c) break;
xmit(c);
}
}


●受信側のキモの部分

ソフト受信関数rcvr()は中で無限ループしタイムアウト管理はしてないです。
何らかのアクシデントで、通信中に相手がハングした場合は、WDTでリセットですかねぇ。
なので、通信開始まで受信ルーチンの中で待っててもいいんですが、もったいないので
通信開始までは他の事をやります。

UARTのプロトコルで、通信開始はスタートビットが立ちます。
これが落ちないうちに、受信ルーチンをコールすればよいです。
下のコードでは、PINBの1ピンがONになるかを見に行って
ONになったら、rcvr()をコールして、受信終わるまで無限ループです。

このコードの例は、GPSのNMEAのGPGGAのセンテンスから必要なものをLCDに送ってます。
NMEAは固定長なので、文字数カウントでベタなコードとなってます。
ここらへんもNMEAのライブラリが出回ってますので、そちらを使うとと幸せかもしれません。


for(;;) {

if(PINB & _BV(1)){
for(;;) {
c2 = rcvr();

if( c2 =='$' ){
lcd_gotoxy(0,0);
wc=0;
}
//北緯コンマ以下
if(wc==20){
lcd_putc('N');
}
if(wc>21 && wc<28){
lcd_putc(c2);
}
//東経コンマ以下
if(wc==33){
lcd_putc('E');
}
if(wc>34 && wc<41){
lcd_putc(c2);
}
//位置品質
if(wc==43){
lcd_putc('Q');
lcd_putc(c2);
lcd_putc(',');
}
//捕獲衛星数
if(wc==44){
lcd_putc('*');
}
if(wc>44 && wc<47){
lcd_putc(c2);
}
++wc;
if(wc>77){break;}
}
}
}

というわけで、めでたくGPSから現在地を受け取って、船外機にコマンドを送れることがわかりました。

RS485


これについては、特に難しいことはなく、TxとRxと、送受信切り替え端子をパタパタやると
ノイズに強い差動で遠隔と話しができます。
RS485自体は電気的な規格だけなので、あとは自由です。
プロトコルはUARTまんまです。
チップは秋月のSN75176BPで@\80が安くていいです。
LTCの\150もありますが、違いがわかりませんw

ケーブルはツイストペアケーブルであればよく、LANケーブルとかUSBとか利用できるみたいです。
実験では、ヨレヨレになった1mの平行ビニル線でつなぎましたが、問題ないです。
マジメにLANケーブル使えばまず問題ないでしょう。

今回は、デキの悪い交流発電機と、エンジンのCDIノイズの中での通信となりますので
ノイズ対策という意味であります。

さあ、あれこれ確認できましたから、いよいよ、基板レイアウト入れます。
やあ、長いなあ・・・w







スポンサーサイト
  1. 2015/09/30(水) 10:11:05|
  2. AVR
  3. | トラックバック:0
  4. | コメント:0
<<DCDCコンバータ HRD05003 と コーナン電動ドライバー | ホーム | DCモーター PWM 問題点>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://handa40rou.blog123.fc2.com/tb.php/337-9ca3dd72
この記事にトラックバックする(FC2ブログユーザー)
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。