CAN制御機器の製作(5) ホスト・ノード(リレー・ノード用)

can_host_rel1

今回はホスト・ノードのプログラムを説明します。この写真はホスト・ノードとリレー・ノードをCANで接続して作動させたときのものです。デバッグのために1つのブレッドボードにまとめています。

●ホスト・ノードの処理(can_host_relay.ino)

前回説明したCAN送信処理をベースにシリアル通信の処理を追加しました。なお、シリアル通信の部分は「リアルタイムクロックRTC-4543SA /WSN366 ボード (4) 」で使用したシリアルコマンドの処理に手を加えて流用しています。

//
// CAN ホスト・ノード(リレー・ノード専用)
//   13/11/19 www.wsnak.com
//
//   シリアルコマンド制御
//     リレー操作コマンド リレーON "r1"~"r5"、リレーOFF "n1"~"n5"
//

#include <wCan2515.h>

wCan2515 Can(2, 4, 3, 5, CAN_BRP_16MHz_125KBPS);  // CANインスタンス
// D2:SCK, D3:SO, D4:SI, D5:SS (SI/SOクロス)

byte CanBuf[14];    // CAN送受信バッファ

int LedPin = 13;    // オンボードLEDのポート番号

char strBuf[16];
char cmdStr[16];
byte cmdPtr;

// 動的にメッセージを作る関数(範囲オーバしないよう注意)
int makeMsg(int node, byte rynum, byte on_off) {
  return (node<<7) + (rynum<<4) + on_off;
}

// 初期化
void setup(void) {
  byte dat[8];      // データ用バッファ
  int msg = 0x001;  // メッセージID(SID値)
  byte dlc = 0;     // データ長(0バイト)

  Serial.begin(19200);            // シリアル初期化
  cmdPtr = 0;
  pinMode(LedPin, OUTPUT);        // D13のLED用出力ポート

  Can.setOpMode(CAM_MODE_NORMAL);
}

// メインループ
void loop(void) {
  char dat;

  if(Serial.available() > 0) {
    dat = Serial.read();
    cmdProc(dat);
  }

  if(Can.checkTxComp(0)) {
    // 送信完了チェック
    digitalWrite(LedPin, LOW);      // LED OFF(送信完了)
  }
}

//
// シリアルコマンド処理
//
void cmdProc(char dat) {
  byte rn;            // リレー番号
  byte buf[1];        // CANデータバッファ(dummy)
  int msg;

  if(dat == '\r') {   // CR
    cmdStr[cmdPtr] = 0;         // コマンド文字列終了 null挿入
    cmdPtr = 0;

    if(strlen(cmdStr) == 2) {
      // -------------- コマンド処理 ----------------
      rn = cmdStr[1] - '0';     // リレー番号取り出し(1-5)
      if(cmdStr[0] == 'r') {
        // リレーONコマンド
        // メッセージID作成
        msg = makeMsg(1, rn, 1);      // リレーノード識別番号, リレー番号, ON
      } else {
        // リレーOFFコマンド
        // メッセージID作成
        msg = makeMsg(1, rn, 0);      // リレーノード識別番号, リレー番号, OFF
      }

// デバッグ用 メッセージID表示
sprintf(strBuf, "MSG = %03x", msg);
Serial.println(strBuf);

      // CAN送信バッファへ送信メッセージ、データを設定
      Can.setTxBuf(0, msg, buf, 0, true);
      Can.txReq(0);                   // 送信要求発行
      digitalWrite(LedPin, HIGH);     // LED ON(送信中)
      // ------------------------------------------------
    } else {
      // コマンド該当なし
      Serial.print(cmdStr);
      Serial.println(" ?");
    }
  } else if(dat != '\n') {
    cmdStr[cmdPtr++] = dat;     // コマンド文字列蓄積
  }
}

メインループの44行目でシリアルデータの受信を待機します。1文字入力されたら、それを”cmdProc()”へ渡します。この処理でコマンド文字列を組み立てて、コマンドを解析します。

それと、49行目ではCAN送信が完了したかをチェックしています。この辺は前回説明した送信の基本型と同じです。

58行目からシリアルで入力したコマンドを処理する関数です。この関数も基本動作は「リアルタイムクロックRTC-4543SA /WSN366 ボード (4) 」で作った同名の関数とほぼ同じ処理です。

67行目でコマンド入力が確定したら2文字目からリレー番号を取り出し、1文字目でリレーをONするか、OFFするかを判定します。そして、ONかOFFかで、73行目か77行目の処理を実行して、メッセージIDを生成します。81行目は”msg”に正しいID値が入っているかを確認するためのシリアル出力です。

85行目からCAN送信バッファへメッセージとダミーデータ、データ長(0)を設定して、86行目で送信要求を発行します。

●動作状況

次の写真はホスト・ノード(写真手前)にリレー・ノード(写真奥)を接続して作動させているときの様子です。機材の関係で、ホストノードのCANボードはWSN292ではなく、WSN220を使用しています。また、リレーボードも、ブレッドボードに実装するためにWSN353を使用しています。

can_host_rel2

左端の白と黄色の2本線がCAN信号です。電源を共用しているため、結果的にGNDが接続されていますが、電源を別にすれば、GNDの接続は不要です。

ホスト側はWSN283でUSBに接続されているため(電源もUSBから供給されている)、PCと通信できます。Arduino-IDEのシリアルモニタから”r1″を送信すると、リレーがONし、”n1″を送信するとリレーがOFFするのを確認できます。

まだ、これだけでは面白くも何ともないですが、CANケーブルを10mぐらい延長して離れたころで操作するとか、リレーを何個か増設すると多少面白みがでるでしょう。CANのありがたみは、ノードをたくさんつなげてガチャガチャ動き出すと実感できます。

メッセージで切り替えれば、リレーノードを何個もぶら下げることもできます。

D13のLEDはCAN送信中にチカッと点灯します。このLEDが点灯しっぱなしのときは、送信が完了していないと判断でます。

なお、自分以外にノードが1つもつながっていない状態で送信要求を出すと、CANコントローラが自動的に再送を繰り返します。


CANについては下記書籍で説明していますのでよろしければ、ご覧ください。
書籍「動かして学ぶCAN通信」 → 書籍紹介ページ

ArduinoのCAN関係の記事は下記書籍でも扱っています(WSN292など使用)。CANなどの専用ライブラリに付いても解説しています。
書籍「Arduino実験キットで楽ちんマイコン開発」 → 書籍紹介ページ

図やテキストの無断転写はお断りします。

コメントは受け付けていません。