Bluetooth NXT to NXT communication

 

nxtOSEK uses simple approach to configure Bluetooth NXT to NXT communication. Therefore, all necessity information for pairing the devices has to be implemented in the code . In case of NXT to PC communication, PC is the master and the NXT is the slave, however, in case of NXT to NXT communication, a NXT has to be the master and the other has to be the slave. To know the Bluetooth Device Address of the slave device, at first, we need to upload a program (e.g. btslave.c sample) into a NXT and when a program is executed in the NXT, we can see the Bluetooth Device Address in the left upper side of the LCD screen. This information needs to be implemented in the code for the master NXT.
If the slave NXT was failed to get Bluetooth Device Address, "BD_ADDR: Failed..." message is appeared instead of the address. In this case, it needs to re-start the slave NXT.

The pairing process itself can be done easily:
1. Upload the program into the slave NXT and leave the button instruction screen.
(The slave NXT is waiting for a connection request from the master NXT)
2. Upload the program into the master NXT, then NXTs are automatically paired and [BT] is appeared in the LCD screen on the both NXTs.


3. Run the program in the both NXTs.
4. In case of stopping the NXTs, stop the slave NXT at first, then stop the master NXT.
5. In case of re-starting the program, the slave NXT should be executed at first, then the master NXT should be executed.

In the master/slave programs, the difference is only Bluetooth initialization functions. In case of the slave, ecrobot_init_bt_slave API is used and pin code is set as the argument. In case of the master, ecrobot_init_bt_master API is used. ecrobot_init_bt_master API requires Bluetooth Device Address of the slave and pin code. While the sample program is running on the both NXTs, if we turn on the Touch Sensor on the NXT, the other NXT's motor is turned on at the maximum speed and the other way is as well.

NOTE: Since nxtOSEK 2.01, Bluetooth connection can be done during device initialization and during run-time. However, practically, it would be better to implement in the device initializations.

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