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 そのまんまをやってみた、のではあるのだけれども...。
絵で書くと、こういう感じになる。
配線
こんな感じ。(細かいところが違うのは気にしない。)
部品表
品名 | 数量 | 購入先 | 購入コード | 価格 (2013.05時点) |
---|---|---|---|---|
ブレッドボード BB-801 | 1 | 秋月電子 | P-05294 | 200円 |
mbed NXP LPC1768評価キット | 1 | 秋月電子 | M-03596 | 5200円 |
DIPスイッチ 2P | 1 | 秋月電子 | P-03141 | 50円 |
抵抗内蔵5mm黄緑色LED(5V用) | 2 | 秋月電子 | I-06246 | 10個入り、120円 |
抵抗 (10kΩ) | 2 | 秋月電子 | R-25103 | 100個入り、100円 |
ブレッドボード・ジャンパーコードセット | 1 | 秋月電子 | C-05159 | 65本入り、200円 |
BC-ANT-SERIAL | 1 | amazon.co.jp | (販売ページ) | 3150円 |
なお、抵抗は購入せず、手持ちのものを使用した。(別に1kΩ程度でも良いかも。)
ANTのメッセージについて
メッセージ構造は、以下のようになっている様子。
- 同期バイト : 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.