2台のNXTにおけるBluetooth通信

 

nxtOSEKでは、2台のNXTのBluetooth通信に必要な情報をあらかじめプログラムに記述する必要があります。NXTとPCのBluetooth通信では、ペアリングに必要な情報はPC上で基本的には設定しますが、NXTとNXTのBluetooth通信では、プログラムレベルで1台のNXTがマスター、もう1台がスレーブとして設定します。ペアリングのためにはスレーブNXTのBluetoothデバイスアドレス情報が必要となるため、サンプルプログラム等を用いて、スレーブNXTのBluetoothデバイスアドレスを取得後に、マスターNXT用プログラムにスレーブNXTのBluetoothデバイスアドレスを定義します。スレーブNXTのBluetoothデバイスアドレスは、スレーブNXTのプログラム起動時にボタン操作画面の左側上部に表示されます。スレーブNXTがBluetoothデバイスアドレスの取得に失敗した場合、アドレスの代わりに"BD_ADDR Failed"というメッセージが表示されます。この場合は、RUNボタンを押してプログラムを起動後、STOPボタンを押すことでスレーブNXTを再起動してください。


ペアリングに必要な情報をプログラムに記述しているため、ペアリング設定そのものは簡単です。
1. スレーブNXTにプログラムをアップロードし、ボタン操作画面のままにしておきます。 (スレーブNXTのボタン操作画面表示状態では、スレーブNXTはBlutooth接続待機状態にあります)
2. マスターNXTにプログラムをアップロードします。その後、自動的にペアリング処理がおこなわれ、ペアリングが完了すると両方のNXTボタン操作画面左下にBluetoothアイコンが表示されます。
3. 2台のNXTのRunボタンを押し、プログラムを実行します。
4. プログラム終了時には、最初にスレーブNXTのSTOPボタンを押し、その後マスターNXTのSTOPボタンを押してください。
5. プログラムの再起動時には、最初にスレーブNXTを起動し、その後マスターNXTを起動するようにしてください。

マスター/スレーブNXTのサンプルプログラムにおける違いは、Bluetooth通信初期化APIのみです。スレーブNXTの初期化API
(ecrobot_init_bt_slave)の引数にはパスキー用文字列を設定します。一方、マスターNXTの初期化API(ecrobot_init_bt_master)では、引数として、パスキー用文字列およびスレーブNXTのBluetoothデバイスアドレスを設定します。2つのサンプルプログラムでは、片方のNXTのタッチセンサをONにすると、他方のNXTのモータが最大速度で回転する様を確認できます。

nxtOSEK 2.01からは、Bluetooth通信の接続が、ecrobot_device_initializeフック関数内だけでなく、アプリケーションプログラム実行中にダイナミックにおこなえるようになりました。

samples\btslave\btslave.c

/* btslave.c */
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"

/* OSEK declarations */
DeclareCounter(SysTimerCnt);
DeclareTask(EventDispatcher);
DeclareTask(EventHandler);
DeclareTask(IdleTask);
DeclareEvent(TouchSensorOnEvent);
DeclareEvent(TouchSensorOffEvent);

/* below macro enables run-time Bluetooth connection */
#define RUNTIME_CONNECTION

/* nxtOSEK hooks */
void ecrobot_device_initialize()
{
#ifndef RUNTIME_CONNECTION
  ecrobot_init_bt_slave("LEJOS-OSEK");
#endif
}

void ecrobot_device_terminate()
{
  ecrobot_term_bt_connection();
}

/* EventDispatcher executed every 5ms */
TASK(EventDispatcher)
{
  static U8 bt_receive_buf[32];
  static U8 TouchSensorStatus_old = 0;
  U8 TouchSensorStatus;

  /* read packet data from the master device */
  ecrobot_read_bt_packet(bt_receive_buf, 32);
  if (bt_receive_buf[0] == 1)
  {
    ecrobot_set_motor_speed(NXT_PORT_B, 100);
  }
  else
  {
    ecrobot_set_motor_speed(NXT_PORT_B, 0);
  }

  TouchSensorStatus = ecrobot_get_touch_sensor(NXT_PORT_S4);
  if (TouchSensorStatus == 1 && TouchSensorStatus_old == 0)
  {
    /* Send a Touch Sensor ON Event to the Handler */
    SetEvent(EventHandler, TouchSensorOnEvent);
  }
  else if (TouchSensorStatus == 0 && TouchSensorStatus_old == 1)
  {
    /* Send a Touch Sensor OFF Event to the Handler */
    SetEvent(EventHandler, TouchSensorOffEvent);
  }
  TouchSensorStatus_old = TouchSensorStatus;

  TerminateTask();
}

/* EventHandler executed by OSEK Events */
TASK(EventHandler)
{
  static U8 bt_send_buf[32];

  while(1)
  {
    WaitEvent(TouchSensorOnEvent); /* Task is in waiting status until the Event comes */
    ClearEvent(TouchSensorOnEvent);
    /* send packet data to the master device */
    bt_send_buf[0] = 1;
    ecrobot_send_bt_packet(bt_send_buf, 32);

    WaitEvent(TouchSensorOffEvent); /* Task is in waiting status until the Event comes */
    ClearEvent(TouchSensorOffEvent);
    /* send packet data to the master device */
    bt_send_buf[0] = 0;
    ecrobot_send_bt_packet(bt_send_buf, 32);
  }

  TerminateTask();
}

/* IdleTask */
TASK(IdleTask)
{
  static SINT bt_status = BT_NO_INIT;

  while(1)
  {
#ifdef RUNTIME_CONNECTION
    ecrobot_init_bt_slave("LEJOS-OSEK");
#endif

    if (ecrobot_get_bt_status() == BT_STREAM && bt_status != BT_STREAM)
    {
      display_clear(0);
      display_goto_xy(0, 0);
      display_string("[BT]");
      display_update();
    }
    bt_status = ecrobot_get_bt_status();
  }
}

samples\btmaster\btmaster.c

/* btmaster.c */
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"

/* OSEK declarations */
DeclareCounter(SysTimerCnt);
DeclareTask(EventDispatcher);
DeclareTask(EventHandler);
DeclareTask(IdleTask);
DeclareEvent(TouchSensorOnEvent);
DeclareEvent(TouchSensorOffEvent);

/* slave device's Bluetooth Device Address (this has to be modified for your NXT) */
const U8 bd_addr[7] = {0x00, 0x16, 0x53, 0x04, 0x51, 0x65, 0x00};

/* below macro enables run-time Bluetooth connection */
#define RUNTIME_CONNECTION

/* nxtOSEK hooks */
void ecrobot_device_initialize()
{
#ifndef RUNTIME_CONNECTION
  ecrobot_init_bt_master(bd_addr, "LEJOS-OSEK");
#endif
}
void ecrobot_device_terminate()
{
  ecrobot_term_bt_connection();
}

/* EventDispatcher executed every 5ms */
TASK(EventDispatcher)
{
  static U8 bt_receive_buf[32];
  static U8 TouchSensorStatus_old = 0;
  U8 TouchSensorStatus;

  /* read packet data from the master device */
  ecrobot_read_bt_packet(bt_receive_buf, 32);
  if (bt_receive_buf[0] == 1)
  {
    ecrobot_set_motor_speed(NXT_PORT_B, 100);
  }
  else
  {
    ecrobot_set_motor_speed(NXT_PORT_B, 0);
  }

  TouchSensorStatus = ecrobot_get_touch_sensor(NXT_PORT_S4);
  if (TouchSensorStatus == 1 && TouchSensorStatus_old == 0)
  {
    /* Send a Touch Sensor ON Event to the Handler */
    SetEvent(EventHandler, TouchSensorOnEvent);
  }
  else if (TouchSensorStatus == 0 && TouchSensorStatus_old == 1)
  {
    /* Send a Touch Sensor OFF Event to the Handler */
    SetEvent(EventHandler, TouchSensorOffEvent);
  }
  TouchSensorStatus_old = TouchSensorStatus;

  TerminateTask();
}

/* EventHandler executed by OSEK Events */
TASK(EventHandler)
{
  static U8 bt_send_buf[32];

  while(1)
  {
    WaitEvent(TouchSensorOnEvent); /* Task is in waiting status until the Event comes */
    ClearEvent(TouchSensorOnEvent);
    /* send packet data to the master device */
    bt_send_buf[0] = 1;
    ecrobot_send_bt_packet(bt_send_buf, 32);

    WaitEvent(TouchSensorOffEvent); /* Task is in waiting status until the Event comes */
    ClearEvent(TouchSensorOffEvent);
    /* send packet data to the master device */
    bt_send_buf[0] = 0;
    ecrobot_send_bt_packet(bt_send_buf, 32);
  }

  TerminateTask();
}

/* IdleTask */
TASK(IdleTask)
{
  static SINT bt_status = BT_NO_INIT;

  while(1)
  {
#ifdef RUNTIME_CONNECTION
    ecrobot_init_bt_master(bd_addr, "LEJOS-OSEK");
#endif

    if (ecrobot_get_bt_status() == BT_STREAM && bt_status != BT_STREAM)
    {
      display_clear(0);
      display_goto_xy(0, 0);
      display_string("[BT]");
      display_update();
    }
    bt_status = ecrobot_get_bt_status();
  }
}

samples\btslave\btslave.oil and samples\btmaster\btmaster.oil

#include "implementation.oil"

CPU ATMEL_AT91SAM7S256
{
  OS LEJOS_OSEK
  {
    STATUS = EXTENDED;
    STARTUPHOOK = FALSE;
    ERRORHOOK = FALSE;
    SHUTDOWNHOOK = FALSE;
    PRETASKHOOK = FALSE;
    POSTTASKHOOK = FALSE;
    USEGETSERVICEID = FALSE;
    USEPARAMETERACCESS = FALSE;
    USERESSCHEDULER = FALSE;
  };

  /* Definition of application mode */
  APPMODE appmode1{};

  /* Definition of Touch Sensor ON Event */
  EVENT TouchSensorOnEvent{
    MASK = AUTO;
  };

  /* Definition of Touch Sensor OFF Event */
  EVENT TouchSensorOffEvent{
    MASK = AUTO;
  };

  /* Definition of EventDispatcher */
  TASK EventDispatcher
  {
    AUTOSTART = FALSE;
    PRIORITY = 3;
    ACTIVATION = 1;
    SCHEDULE = FULL;
    STACKSIZE = 512; /* Stack size */
  };

  /* Definition of EventHandler */
  TASK EventHandler
  {
    AUTOSTART = TRUE
    {
      APPMODE = appmode1;
    };
    PRIORITY = 2;
    ACTIVATION = 1;
    SCHEDULE = FULL;
    STACKSIZE = 512; /* Stack size */
    EVENT = TouchSensorOnEvent;
    EVENT = TouchSensorOffEvent;
  };

  /* Definition of IdleTask */
  TASK IdleTask
  {
    AUTOSTART = TRUE
    {
      APPMODE = appmode1;
    };
    PRIORITY = 1;
    ACTIVATION = 1;
    SCHEDULE = FULL;
    STACKSIZE = 512; /* Stack size */
  };

  /* Definition of OSEK Alarm Counter */
  COUNTER SysTimerCnt
  {
    MINCYCLE = 1;
    MAXALLOWEDVALUE = 10000;
    TICKSPERBASE = 1; /* One tick is equal to 1msec */
  };

  /* Definition of EventDispatcher execution timing */
  ALARM cyclic_alarm1
  {
    COUNTER = SysTimerCnt;
    ACTION = ACTIVATETASK
    {
      TASK = EventDispatcher;
    };
    AUTOSTART = TRUE
    {
      ALARMTIME = 1;
      CYCLETIME = 5; /* Executed every 5msec */
      APPMODE = appmode1;
    };
  };  
};

 

 

 

Back to Samples