Understanding the BC127 Bluetooth Module

Pages
Contributors: SFUptownMaker
Favorited Favorite 6

Example: Audio Bridge

This example is for a pair of BC127 modules, one of which is set up as a receiver and the other as a transmitter. The transmitter module will automatically pair to the receiver and start streaming audio from its input.

Pete uses this in his office to send audio from his computer to his stereo on the other side of the room.

One thing to note, if you implement this yourself: it takes some time (~2 minutes) for one of the devices to notice that the remote has disappeared, reset, and retry the connection. That can't really be rushed; it's inherent to the BC127 module. A possible way around it would be to pair with an SPP connection and reset if you miss a heartbeat signal; I'll leave that as an exercise for the reader. After all, the fun is in the hacking!

The Hardware

The hardware is identical at both ends: an Arduino Pro Mini 3.3V hooked up to a Purpletooh Jamboree. Here's a Fritzing diagram showing how it works:

alt text

Power is a delicate thing, here. For best results, you probably want to power the transmitter using the on-board microUSB connector with some kind of power supply external to the signal source; say, a cell phone charger or wall wart. If you are using this to transmit a signal from a PC, powering it from the onboard USB can set up ground loops which will cause a noticeable hum or hiss in the signal.

The Receiver

Note: This example assumes you are using the latest version of the Arduino IDE on your desktop. If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE. If you have not previously installed an Arduino library, please check out our installation guide.

The receiver end uses the Pro Mini to monitor the connection and restart the module if the connection is lost. The reason for this is simple: when a paired module loses its connection, it only wants to restore a connection with the paired device. However, if the paired device loses its knowledge of the pairing, the connection can't be restored until the receiver gets reset. Hence, the Pro Mini.

We also need to issue the AVRCP "PLAY" command across the link, to start the audio flowing. The Pro Mini handles that, as well.

The code comments give you all the deets about how this is done. Here's the code:

language:c
// Include the two libraries we need to use this; I'm using a software serial port
//  because time-sharing the hardware port with uploading code is a pain.
#include <bc127.h>
#include <SoftwareSerial.h>

// Create a software serial port.
SoftwareSerial swPort(11,10);  // RX, TX
// Create a BC127 and attach the software serial port to it.
BC127 BTModu(&swPort);

void setup()
{
  // Serial port configuration. The software port should be at 9600 baud, as that
  //  is the default speed for the BC127.
  Serial.begin(9600);
  swPort.begin(9600);
}

// buffer *should* be a static within loop(), but Arduino freaks out about that,
//  so I'm making it a global. Le sigh.
String buffer = "";

void loop()
{
  // resetFlag tracks the state of the module. When true, the module is reset and
  //  ready to receive a connection. When false, the module either has an active
  //  connection or has lost its connection; checking connectionState() will verify
  //  which of those conditions we're in.
  static boolean resetFlag = false;

  // This is where we determine the state of the module. If resetFlag is false, and
  //  we have a CONNECT_ERROR, we need to restart the module to clear its pairing
  //  list so it can accept another connection.
  if (BTModu.connectionState() == BC127::CONNECT_ERROR  && !resetFlag)
  {  
    Serial.println("Connection lost! Resetting...");
    // Blast the existing settings of the BC127 module, so I know that the module is
    //  set to factory defaults...
    BTModu.restore();

    // ...but, before I restart, I need to set the device to be a SINK, so it will
    //  enable its audio output and dump the audio to the output.
    BTModu.setClassicSink();

    // Write, reset, to commit and effect the change to a source.
    BTModu.writeConfig();
    // Repeat the connection process if we've lost our connection.
    BTModu.reset();
    // Change the resetFlag, so we know we've restored the module to a usable state.
    resetFlag = true;
  }
  // If we ARE connected, we'll issue the "PLAY" command. Note that issuing this when
  //  we are already playing doesn't hurt anything.
  else BTModu.musicCommands(BC127::PLAY);

  // We want to look for a connection to be made to the module; once a connection
  //  has been made, we can clear the resetFlag.
  if (BTModu.connectionState() == BC127::SUCCESS) resetFlag = false;
}

The Transmitter

Note: This example assumes you are using the latest version of the Arduino IDE on your desktop. If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE. If you have not previously installed an Arduino library, please check out our installation guide.

As with the receiver, we want to watch for a failure in the connection, then reconnect.

Check out the code:

language:c
// Include the two libraries we need to use this; I'm using a software serial port
//  because time-sharing the hardware port with uploading code is a pain.
#include <bc127.h>
#include <SoftwareSerial.h>

// Create a software serial port.
SoftwareSerial swPort(11,10);  // RX, TX
// Create a BC127 and attach the software serial port to it.
BC127 BTModu(&swPort);

String address = "20FABB0101CF"; // Remote module's address. If I were an optimist,
                                 //  I'd scan for BC127 modules and treat any one I
                                 //  found as the remote. Let's hard code for safety.

void setup()
{
  // Serial port configuration. The software port should be at 9600 baud, as that
  //  is the default speed for the BC127.
  Serial.begin(9600);
  swPort.begin(9600);
}

void loop()
{
  // Loop doesn't have to do much...just monitor the connection and try and restore
  //  it if it's lost.
  if (BTModu.connectionState() == BC127::CONNECT_ERROR)
  {
    // Blast the existing settings of the BC127 module, so I know that the module is
    //  set to factory defaults...
    BTModu.restore();

    // ...but, before I restart, I need to set the device to be a SOURCE, so it will
    //  enable its audio input and forward the data to the remote.
    BTModu.setClassicSource();

    // Write, reset, to commit and effect the change to a source.
    BTModu.writeConfig();
    BTModu.reset();

    // Now, attempt to connect. There are timeouts on these operations, so we won't
    //  sit forever.
    BTModu.connect(address, BC127::A2DP);
    BTModu.connect(address, BC127::AVRCP);
    // If we DID connect, we want to use the "PLAY" command to start the devices
    //  streaming audio. If we didn't, well, who cares? No harm in a spurious "PLAY".
    BTModu.musicCommands(BC127::PLAY);
  }
}