bc-ant_Receiver

BC-ANT-SERIAL でマルチスレーブ

mbed (LPC1768) + BC-ANT-SERIAL で、bc_antライブラリを使ってANTのマルチスレーブを試してみる。

ANT Message Protocol and Usageの 8.2 Implementation using Shared Channels そのまんまをやってみた、のではあるのだけれども...。

/media/uploads/MRSa/_scaled_fig8-4.png

絵で書くと、こういう感じになる。

/media/uploads/MRSa/_scaled_bc-ant-receiver.png

配線

こんな感じ。(細かいところが違うのは気にしない。)

/media/uploads/MRSa/ant-multi_slave1.jpg /media/uploads/MRSa/_scaled_bcantserial-mbed0.png

部品表

品名数量購入先購入コード価格 (2013.05時点)
ブレッドボード BB-8011秋月電子P-05294200円
mbed NXP LPC1768評価キット1秋月電子M-035965200円
DIPスイッチ 2P1秋月電子P-0314150円
抵抗内蔵5mm黄緑色LED(5V用)2秋月電子I-0624610個入り、120円
抵抗 (10kΩ)2秋月電子R-25103100個入り、100円
ブレッドボード・ジャンパーコードセット1秋月電子C-0515965本入り、200円
BC-ANT-SERIAL1amazon.co.jp(販売ページ)3150円

なお、抵抗は購入せず、手持ちのものを使用した。(別に1kΩ程度でも良いかも。)

ANTのメッセージについて

メッセージ構造は、以下のようになっている様子。

/media/uploads/MRSa/ant-message-structure.png

  • 同期バイト : 0xa4 
  • メッセージ長 : データ~チェックサムのバイト数
  • メッセージID : データの内容は、このメッセージIDで決まってくる。
  • チャンネル番号 : チャンネル番号。初期化時に指定する番号。
  • データ : メッセージIDで決められた構造のデータ。
  • チェックサム : メッセージのチェックサム

メッセージIDと構造

ANT Message Protocol and Usage の9.3 ANT Message Summaryに書いてある。

めっちゃ大雑把には、メッセージIDが 0x40 の場合はチャンネル状態、0x4e の場合はデータ、という認識で良いかと。

(0x4eで受けて、0x4fで応答を返すのかな。これは未挑戦。)

  • 0x4e (Broadcast data)の場合には、メッセージ長は9バイト(データ8バイト、チェックサム1バイト)
  • 0x40 (Channel Event)の場合には、メッセージ長は3バイト(データ2バイト、チェックサム1バイト)

Shared Channelの場合のメッセージ構造

Shared Channelを設定した場合には、 Broadcast dataの先頭2バイト(設定で1バイトにも変えられるんだが)がスレーブのアドレスで、残りの6バイト部分が実際にやり取りするときのメッセージ。

先頭2バイトが、0x0001 ~ 0xffff まで、65535個のアドレスがモテるようだ。(ここの部分が0x0000として送信した場合には、ブロードキャストメッセージで、全てのスレーブにメッセージが届く。)

プログラム

ディップスイッチでデバイスのアドレスを設定すると、マスタから送られるその設定したアドレス向けのメッセージとブロードキャストメッセージを受信できるようになることを確認。

処理の内容

  • 電源投入後、DIPスイッチの設定状態を確認する
  • BC-ANT-SERIALを初期化する
    • 共有チャンネルのスレーブ
    • チャンネル番号は0、デバイス番号は65、ネットワーク番号は0、デバイスタイプIDは3
    • 周波数は2404Mhzで、1秒間に16回通信する
    • DIPスイッチの設定に合わせてデバイスのアドレスを設定
  • 0.5秒間隔で、DIPスイッチの設定に合わせ、mbedのボード上LEDを点滅させる
  • データを受信したら、割り込み処理を走らせる
    • USBに受信データのダンプを表示
    • データボディの先頭バイトと0x40でand(論理積)をとって値があれば、p21につないだLEDを点灯させ、ゼロならば消灯させる
    • データボディの先頭バイトと0x04でand(論理積)をとって値があれば、p22につないだLEDを点灯させ、ゼロならば消灯させる

コード

BC-ANT-SERIALでマルチスレーブ

/**  インクルードファイル群 **/
#include "mbed.h"     // http://mbed.org/users/mbed_official/code/mbed/
#include "bc_ant.h"   // http://mbed.org/users/MRSa/code/bc_ant/


/** USBTX - Tranmit on USB  USBRX - receive on USB  **/
Serial pc(USBTX, USBRX);   //  デバッグ用にシリアル端末に出力する

/**  LPC1768 LEDs **/
BusOut myLeds(LED1, LED2, LED3, LED4);    // DIPスイッチの設定に合わせて、点滅させるLEDを変えている

/** for BC-ANT-SERIAL (LPC1768) **/
bc_ant antPort(p13, p14, p15, 9600);    // BC-ANT-SERIALとの接続

/** DIP-SW (ANTの通信ID設定用)  **/
DigitalIn dip1(p20);   // DIP-SW1
DigitalIn dip2(p19);   // DIP-SW2

/** データ出力デバイス(サンプル)  **/
DigitalOut led0(p21);
DigitalOut led1(p22);

/**  ANT用の定義  **/
#define MAX_BUFSIZE              64
#define ANT_CH                   0  // チャンネル番号 (MASTERと合わせる必要あり)
#define DEVICE_NUMBER            65  // デバイス番号 (MASTERと合わせる必要あり)
#define ANT_NETWORK_NUMBER       0  // ネットワーク番号 (MASTERと合わせる必要あり)
#define TRANS_TYPE_SHARED_2BYTES 3  // 共有チャンネルで2バイトアドレス使用する設定
#define DEVICE_TYPE_ID           3  // デバイスタイプID


/** デバイスのアドレス設定 **/
#define ID_1   0x00001   // 1:off, 2:off
#define ID_2   0x00002   // 1:on,  2:off
#define ID_3   0x00004   // 1:off, 2:on
#define ID_4   0x00008   // 1:on,  2:on


/**
 *   DIPスイッチの状態を応答する。 (ONが0, OFFが1)
 *      00  :  4 
 *      01  :  3
 *      10  :  2
 *      11  :  1
 */
int check_DipSw()
{
    if (dip1 == 0)
    {
        return ((dip2 == 0) ? 4 : 2);
    }
    return ((dip2 == 0) ? 3 : 1);
}

/**
 *   デバイスIDから、LEDのIDを設定する
 */
int getLampId(int id)
{
    int lampId = ID_1;
    switch (id)
    {
      case 4:
        lampId = ID_4;
        break;
      case 3:
        lampId = ID_3;
        break;
      case 2:
        lampId = ID_2;
        break;
      case 1:
      default:
        lampId = ID_1;
        break;
    }
    return (lampId);
}

/**
 *   受信したコマンドのタイプををみて、処理を実行する
 */
void executeAction(uint8_t commandType, uint8_t channel, uint8_t command)
{
    if (commandType != 0x4e)
    {
        //   コマンドのタイプが "0x4e : Broadcast Data" ではない場合、何もしない
        return;
    }

    // execute! (とりあえず、LEDを点灯する)
    if ((command & 0x40) != 0)
    {
        led0 = 1;    
    }
    else
    {
        led0 = 0;
    }
    if ((command & 0x04) != 0)
    {
        led1 = 1;    
    }
    else
    {
        led1 = 0;
    }
}

/**
 *  ANT経由でデータを送ります。(AcknowledgedData として、メッセージIDが0x4f)
 */
void sendToAnt(uint8_t *buffer)
{
    antPort.ANT_SendAcknowledgedData(ANT_CH, buffer);
}

/**
 *  ANTからメッセージを受信した時の処理。
 */
void receivedFromAnt()
{
   // 受信したメッセージを receivedBufferに入れ、受信メッセージ長を receivedLengthに格納する。
   uint8_t receivedLength = 0;
   uint8_t receivedBuffer[MAX_BUFSIZE];
   receivedLength = antPort.BC_ANT_RecvPacket(receivedBuffer, MAX_BUFSIZE);

   // コマンド実行。
   executeAction(receivedBuffer[2], receivedBuffer[4], receivedBuffer[6]);

   // 受信データをシリアルターミナルに送出
   printf("RX(%3d):", receivedLength);
   for (int index = 0; index < receivedLength; index++)
   {
       printf("%02x ", receivedBuffer[index]);
   }
   printf("\r\n");
}

/**
 *   ANTポートの初期化。
 */
int initialize_ANTport(bool isReceive)
{
    // リセット
    antPort.ANT_ResetSystem();

    // 共有チャンネル双方向通信のスレーブ
    antPort.ANT_AssignChannel(ANT_CH, ANT_Shared_Bidirectional_Slave, ANT_NETWORK_NUMBER);

    // チャンネルのID設定
    antPort.ANT_SetChannelId(ANT_CH,  DEVICE_NUMBER, DEVICE_TYPE_ID, TRANS_TYPE_SHARED_2BYTES);

    // 1秒間に16回通信、、4つのスレーブが4回受信出来る程度  (20ぐらいまでなら大丈夫そう。それ以上はダメかも。)
    antPort.ANT_SetChannelPeriod_Hz(ANT_CH, 16);   // 16Hz : 32768/16 = 2048

    // 通信する周波数
    antPort.ANT_SetChannelRFFreq(ANT_CH, 4);       // 2404 MHz

    // 通信回線オープン
    antPort.ANT_OpenChannel(ANT_CH);

    // メッセージ受信したら、コールバック関数(receivedFromAnt())を呼び出してもらう設定にする
    antPort.attach(&receivedFromAnt);

    // あー、オレオレ、俺は xx だから、とDIPスイッチ設定でアドレスを設定する。
    // (この設定以降、アドレス向けのメッセージとブロードキャストメッセージしか受信しなくなる。)
    uint8_t buffer[MAX_BUFSIZE] =
    {
        0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
    };
    buffer[0] = check_DipSw();
    antPort.ANT_SendBroadcastData(ANT_CH, buffer);
    return (0);
}

/**
 *   Main Routine
 */
int main()
{
    // 初期化...
    pc.baud(9600);                 // set serial speed between PC and mbed.
    printf("--- INITIALIZE (ID:%d)  ----\r\n", check_DipSw());
    int statusLamp = getLampId(check_DipSw());
    initialize_ANTport(true);      // initialize BC-ANT-SERIAL
    printf("--- READY ----\r\n");

    // 0.5秒おきにランプを点滅させる。(DIPスイッチの設定に合わせたランプを使う)
    while(1)
    {
        myLeds = statusLamp;
        wait(0.5);
        myLeds = 0;
        wait(0.5);
    }
}

送信側(BC-ANT-USB)

プログラム的には、アドレスに2を設定したデータを送り続ける。

BC-ANT-USBの送信側コード(サンプルコード改造版)

/////////////////////////////////////////////////////////////////////
//	BCA_Lib サンプルコード 
/////////////////////////////////////////////////////////////////////
//	送信サンプル (コールバックI/F)
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <string.h>
#include <windows.h>
#include "AntCallbackInterface.h"

//
//	送信コールバック関数
//
void SendFunc(void* dev, unsigned char channel, void* cookie)
{
	int res = 0;
	static unsigned char val = 0;
	unsigned char dat[8];
	memset(dat, val,8);
	val++;

        //  +++++++++++++++++++++++++  ここで、アドレス番号2のやつに送信するよう設定している
	dat[0] = 2;
	dat[1] = 0;
        //  +++++++++++++++++++++++++
       
	// send data
	printf("BCA_SendData():");
	for (int index = 0; index < 8; index++)
	{
		printf(" 0x%02x", dat[index]);
	}
	printf("\n");
	res = BCA_SendData(dev, channel, dat, 8);
}
//
//	main
//
int _tmain(int argc, _TCHAR* argv[])
{
	void* dev = NULL;
	int res = 0;
	//	ANTデバイスのオープン
	printf("BCA_OpenDevice()\n");
	dev = BCA_OpenDevice(0);
	if (!dev) {
		printf("BCA_OpenDevice ERROR:%d\n", res);
		goto end;
	}

	//	ANTデバイスの初期化
	printf("BCA_Init()\n");
	res = BCA_Init(dev);
	if (res != BCA_OK) {
		printf("BCA_Init ERROR:%d\n", res);
		goto end;
	}

	//	送信コールバック関数の登録
	printf("BCA_RegisterSendFunc()\n");
	BCA_RegisterSendFunc(dev, SendFunc, NULL);

	//	 チャンネルのオープン
	printf("BCA_OpenChannel()\n");
	res = BCA_OpenChannel(dev,						//	device
						  0,						//	channel no
						  BCA_CHANNEL_TYPE_MASTER,	//	channel type
						  BCA_CHANNEL_SHARED,		//	shared channel
						  65,						//	device no
						  3,						//	device type
						  3,						//	trans type
						  4,						//	freq
						  16);						//	hz
	if (res != BCA_OK)
	{
		printf("BCA_OpenChannel ERROR:%d\n", res);
		goto end;
	}
	// 
	//	送信中...
	// 
	Sleep(1000 * 80);

	//	チャンネルのクローズ
	printf("BCA_CloseChannel()\n");
	res = BCA_CloseChannel(dev, 0); 
end:
	//	デバイスのクローズ
	printf("BCA_CloseDevice()\n");
	res = BCA_CloseDevice(dev);

	return 0;
}


Please log in to post comments.