スパイス  組み込み制御装置の受注製作

ライブラリの導入
平成27年3月25日

 PIC32にMODBusを実装する
 ことの始まりは、新規のお客様から他社購入製品の置き換えとして新規に自社の専用装置を設計できないかとの問い合わせでした。
結果的に受注には至らなかったのですが、その見積もり段階での検討としてMODBusをPIC32に実装する上での検討事項の洗い出しが必要になり、ほぼ終わりまで検討した結果を備忘録として残しておきます。

 今回は机上での検討までのため、内容の信憑性はあまり高くないのが現実です。例えばMODBusの仕様を誤って理解しているかもしれません。
他の情報と照らし合わせて矛盾があるようなら疑って掛かった方がいいです。

 MODBusに関しての参考資料は下記が参考になります。ここではMODBusのRTUモードのみを対象にします。
http://www.m-system.co.jp/mssjapanese/kaisetsu/nmmodbus.pdf
http://www.moxa-jp.com/modules/Technical/MGate.cgi

 簡単に特徴を整理すると、  つまり、下記のようにコマンドと応答の間には少なくとも7文字分3.5文字分の空白時間があります。
(H27/04/22訂正)
 空白時間はコマンドと応答の両者の前後に必要ではなく、各コマンドとその応答を分離するために最低一つ分が必要です。
従って、時間軸上の動作も下記のようになります。
コマンド    [空白][コマンド][空白]|      |[次のコマンド]  
--------------------------------------+---------------------------------------------------
応答                 |[空白][応答][空白]                    
応答                 [応答][空白]|                    
(訂正ここまで)

 この要求仕様をPIC32に実装する場合に考えるべき点を順に検討していきます。
1.空白時間の確保と判定
 通信の要求仕様に時間による制約があります。通信の効率を無視してよいなら十分に長い時間を使って処理すれば済みます。例えば1ms単位で計測しているソフトウェアタイマを使って、時間を確保すれば良い。本当にそうでしょうか?
 少しくらい嫌がらせをされても正しく動作するには不十分です。
通信エラーを考慮すると、全てのスレーブが通信内容を常にトレース(マスタからみての送信・受信を正しく追跡している状態)出来ている保障はありません。どこかで通信の再同期が必要になります。通信データはバイナリーですのでアスキーモードのように通信データからコマンドの先頭を判断することは出来ません。結果として再同期のトリガになり得るのは、送受信の切り替わりで発生する7文字分以上の空白時間だけです。つまり、7文字分を超える通信空白時間が空いた最初の通信がコマンドか応答の先頭文字です。
この方法を採用するには通信速度にもよるものの、タイマにはそれなりの分解能が必要です。通信速度を9,600〜115,200bpsとすると、115,200bpsでは1文字分の通信時間はおよそ80us程度です。この程度の分解能が無いと判断は難しいと思われます。
仮に80us単位でソフトウェアタイマを実装する(80us単位に割り込みを発生させる)とすると、多重割り込み発生時にタイマ割り込みを一回取りこぼす危険が考えられます。ハードウェアタイマで計測するべきでしょう。

2.割り込み発生のタイミングと優先度
 これも通信仕様に時間が組み込まれているために検討が必要になります。通信中の文字と文字の間に空白時間が空きすぎるとコマンドや応答の終了とみなされます。通常はシフトレジスタの前段にあるバッファが空になったら割り込みを起こして次の送信データを受け取るようにしますので送信間隔が空くことはないのですが、通信速度が高速でかつ他の割り込み処理で時間の掛かるもの(USBやEtnerなどはそれなりに時間が掛かります)があれば、タイミングによっては通信エラーの要因になり得ます。対策としては送信時には割り込みの優先度を上げておいたほうが良いでしょう。比較的処理時間の掛かる割り込みよりも優先度を上げておきます。反面、受信では8段のFIFOが機能しますのでかなり時間の余裕があります。割り込みの優先度を送信と受信で切り替えるのも有効でしょう。
(201/03/26追記)
 言葉足らずな説明になっていました。送信中の文字同士にどの程度までなら空白時間を許されるかは正確には規定されていないようです。文書から少なくとも送信の終了とみなされる3.5文字分は空けてはならないことは明白です。実際には、そこまできわどい状態では他の装置がどのように判断しているか不明ですので、少なくともこの値に対して十分なマージンを確保した空白時間で留めておくべきです。そうすると精々2文字分多くても3文字分が限界でしょう。送信回路のシフトレジスタが1バイト分ありますので、それを合わせても3〜4文字分の時間以内に送信割り込み処理を終了する必要があります。割り込み処理はその優先度によって複数の割り込み処理が先に実行される状況が起こり得ます。それを加味すれば送信時の割り込み優先度を他の処理に時間の掛かる割り込みよりも上げる必要性が出てきます。
(追記ここまで)
 なお、コマンドや応答の送信終了後に送受信の切り替えが必要になります。それまでは送信間隔が空かないようにFIFOが空になったら割り込みを起こしましたが、最後の送信文字に関しては送信が終了した(シフトレジスタが空になった)後にも再度割り込みを起こして送受信の切り替えを行います。従って、ここでも割り込み発生のタイミングを変更が必要です。送信処理中に割り込み要因を切り替えますので、切り替えの前後には2重のチェックが必要になります。


 なお、今回このような内容を書こうと思った動機はフリーソフトを参考にしてプログラムの開発を依頼されたことによります。
フリーソフトというのは玉石混合状態です。非常に素晴らしいものもありますが、サンプルプログラム程度にしか役に立たないものも多数あります。
アルゴリズムのようにCPUに依存しない内容なら良いのですが、通信のように直接ハードウェアを操作するプログラムでは、ハードウェアの違いを十分に考慮されていないことの方が多数です。特に複数のCPUをサポートするプログラムでは要注意です。現在のマイコン周辺機能はプログラム最下層のハードウェア依存部分だけを幾つかの関数で隠蔽する手法が通用するほど単純では無くなっています。もう少し大きなモジュール単位で書き直しが必要です。
特に汎用的に市販製品を接続する装置を設計するなら、なおさらプログラムには慎重な検討が必要です。

 過去には随分と古い時代に作られたプログラムを基にしてCプログラムへの移植を行ったときに、あまりの処理内容の酷さに作り直しを薦めたことがあります。過去の資産やフリーソフトはある程度管理されていないと「むしろ無い方が速く終わることができた」という結果になりかねません。


目次へ  前へ  次へ