9.その他のセンサーの使用 TOPへ

10.Bluetooth通信


NXTの特徴として、Bluetooth通信があります。 Bluetooth通信とは短距離無線通信技術の一つであり、また無線通信の規格の一つです。 このBluetooth通信は次のような特徴を持ち、携帯電話などの様々な携帯端末に用いられています。 Bluetooth通信ではマスター(master)機1つに対して規格上では最大7台のスレーブ(slave)機を接続できます。通信はマスター・スレーブ間のみで可能で、スレーブ間での通信はできません。
Bluetoothには様々なバージョンや規格があり、NXTのBluetoothはVer.2.0でシリアル通信機能を有しています。 また、Bluetoothの通信距離・電波強度を定める規格をクラスと呼んでおり、NXTに実装されている Bluetooth は10mまでの通信を保障する Class2 です。NXT はは PC との間で Bluetooth 通信することも可能ですが、ここではNXT同士でBluetooth通信を行うプログラムについて学習します。なお、NXTのマスター機は1台のスレーブ機としか通信できません。

なお、以下のプログラムでは、スレーブ機を受信側、マスター機を送信側としていますが、スレーブとマスターの送受信の関係を反対にすることも可能ですし、送受信の両方を行うことも可能です。

1.マスター側のプログラム

以下に、1から10までの整数を1秒おきに送信するマスター側のプログラムについて説明します。
次のプログラムを blue_master.c として作成し、ビルドしたものをマスター側のNXTへダウンロードしてください。
blue_master.c
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"

// NXT Bluetooth 設定
// bluetoothパスキー
#define BT_PASS_KEY "1234"
// bluetooth送信パケットの大きさ 
#define BT_SNV_BUF_SIZE 32
// 送信データのリセット値 
#define COUNT 10

// スレーブNXTのデバイスアドレス
const U8 BT_ADDR[7] = {0x00,0x16,0x53,0x01,0x85,0x83,0x00};	
// bluetooth送信パケットァの宣言、   U8 は unsinged char (1バイト)
U8 bt_send_buf[BT_SNV_BUF_SIZE];

DeclareCounter(SysTimerCnt);
DeclareTask(Task1);

void ecrobot_device_initialize(){
	//Bluetoothデバイス設定 デバイス名を新たに設定したい場合のみ、以下のコメントアウトをはずす。
	//ecrobot_set_bt_device_name("NXT51");

	//スレーブのアドレスを指定して、マスターとして初期化 
	ecrobot_init_bt_master(BT_ADDR, BT_PASS_KEY);	
}

void ecrobot_device_terminate(){
	// bluetooth通信終了 
	ecrobot_term_bt_connection();		
}

void user_1ms_isr_type2(void){}

TASK(Task1)
{
	int i=0;
	unsigned int send_len;

	while(1){

		if( i < COUNT ){
			bt_send_buf[0] = i; // bt_send_buf[0] には i(int 型)の下位1バイトが代入さえる
			send_len = ecrobot_send_bt_packet(bt_send_buf, BT_SNV_BUF_SIZE);//buf のデータを送信
			display_goto_xy(0,1);
   			display_string("Sending ");
			display_goto_xy(8,1);
			display_int(i, 2);
			display_update();
			i++;				
		}else{
			i = 0;					
		}
		systick_wait_ms(1000);	// 1秒待つ
	}

	TerminateTask();					
}

blue_master.c で用いた Bluetooth 通信の API について説明します。

ecrobot_init_bt_master(BT_ADDR, BT_PASS_KEY);
NXTをマスターとして初期化します。
第一の引数は、スレーブ側のNXTのアドレスです。アドレスを調べる方法については下の※で示します。
第二の引数は、通信を確立するためのパスキーです。(マスター側とスレーブ側で同じ値を保持する必要があります。)
この関数は、NXT起動時の処理を記述するフック関数内に記述します。

ecrobot_term_bt_connection();
bluetooth通信を終了するAPIです。
この関数は、NXT終了時の処理を記述するフック関数内に記述します。

ecrobot_send_bt_packet(bt_send_buf, BT_SNV_BUF_SIZE);
データを送信するAPIです。戻り値は送信したデータのバイト数となります。
第一の引数は、送信バッファの名前(配列名)を指定します。
第二の引数は、送信バッファのサイズ(バイト数)を指定します。最大値は256[byte]です。

※スレーブ側NXTのアドレスの調べ方
  1. スレーブ側NXTにスレーブ用プログラムをダウンロードします。
  2. スレーブ側プログラムを起動し、OSEKの画面にします。
  3. 画面上の BT_ADDR: の下に表示されている14桁の数字がbluetooth通信用のアドレスですので、この文字を控えます。
  4. たとえば、スレーブのBT_ADDRが「00165304F1B300」と表示された場合、マスター用のプログラム中の BT_ADDR に {0x00,0x16,0x53,0x04,0xF1,0xB3,0x00}を代入します。
データの送信頻度を上げるには、送信の待ち時間(systick_wait_ms の引数の値(ミリ秒))を小さくすればよいが、 無闇に小さくするとデータが全く送れなくなります。具体的には 20msec だと送信可能ですが、10msec にすると送信出来なくなります。

2.スレーブ側のプログラム

スレーブ機の設定を行って、受信したデータを画面に表示するプログラムについて説明します。
次のプログラム blue_slave.c として作成します。
blue_slave.c
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"

// NXT Bluetooth 設定
// bluetoothパスキー
#define BT_PASS_KEY	"1234"
// bluetooth受信パケットの大きさ 
#define BT_RCV_BUF_SIZE 32
#define COUNT 10

// bluetooth受信パケットの宣言   U8 は unsigned 8bit(1バイト)
U8 bt_receive_buf[BT_RCV_BUF_SIZE];	

DeclareTask(Task1);			

void ecrobot_device_initialize(){

	//Bluetoothデバイス設定 デバイス名を新たに設定したい場合のみ、以下のコメントアウトをはずす。
	//ecrobot_set_bt_device_name("NXT51");

	// スレーブとして初期化 
	ecrobot_init_bt_slave(BT_PASS_KEY);	
}

void ecrobot_device_terminate(){
	// bluetooth通信終了
	ecrobot_term_bt_connection();		
}

void user_1ms_isr_type2(void){}

TASK(Task1)
{
	int i=0;
	unsigned int read_len;

	while(1){
		// 受信データを buf に代入
		read_len = ecrobot_read_bt_packet(bt_receive_buf, BT_RCV_BUF_SIZE);	

		if( read_len != 0){	//データ更新されたときの実行
			i = bt_receive_buf[0];	
			display_clear(0);
			display_goto_xy(0,1);
   			display_string("Receive ");	
			display_goto_xy(8,1);
			display_int(i, 2);
			display_update();
		}

		i = 0;					
		systick_wait_ms(10);
	}
	TerminateTask();
}


blue_slave.c で新たに用いたAPIについて解説します。

ecrobot_init_bt_slave(BT_PASS_KEY);
NXTをスレーブデバイスとして初期化します
引数には、パスキーを指定します。パスキーとは、通信する双方で有する合言葉のようなものです。4桁以上の文字を自由に指定してください。"1234"がディフォルト値です。
この関数は、NXT起動時の処理を記述するフック関数(デバイス初期化関数)内に記述します。

ecrobot_read_bt_packet(bt_receive_buf, BT_RCV_BUF_SIZE);
データを受信するAPIです。戻り値は受信したデータのバイト数です。
第一の引数は、受信バッファの名前を指定します。
第二の引数は、受信バッファのサイズ(バイト数)を指定します。最大値は256byteです。

このプログラムでは受信処理を 10msec 周期で行っていますが、受信したデータはハード的に受信バッファに取り込まれているため、バッファがいっぱいにならない限り受信データを取りこぼすことはありません。
送信データを受信側が取りこぼさないためには、一般に送信側の動作周期(systeick_wait_ms(10))より、 受信側の動作周期を短くする(同じでもよい)しておく必要があります。


3.動作のさせ方

Bluetooth通信プログラムを動作させるときは、必ずスレーブ側NXTを先に起動させOSEK画面が立ち上がった後に、マスター側のプログラムを起動させ、両方のNXTのOSEKメニュー画面で[R]の右横に[BT]と表示されるまで待ちます。通常、4~5秒で通信が確立します。
[BT]の表示を確認出来たら、両方のプログラムを走らせます。

ここではマスターからスレーブにデータを送信しましたが、逆にスレーブでパケットを受信しマスターで受信することも可能です。マスター・スレーブの双方で送受信を行うことにより、双方向通信が可能になります。


4.補足

今回は通信用の API に ecrobot_read_bt_packet(), ecrobot_send_bt_packet() を用いましたが、nxtOSEK ver2.15以降は、 これと別に ecrobot_read_bt(), ecrobot_send_bt()というAPIが用意されています。

read_len = ecrobot_read_bt(buf, 0, BT_RCV_BUF_SIZE);  //戻り値は受信したデータのバイト数
send_len = ecrobot_send_bt(buf, 0, BT_SND_BUF_SIZE);  //戻り値は送信したデータのバイト数 

このAPIの詳細は、ECRobot C APIレファレンスのBluetooth 通信API を参照して下さい。
Bluetooth通信でパソコンとデータの送受信を行う場合は、こちらの(_packetの無い)APIを使う必要があります。


5.課題

  1. スレーブ側のアドレスを確認し、サンプルプログラムの動作を確認せよ。
    1. それぞれのNXTにスレーブ側のプログラムをアップロードし、OSEK画面で Bluetooth の通信アドレス(BTアドレス)を確認する。
    2. マスター側のプログラムにスレーブ側(相手側)のBTアドレスを入れて、マスター側プログラムをアップロードする。
    3. NXTの一方でスレーブのプログラムを、他方でマスター側のプログラムを起動し、BT通信の確立・データの送受信ができることを確認する。
    4. 3.をマスター機とスレーブ機を入れ替えて実施する。

  2. マスター側のタッチセンサが押されているときスレーブ側の走行体が前進、押されていないとき停止するプログラムを作成せよ。
    このとき送信側の周期(待ち時間)が大きいとその分反応が遅れるで、待ち時間は適切な値とすること。


6. チャレンジ課題

超音波センサの課題で実現した動作をマスター側に実装し、スレーブ側の走行体がそれに同調して前後するようにせよ。

ヒント:マスター機の送信バッファ(bt_send_buf[])に、左右の指定速度値または、命令(前進・後退・停止)に対応する数値を入れてスレーブ機に送り、スレーブ機はそのデータに従って動作するようにする。



9.その他のセンサーの使用 TOPへ