nRF8001 - Multiple Bluetooth LE

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
dt
 
Posts: 3
Joined: Wed May 07, 2014 11:47 pm

nRF8001 - Multiple Bluetooth LE

Post by dt »

Hello Forum,

I am connecting multiple (2) nRF8001 Bluefruits to an Arduino Micro.

I have wired each Bluefruit to its unique pins and confirmed that they are functioning independently. Now, I want to use both at the same time, and have each perform its own functions. So, I am working within the echoDemo sketch. I've defined the pins for each Bluefruit, and tried a few other things, but I keep hitting errors #noobfail. So, I need a little assistance programming the sketch - I'm not exactly sure what code I should replicate for the second BLE and where it should go within the sketch...

Thanks for some direction. Maybe @KTOWN would like to answer? Here is the echoDemo with the only changes being the pin definitions for the second Bluefruit.

Code: Select all

/*********************************************************************
This is an example for our nRF8001 Bluetooth Low Energy Breakout

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/1697

Adafruit invests time and resources providing this open source code, 
please support Adafruit and open-source hardware by purchasing 
products from Adafruit!

Written by Kevin Townsend/KTOWN  for Adafruit Industries.
MIT license, check LICENSE for more information
All text above, and the splash screen below must be included in any redistribution
*********************************************************************/

// This version uses the internal data queing so you can treat it like Serial (kinda)!

#include <SPI.h>
#include "Adafruit_BLE_UART.h"

// Connect CLK/MISO/MOSI to hardware SPI
// e.g. On UNO & compatible: CLK = 13, MISO = 12, MOSI = 11
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 3     // This should be an interrupt pin, on Uno thats #2 or #3
#define ADAFRUITBLE_RST 9

#define ADAFRUITBLE_REQ02 4
#define ADAFRUITBLE_RDY02 2     // This should be an interrupt pin, on Uno thats #2 or #3
#define ADAFRUITBLE_RST02 5
#define ledPin 13

Adafruit_BLE_UART BTLEserial = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
/**************************************************************************/
/*!
    Configure the Arduino and start advertising with the radio
*/
/**************************************************************************/
void setup(void)
{ 
  Serial.begin(9600);
  while(!Serial); // Leonardo/Micro should wait for serial init
  Serial.println(F("Adafruit Bluefruit Low Energy nRF8001 Print echo demo"));

  BTLEserial.begin();
}

/**************************************************************************/
/*!
    Constantly checks for new events on the nRF8001
*/
/**************************************************************************/
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;

void loop()
{
  // Tell the nRF8001 to do whatever it should be working on.
  BTLEserial.pollACI();

  // Ask what is our current status
  aci_evt_opcode_t status = BTLEserial.getState();
  // If the status changed....
  if (status != laststatus) {
    // print it out!
    if (status == ACI_EVT_DEVICE_STARTED) {
        Serial.println(F("* Advertising started"));
        digitalWrite(ledPin, HIGH);
    }
    if (status == ACI_EVT_CONNECTED) {
        Serial.println(F("* Connected!"));
    }
    if (status == ACI_EVT_DISCONNECTED) {
        Serial.println(F("* Disconnected or advertising timed out"));
    }
    // OK set the last status change to this one
    laststatus = status;
  }

  if (status == ACI_EVT_CONNECTED) {
    // Lets see if there's any data for us!
    if (BTLEserial.available()) {
      Serial.print("* "); Serial.print(BTLEserial.available()); Serial.println(F(" bytes available from BTLE"));
    }
    // OK while we still have something to read, get a character and print it out
    while (BTLEserial.available()) {
      char c = BTLEserial.read();
      Serial.print(c);
    }

    // Next up, see if we have any data to get from the Serial console

    if (Serial.available()) {
      // Read a line from Serial
      Serial.setTimeout(100); // 100 millisecond timeout
      String s = Serial.readString();

      // We need to convert the line to bytes, no more than 20 at this time
      uint8_t sendbuffer[20];
      s.getBytes(sendbuffer, 20);
      char sendbuffersize = min(20, s.length());

      Serial.print(F("\n* Sending -> \"")); Serial.print((char *)sendbuffer); Serial.println("\"");

      // write the data
      BTLEserial.write(sendbuffer, sendbuffersize);
    }
  }
}

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: nRF8001 - Multiple Bluetooth LE

Post by adafruit_support_rick »

For starters, you need to define two objects, one for each NRF8001:

Code: Select all

Adafruit_BLE_UART BTLEserial_1 = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
Adafruit_BLE_UART BTLEserial_2 = Adafruit_BLE_UART(ADAFRUITBLE_REQ02, ADAFRUITBLE_RDY02, ADAFRUITBLE_RST02);
But I'm not certain the driver will support two devices.

EDIT: I heard from KTOWN. This doesn't sound easy at all. the driver will require some significant rework to support two devices:
You'd have to redo the interrupt handling since the SPI requires a HW interrupt for each device so you'll need to wire up a second one on a different pin (though the Uno has two available). To be honest I'm not sure how this would work out in practice since it isn't a standard SPI interface. In principle, the answer is yes, but it will definately require some digging in the lower level code at least for the interrupts.

The nRF8001 doesn't have a single 'CS/SSEL' pin the way most SPI devices do, and splits the assert functionality across two pins, which will likely throw a wrench in anyone's plans if they're expecting something as simple as two standard SPI devices each with one standard select pin and no HW interrupts to handle.

dt
 
Posts: 3
Joined: Wed May 07, 2014 11:47 pm

Re: nRF8001 - Multiple Bluetooth LE

Post by dt »

I've been struggling to get the (2) BLE's running side by side. Would love some more help if anyone can pitch in...

I dug into the lower level files but am not finding what needs to be modified... Here's my progress on the code for the sketch.

Code: Select all

// This version uses the internal data queing so you can treat it like Serial (kinda)!

#include <SPI.h>
#include "Adafruit_BLE_UART.h"

// Connect CLK/MISO/MOSI to hardware SPI
// e.g. On UNO & compatible: CLK = 13, MISO = 12, MOSI = 11
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RDY 3     // This should be an interrupt pin, on Uno thats #2 or #3
#define ADAFRUITBLE_RST 9

#define ADAFRUITBLE_REQ02 4
#define ADAFRUITBLE_RDY02 2     // This should be an interrupt pin, on Uno thats #2 or #3
#define ADAFRUITBLE_RST02 5

#define ledPin 13

Adafruit_BLE_UART BTLEserial = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
Adafruit_BLE_UART BTLEserial02 = Adafruit_BLE_UART(ADAFRUITBLE_REQ02, ADAFRUITBLE_RDY02, ADAFRUITBLE_RST02);

/**************************************************************************/
/*!
    Configure the Arduino and start advertising with the radio
*/
/**************************************************************************/
void setup(void)
{ 
  Serial.begin(9600);
  while(!Serial); // Leonardo/Micro should wait for serial init
  Serial.println(F("Welcome to the Dolores Project!"));

  BTLEserial.begin();
}

/**************************************************************************/
/*!
    Constantly checks for new events on the nRF8001
*/
/**************************************************************************/
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;
aci_evt_opcode_t laststatus2 = ACI_EVT_DISCONNECTED;

void loop()
{
  // Tell the nRF8001 to do whatever it should be working on.
  BTLEserial.pollACI();

  // Ask what is our current status
  aci_evt_opcode_t status = BTLEserial.getState();
  // If the status changed....
  if (status != laststatus) {
    // print it out!
    if (status == ACI_EVT_DEVICE_STARTED) {
        Serial.println(F("* BLE ONE advertising started"));
        digitalWrite(ledPin, HIGH);
    }
    if (status == ACI_EVT_CONNECTED) {
        Serial.println(F("* Connected!"));
    }
    if (status == ACI_EVT_DISCONNECTED) {
        Serial.println(F("* Disconnected or advertising timed out"));
    }
    // OK set the last status change to this one
    laststatus = status;
  }

  if (status == ACI_EVT_CONNECTED) {
    // Lets see if there's any data for us!
    if (BTLEserial.available()) {
      Serial.print("* "); Serial.print(BTLEserial.available()); Serial.println(F(" bytes available from BTLE"));
    }
    // OK while we still have something to read, get a character and print it out
    while (BTLEserial.available()) {
      char c = BTLEserial.read();
      Serial.print(c);
    }

    // Next up, see if we have any data to get from the Serial console

    if (Serial.available()) {
      // Read a line from Serial
      Serial.setTimeout(100); // 100 millisecond timeout
      String s = Serial.readString();

      // We need to convert the line to bytes, no more than 20 at this time
      uint8_t sendbuffer[20];
      s.getBytes(sendbuffer, 20);
      char sendbuffersize = min(20, s.length());

      Serial.print(F("\n* Sending -> \"")); Serial.print((char *)sendbuffer); Serial.println("\"");

      // write the data
      BTLEserial.write(sendbuffer, sendbuffersize);
    }
  }

/**************************************************************************/
/*!
    Repeat for BLE 02 & Constantly checks for new events on the nRF8001
*/
/**************************************************************************/


  // Tell the nRF8001 to do whatever it should be working on.
  BTLEserial02.pollACI();

  // Ask what is our current status
  aci_evt_opcode_t status2 = BTLEserial02.getState();
  
  // If the status changed....
  if (status2 != laststatus) {
    // print it out!
    if (status2 == ACI_EVT_DEVICE_STARTED) {
        Serial.println(F("* BLE2 advertising started"));
        digitalWrite(ledPin, HIGH);
    }
    if (status2 == ACI_EVT_CONNECTED) {
        Serial.println(F("* Connected!"));
    }
    if (status2 == ACI_EVT_DISCONNECTED) {
        Serial.println(F("* Disconnected or advertising timed out"));
    }
    // OK set the last status change to this one
    laststatus2 = status2;
  }

  if (status2 == ACI_EVT_CONNECTED) {
    // Lets see if there's any data for us!
    if (BTLEserial02.available()) {
      Serial.print("* "); Serial.print(BTLEserial02.available()); Serial.println(F(" bytes available from BTLE"));
    }
    // OK while we still have something to read, get a character and print it out
    while (BTLEserial02.available()) {
      char c = BTLEserial02.read();
      Serial.print(c);
    }

    // Next up, see if we have any data to get from the Serial console

    if (Serial.available()) {
      // Read a line from Serial
      Serial.setTimeout(100); // 100 millisecond timeout
      String s = Serial.readString();

      // We need to convert the line to bytes, no more than 20 at this time
      uint8_t sendbuffer[20];
      s.getBytes(sendbuffer, 20);
      char sendbuffersize = min(20, s.length());

      Serial.print(F("\n* Sending -> \"")); Serial.print((char *)sendbuffer); Serial.println("\"");

      // write the data
      BTLEserial02.write(sendbuffer, sendbuffersize);
    }
  }
  
}

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”