マルチマイコン制御 ~ソフトウェア編~

サンプルソフト

まずはサンプルソフトとしてプロジェクトファイルを含む一括ファイルを下記よりダウンロードできます。筆者と同じ開発環境(MPLAB IDE 8.92 + CCS 4.132)の方はそのまま転用できます。
圧縮ファイルにはマスター側とスレーブ側の両方が入っています。

ZT-PIC18F46K2201_MultiPic.ZIP

ライブラリ内の関数について

マルチマイコンのソースに関してはprocess_multipic.cにまとまっており、その中の関数に関してはそれぞれコメントが記述されおり、詳しくはそちらを参照願います。main.cのどこに追加すべきかもソース内で確認願います。

マスター側マイコンで行うスレーブマイコンの設定

スレーブのマイコンの設定についてだけ特記しますが、ハードウェア編で説明があったようにマスター側にスレーブ側マイコンの設定を行う必要があるという点については、process_multipic.cのmultipic_startup関数内で設定する必要があります。

下のソースの下側8行がそれにあたり、1の値で入力、2の値で出力と設定しています。スレーブ側マイコンの構成を変更する場合はここを編集したうえでスレーブ側も設定変更する必要があります。
また、スレーブ側の設定はソース上ではなく電源を入れてスイッチで行います。

以下はprocess_multipic.c内の抜粋

//マルチマイコンの初期値設定
void multipic_startup(){
    int tmp1 = 0;    

    //端末側の起動を待つ
    //ウォッチドッグタイマーリセットとウェイト
    restart_wdt();  delay_ms(250);
    restart_wdt();  delay_ms(250);
    restart_wdt();

    //初期値設定
    pic_target_add = 1; 
    for(tmp1=0;tmp1<16;++tmp1){
        pic_life[tmp1] = 0;
        pic_port3[tmp1] = 0x0000;
        pic_port4[tmp1] = 0x0000;
    }

    //各スレーブのマイコンの仕様を割り当て(スレーブ側の設定と合わせる必要がある)
    pic_mode[1] = 0x02;//端末はすべて出力
    pic_mode[2] = 0x02;//端末はすべて出力
    pic_mode[3] = 0x02;//端末はすべて出力
    pic_mode[4] = 0x02;//端末はすべて出力
    pic_mode[5] = 0x01;//端末はすべて入力
    pic_mode[6] = 0x01;//端末はすべて入力
    pic_mode[7] = 0x01;//端末はすべて入力
    pic_mode[8] = 0x01;//端末はすべて入力    
}

通信プロトコル

先にプロトコルって何?2進数って何?という人は先にグーグル先生に聞いてから読み進めることをお勧めします。

通信手順としてはマスター側マイコンからの問いかけに対して該当するスレーブ側マイコンが応答する流れとしており、マスター側マイコンは何も接続されていなければひたすら応答依頼のコマンドを送信し続けます。
スレーブ側マイコンは自分に割り当てられたアドレスと一致するコマンドが取得できた場合のみ応答します。

マスター側マイコン送信コマンド
コマンド説明
0x01SOH ヘッダ開始
0x05ENQ 照会
0x01Address スレーブマイコンアドレス
0x04EOT 転送終了
入力用スレーブマイコン(アドレス番号1)への値応答依頼
コマンド説明
0x01SOH ヘッダ開始
0x11DC1 装置制御1
0x05Address スレーブマイコンアドレス
0x34DATA PORT3の下2桁
0x12DATA PORT3の上2桁
0x78DATA PORT4の下2桁
0x56DATA PORT4の上2桁
0x04EOT 転送終了
出力用スレーブマイコン(アドレス番号5)への値(0x1234と0x5678)を送信
スレーブ側マイコン送信コマンド
コマンド説明
0x01SOH ヘッダ開始
0x06ACK 肯定応答
(入力データとしてきた場合は否定応答として0x15 NACを返す)
0x01Address 自機アドレス
0x00NULL 空データ
0x00NULL 空データ
0x00NULL 空データ
0x00NULL 空データ
0x04EOT 転送完了
自機(アドレス番号1)が出力設定で出力データが来た場合
コマンド説明
0x01SOH ヘッダ開始
0x06ACK 肯定応答
(出力データとしてきた場合は否定応答として0x15 NACを返す)
0x05Address 自機アドレス
0x34DATA PORT3の下2桁
0x12DATA PORT3の上2桁
0x78DATA PORT4の下2桁
0x56DATA PORT4の上2桁
0x04EOT 転送完了
自機(アドレス番号5)が入力設定で1234と5678のデータを送る場合

通信速度について

シリアルの設定については下記のとおりです。おそらくこのマイコンでは限界かと思います。

  • 速度115200bps
  • データ8bit
  • パリティ無し
  • ストップビット1
  • フロー制御無し

マスター側マイコンからのコマンドは10mSec単位で送信されています。
右の図ではマスター側マイコンのUSARTのTXに2ch(水色の線)を接続しています。対して1ch(オレンジの線)はRXに接続しています。
マスター側マイコンからのコマンドに対して各スレーブ側マイコンがすべて応答されている事を表します。
また、スレーブ側マイコンを8個とした場合、80mSec単位(12.5回/秒)で更新されていることになります。

対して1chはそのままマスター側マイコンのUSARTのTXに接続し、2chはスレーブ側マイコンのTXに接続しています。ダイオード1N4148が分岐基板上にあるため、他の信号は影響受けず、自身の出力した信号だけを取得しており、マスター側マイコンからの8回の要求に対して自身のアドレスに該当する1回にだけ応答している事がわかります。

一つのコマンドを見てみると1.5mSec以内に完了しています。マスター側マイコン内でのI2C処理やほかの処理を考えると10mSec間隔で各スレーブ側マイコンに要求を出すのは妥当な数字と思います。
試しに5mSec間隔で試してみましたがデータの取りこぼしが解決できず安定しませんでした。

メイン処理について

筆者の場合状況に応じて処理をまとめるためにmode(又はstep)という変数を元に全体の処理を管理しています100未満はスタートアップ処理として例えば各機器が問題なく稼働するかのチェックを行う処理を行い、900以下では異常事態を想定した停止処理を入れたりしています。
サンプルプロジェクトのファイルでメイン処理ではスレーブ側マイコンのアドレス5のデータを1に入れるという感じで全ての入力値を出力側に移しているだけになっています。
実際にはここで複雑な処理を追加していくことでハードウェア編で記述したように多くのスイッチや表示灯の処理が行えます。

以下はmain.cの抜粋

if(mode >= 0 && mode < 100){
	mode = 100;
}else if(mode >= 100 && mode < 200){
	//

	if(multipic_process_one != 0){
		multipic_process_one = 0;
		
		//マルチマイコン用
		multipic_process();

		//テスト用に取得した入力値をそのまま出力値として設定する
		//※スタートアップのmultipic_startupで入力用、出力用マイコンのアドレスを指定している。
		//※1~4は出力用マイコン、5~8は入力用マイコンとして指定している
		pic_port3[1] = pic_port3[5];	pic_port4[1] = pic_port4[5];
		pic_port3[2] = pic_port3[6];	pic_port4[2] = pic_port4[6];
		pic_port3[3] = pic_port3[7];	pic_port4[3] = pic_port4[7];
		pic_port3[4] = pic_port3[8];	pic_port4[4] = pic_port4[8];
	}
}else{

}