两台NXT间的蓝牙通信

nxtOSEK 利用简单的方法实现NXT间的蓝牙通信。因此,所有用于配对连接设备的必要信息都必需用代码来实现。例如NXT和PC机间的通信,PC机是主设备而NXT是从设备,又比如NXT和NXT间的通信,其中一个NXT必需为主设备,另一个为从设备。为了知道奴隶设备的蓝牙设备地址,我们得先上传一个 程序(例如,btslave.c 样例)到NXT。当程序在NXT上执行后,我们会在LCD屏幕的左上角看到蓝牙设备的地址。这些信息必需在 主NXT 上的代码运行实现。如果 从NXT 获取蓝牙设备地址失败,"BD_ADDR:Failed..."信息将代替地址信息出现。在这种情况下,需要重启从NXT。

配对连接过程可以简单实现:

1.将程序上传到从NXT,显示按钮指令屏

(从NXT等待主NXT的请求连接信息)

2.将程序上传主NXT,那么两个NXT会自动进行配对并且在他们的LCD屏幕上均会出现[BT]。

3.在两台NXT上都运行程序。

4.在停止NXT时,先停止从NXT,再停止主NXT。

5.在重启程序时,必需先运行从NXT,再运行主NXT。

主/从程序的区别只在于蓝牙初始化功能。奴隶程序中使用ecrobot_init_bt_slave API并把pin号码作为参数。主人程序使用ecrobot_init_bt_master API。ecrobot_init_bt_master API需要从设备的蓝牙设备地址和pin码。在两台NXT上运行例子程序,如果我们打开一台NXT上的触觉传感器,另一台NXT的伺服电机将开到最大速度或者也可做出其他反应。

注意:从nxtOSEK 2.01开始,蓝牙连接可在设备初始化和设备运行期间完成。在实践中,蓝牙连接在设备初始化期间完成会更好。

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;
    };
  };  
};

 

 

 

返回 示例程序