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.
