text: :
  Installing an Arduino Library
  Serial Terminal Basics
  Bluetooth Basics
  BC127 Basics
  On this page, we're going to lay the basic groundwork for understanding the BC127 module's functionality and capabilities. Everything we cover is in the BC127 module datasheet, but we're going to pare down what is in the datasheet to make it a bit easier to understand.
  If you plan on using the BC127 with the Arduino library we provide, you may still find it useful to read through this page. While the library abstracts away the majority of the under-the-hood stuff, knowing what's going on may still be helpful, especially if you find that the library doesn't support a function you would like to use.
  Operational Modes
  The BC127 has two operational modes: command mode and data mode..
  Command Mode
  In command mode, data received locally and appended with a carriage return (typically represented as "\r", or as 0x0D hex) will be parsed as a command. Note that the parser expects only a carriage return; if the device sending commands appends both carriage return and newline (e.g., an Arduino using the println() statement), the parser will have trouble with it. If the newline character precedes the carriage return, the parser may not accept the command at all. If the carriage return comes first, the parser will interpret the newline as a start of another command string, which can cause unexpected error messages from the module.
  Throughout the rest of this guide, I will be considering the carriage return at the end of the command to be implicit. Also, while commands are theoretically case-insensitive, commands will always be presented as all-caps and I suggest that you always send all-caps strings for commands, as it sometimes makes a difference.
  Finally, the parser isn't very smart about whitespace. Inserting spaces in command strings in unexpected locations will cause errors. More on this later, as we start to talk about specific commands.
  Data Mode
  To enter data mode, simply input the command "ENTER_DATA". The module will respond with "OK" (more on responses later), whether it is connected as an SPP device or not. From that point on, data will be tranparently passed out via the SPP connection, if one is available. If not, it will simply be ignored--it is not buffered for later delivery when a connection is available.
  To exit data mode, a string of four dollar signs must be sent ("$$$$"). In order for this to be interpreted as the command to exit data mode, rather than as data to be passed, there must be a gap before the first $ and after the fourth. The length of that gap can be set by the user, but is, by default, 400ms at either end. Without that gap in place, the string will be treated as data.
  Also note that data mode does not support BLE connections, despite the superficial similarity between SPP data transfer and BLE data transfer. That is a constraint of the firmware on the BC127 and may change in the future.
  Commands, Responses, and Configuration Parameters
  To interface with the BC127 in command mode, you need to be aware of three things: the specific commands it will accept, the responses of the module to those commands, and the various configuration parameters that the user has control over.
  Commands
  We're going to discuss some of the more useful commands here. For each one, we'll provide the syntax, expected responses, and a discussion of the command's actions. Reminder--terminate your command strings with a carriage return only! Extra newlines will cause an error.
  RESET - Resets the module to its currently stored default settings. You can see in the screenshot above the expected response. Note that this does not restore the factory defaults.
  RESTORE - Resets the module to the factory default settings. Returns
  OK when complete. This restoration is only temporary, and upon a
  RESET the module will revert to the currently stored settings.
  WRITE - Stores the current settings in non-volatile memory, to be used for configuration on next reset or power up. Returns
  OK when complete. Many settings require a restart of the module before they take effect; if you don't
  WRITE the current settings to non-volatile memory before issuing a
  RESET command, they'll be lost and the changes won't take effect.
  Issuing
  RESTORE,
  WRITE,
  RESET will return the module to factory defaults and may be a good way to start out any program using the BC127, to provide a known good starting point.
  GET and
  SET - These two commands allow for access to the configuration parameters that we'll delve into below; generally, a
  SET command will incur an
  OK response, and
  GET will cause the module to respond with the current value.
  Responses
  Any command will cause a response to be issued by the module. This will take the form of a string entirely composed of ASCII characters, terminated by both a new line ('\n' or 0x0A) and a carriage return ('\r' or 0x0D), in that order. As with commands, I'll assume that these are implicit whenever I mention a response.
  All characters in all response strings will be all caps, unless the repsonse string represents received data in some way.
  The two most common responses are "OK" and "ERROR". The receipt of either of these indicates that the characters entered since the last carriage return have been parsed and the input buffer is empty. For commands that take some time to execute (for example, scanning for local advertising BLE devices), many other commands cannot be submitted and will cause an "ERROR" response if submitted before the "OK" response signaling the end of the extended command is received.
  Below are some of the responses the module can send in response to actions taken by the remote unit; these are naturally in addition to the responses to locally issued commands that we covered above.
  CLOSE_OK SPP - The remote connection has closed the given profile. Note that SPP is just an example; that parameter can be of any type of connection, and in the event of the remote device closing all connections, you will receive one message for each profile that was connected. This can also mean that the remote device has moved out of range or been switched off.
  PAIR_PENDING - A remote device is attempting to connect to the module.
  PAIR_OKAY - A remote device, with the address immediately reported after the
  PAIR_OKAY message, has successfully paired with the BC127. Will be followed by one or more
  OPEN_OK messages detailing the types of connections that were established.
  AVRCP_STOP,
  AVRCP_PLAY,
  AVRCP_PAUSE,
  AVRCP_FORWARD,
  AVRCP_BACKWARD - The remote AVRCP device has executed this command. Not all devices will return all of these messages upon execution of a command.
  Configuration Parameters
  In addtion to the commands listed above, there are numerous configuration parameters which can be set or read back using the
  SET and
  GET commands. Generally, the format for setting a value is
  SET PARAM=VALUE1 VALUE2 VALUE3; parameters will always have at least one parameter and may have several. When entering multiple parameters, separate subsequent parameters to the first with a space. Ther should be no whitespace between the parameter name, the equals sign, and the first value; whitespace in that region will cause an error.
  It is possible to read back the current state of all configuration parameters by entering the
  CONFIG command; many of these values will not be cover here.
  BC127 Profiles
  The BC127 supports several different "profiles", which are connection types specified in the Bluetooth standard. These profiles determine the capabilities of the device and how the device responds to input.
  General Connection Information
  Connections between devices are managed differently when the connecting device is Bluetooth Classic or Bluetooth 4.0 (also referred to as Bluetooth Low Energy, or BLE).
  Classic Mode
  Here are useful commands for Classic mode connection control:
  CLOSE disconnects from one of the links returned by
  STATUS. Pass as a parameter either a single digit corresponding to the link ID returned by
  STATUS or
  ALL, to disconnect all connections. Note that it is possible to disconnect a single profile connection but remain connected to a device with other profiles. Also note that, so long as the parameter passed is valid, this command will return
  OK, whether there is a connection with that link ID or not.
  As you can see above, there are two responses from this command:
  OK, which indicates that the command was received locally successfully (i.e., no typos) and
  CLOSE_OK SPP, which tells you that the remote device was disconnected successfully. If there had been no connection open with link ID 0, the
  CLOSE_OK message would not have appeared.
  DISCOVERABLE mode makes the device discoverable by other Bluetooth Classic devices in range (
  ON). The device will automatically switch to
  OFF when a connection is made; executing
  DISCOVERABLE ON will disconnect any existing connections.
  INQUIRY looks for local Bluetooth Classic devices that are discoverable. Requires an integer parameter between 1 and 48; that value determines the length of time the inquiry will last; the timeout will be equal to 1.28s times the passed value.
  The response is as seen above. The
  INQUIRY string denotes that a device has been found. It is followed by 12 hexadecimal digits, which are the address of the device, and then six more hexadecimal digits conveying the device's capabilities. This six-digit value, the Class of Device value, is generally beyond the scope of this document. Finally, you'll see a signal strength indicator. Anything above -70db is probably strong enough to make a good connection.
  Once the
  OK response string has been received, the inquiry process is complete.
  LIST prints a list of all devices currently paired with this module, whether they are connected or not. The BC127 can store up to 8 devices in this list. Devices in this list persist through resets or power cycles even without a
  WRITE having been executed
  OPEN establishes a connection to a device at a given address of a given type. The above example shows a connection of type Serial Port Protocol with a device at address 20FABB0101CD. Note that all of the letters in the address and connection type must be in all caps!
  The responses for this can vary. A successful connection will return the above messages:
  PAIR_PENDING indicates that the device was found,
  PAIR_OK followed by an address indicates that the pairing process completed successfully, and
  OPEN_OK indicates that the connection with the stated profile was successful. If there is an error in the command syntax (i.e., not enough characters for a valid Bluetooth address, or invalid profile type), the response will be
  ERROR. If no device at that address is found, you'll receive
  OPEN_ERROR. If the device is not accepting connections of the specified profile, you will get the
  PAIR_OK message, but you'll see the
  OPEN_ERROR message for the connection.
  Available connection types are A2DP, AVRCP, MAP, HFP, PBAP, SPP and BLE. We'll talk about these connection types (usually referred to as "Profiles") later on in this tutorial.
  RSSI returns the current link's signal strength.
  STATUS returns information about the current state of the module. As you can see above, the first line of the response is
  STATE followed by some information. Options here are
  CONNECTED,
  DISCOVERABLE,
  CONNECTABLE, or
  ADVERTISING.
  DISCOVERABLE and
  CONNECTABLE may both be returned at once.
  If the module is
  CONNECTED, a list of links will follow the
  STATE response. Each link is given a reference ID, status, profile type, and address of connected device. In the above example, we have one connection: Link ID 0 is connected with serial port profile to a device at address 20FABB0101CD.
  UNPAIR clears the list of paired devices. This does not affect the remote devices' idea of what they are paired with, however.
  These are parameters which are useful for Classic connections. To change or view them, use the
  SET and
  GET commands as detailed on the previous page.
  AUTOCONN=value controls the automatic connection of paired devices upon reset or power up. When value is
  0, the BC127 will not attempt to connected to any previously paired devices at startup. When value is
  1, the BC127 will attempt each of the paired devices (as reported by the
  LIST command; the number of attempts to connect to each device is set in the
  MAX_REC parameter. When value is
  2, the BC127 will attempt to connect to a device whose address is stored in parameter
  REMOTE_ADDR on startup. To change this value, a
  WRITE
  RESET cycle is required.
  CLASSIC_ROLE=value determines the role of the device:
  0 for sink,
  1 for source. This becomes important when connecting BC127 devices together for audio purposes; it determines which device sends audio and which receives.
  DISCOVERABLE=value timeout sets the devices mode on startup. This is different to the
  DISCOVERABLE command! The command of the same name controls the immediate discoverability of the module; this sets the default state on startup.
  0 makes the device undiscoverable on boot.
  1 makes the device discoverable on boot, but only if it fails to autoconnect to one of its paired devices.
  2 makes it immediately discoverable and overrides the autoconnect setting entirely. The value of timeout determines how long it will remain in discoverable mode before going to power save mode, in milliseconds; set that value to 0 for infinite wait.
  LOCAL_ADDR=value prints the modules address to the serial port. Any attempt to change this will generate and error.
  MAX_REC=value sets the number of times to attempt to reconnect to each paired device in the list of paired devices when autoconnecting. Defaults to 2 times.
  REMOTE_ADDR=value provides a single address to attempt to reconnect to at startup (assuming
  AUTOCONN=2). The BC127 will attempt to connect
  MAX_REC times.
  RSSI_THRESH=value puts a bottom limit to the signal strength the module will accept as a solid connection. Default is -75db.
  Bluetooth 4.0 Mode
  Many of those same settings and commands can be applied to Bluetooth 4.0 connections; here are the BLE-specific commands:
  ADVERTISING value can be passed
  ON or
  OFF to start and stop BLE advertising. The
  BLE_ROLE value must be 1 for this to work; we'll discuss that later.
  SCAN is equivalent to
  INQUIRY for Bluetooth 4.0 devices. Note that before executing
  SCAN, the module must be made into a Bluetooth 4.0 central device by setting parameter
  BLE_ROLE to 2, writing that value to non-volatile memory, and resetting the device.
  The response is very similar to that for
  INQUIRY; the first field of the response is the address, the second field is the "short name" of the device, the third gives information about the device (0A indicates a general purpose dual-mode device; 02 would be a single mode device), and the fourth is the received signal strength.
  SEND BLE data transmits data across the BLE link. The BLE connection does not currently support data mode; data can only be sent and received in command mode via the
  SEND command.
  There is only one parameter associated with Bluetooth 4.0 connection only:
  BLE_ROLE=value sets the type of device the BC127 will function as.
  SCAN can only be performed if
  BLE_ROLE=2;
  ADVERTISING will only work if
  BLE_ROLE=1. BLE can be disabled by setting this parameter to 0.
  As we discuss individual connection protocols, we'll add more information as required for each one.
  Serial Port Protocol
  Most of the tinkering with Bluetooth devices in the past has focused on SPP- the Serial Port Protocol. In this mode, the device emulates a physical serial port, passing data (and, potentially, handshaking signals) across the ether as though it were a physical, wired connection.
  There are several commands associated with SPP connections:
  $$$$ will cause a BC127 in data mode to exit data mode and return to command mode. In order for this to work, however, there must be a guard time before the first character and after the last character; this guard time is set in paramter
  CMD_TO and will be discussed in the parameters section.
  ENTER_DATA will put the device in data mode; any serial data coming into the serial port will be transparently forwarded to the remote device.
  SEND SPP string will cause string (or whatever other data preceds the carriage return at the end of the command) to be sent over the serial connection. This allows data to be sent without entering data mode. If data is received and the module is not in data mode, the data will be prepended with
  RECV SPP.
  There are quite a few parameters which can be set to allow for very flexible connections with the BC127 over serial:
  BAUD=value sets the baud rate of the incoming and outgoing serial data. Valid values are 9600, 19200, 38400, 57600, 115200, 230400, 460800 and 921200; modules default to 9600 when set to factory defaults.
  CMD_TO=value controls the guard time for detecting the
  $$$$ command to exit data mode. There should be a 20ms * value break in serial data before and after the
  $$$$ for it to be recognized; failure to respect this guard time will result in a string of four dollar signs being sent rather than causing the device to exit data mode.
  ENABLE_SPP=value allows the user to selectively disable connections over SPP. Default is
  ON; any change in state requires a
  WRITE
  RESET to take effect.
  FLOW_CTRL=value enables and disables the use of the hardware flow control pins on the BC127. Requires
  WRITE
  RESET to take effect.
  PARITY=value enables and disables a parity bit for the serial data, where
  1 is no parity (default),
  2 is even parity, and
  3 is odd parity.
  SPP_TRANSPARENT=value determines whether a new SPP connection immediately activates data mode or not.
  OFF by default, and requires
  WRITE
  RESET for any change to take effect.
  AVRCP AND A2DP Protocols
  A2DP stands for Advanced Audio Distribution Profile; AVRCP is the Audio/Visual Remote Control Profile. The two are intricately related; you cannot have an AVRCP connection open without an A2DP connection open as well. You can, however, have only an A2DP connection open.
  A2DP is a two-channel audio streaming protocol, which transfers data from a source to a sink. The source can be a cell phone, a media player, or the audio input on another BC127 (or similar) module. AVRCP allows the BC127 to send commands to the remote device which will cause the remote device to play, pause, stop, advance or reverse playback; some remote devices will transmit track meta data back to the BC127 via the AVRCP protocol.
  The BC127 also supports the Hands-Free Protocol (HFP); we'll talk about that later, but for now be aware that incoming calls over the HFP connection will override data on the A2DP connection.
  Here are the commands you'll need to know to get A2DP and AVRCP working properly:
  MUSIC instruction sends a command over the AVRCP link to the A2DP source device. Valid options for instruction are
  PLAY,
  PAUSE,
  STOP,
  FORWARD and
  BACKWARD.
  VOLUME flag has different options depending on whether the device is a sink or source (as defined by the
  CLASSIC_ROLE parameter discussed below). If the device is a sink, the local volume will change, but no remote volume change will occur. If the device is a source, the volume at the remote device will change. Valid values for flag are
  UP,
  DOWN, and
  A2DP;
  A2DP will report the volume level set for the A2DP speaker.
  If flag is formatted as
  A2DP=value, that will set the volume as above to a value between 0 and 15.
  These are the parameters governing A2DP/AVRCP connections:
  AUDIO=value routes the A2DP audio stream from various sources/sinks. Options are 0 for analog (default), 1 for PCM Master, 2 for PCM Slave, 3 for I2S Master, 4 for I2S Slave, and 5 for SPDIF.
  WRITE
  RESET required after changes.
  BPS=value sets the bits per sample for I2S and PCM codecs. Valid values are 8, 13, and 16 for PCM and 16 and 24 for I2S.
  WRITE
  RESET required after changes.
  CLASSIC_ROLE=value allows user to set the device to source (1) or sink (0). This is important when attempting to make a connection between two BC127 modules, as it determines which module is expecting to send audio data and commands and which is expecting to receive. We'll cover that in an example, later.
  WRITE
  RESET required after changes.
  ENABLE_A2DP=value and
  ENABLE_AVRCP=value allow the user to selectively enable and disable connections over A2DP and AVRCP.
  WRITE
  RESET required after changes.
  I2S=value controls various parameters of the I2S system See page 15 of the BC127 manual for details on this.
  WRITE
  RESET required after changes.
  INPUT_GAIN=value controls the gain level of the analog input to the device. Supports values between 0 and 15; the default value is reported as 16, although it is in fact 15.
  On the next page, we'll walk through examples of interfacing the BC127 with a couple of different audio sources.
  HFP and PBAP Protocols
  HFP (Hands-Free Protocol) and PBAP (Phone Book Access Protocol) are implemented to support connections to cellular phones. They are related, in that most devices that support one will support both, but are not as closely related as AVRCP and A2DP.
  HFP allows you to make and receive phone calls using a BC127 module. If an A2DP link is present as well as the HFP link, the HFP link will override the A2DP data stream when a call is received.
  Here's a list of commands for accessing the HFP and PBAP functionality:
  ANSWER accepts the incoming call on the HFP link.
  CALL number initiates a call on the HFP link; if two BC127 modules are connected, this will create a bidirectional HFP link (i.e., walkie-talkie).
  END hangs up an active call.
  PULL_PBOOK option initiates retrieval of the phone's phonebook, call list or some subset thereof. If no option is passed, or the option
  PHONEBOOK is passed, the phonebook will be downloaded. For call lists, the options are
  OUTGOING,
  INCOMING,
  MISSED, or
  COMBINED. The response for each item in the list takes the following format:
  PBAP_PB NAME: name PBAP_PB TEL: number
  Once all requested data has been delivered, the message
  PBAP_PB OK will be sent.
  PULL_ABORT stops a phonebook download in progress; PBAP profile connections cannot be close during an active phonebook pull.
  REJECT will cause an incoming call to be rejected.
  TOGGLE_VR will activate voice recognition dialing on the phone.
  TRANSFER_CALL sends audio back to the phone. This may cause the phone to drop the Bluetooth connection; that varies with phone model.
  VOLUME flag allows for control of the speaker volume. Flag values
  UP and
  DOWN control speaker volume;
  HFP will return the current HFP speaker volume.
  MIC_MUTE reports the mute state of the microphone.
  If the flag takes the form
  flag=value, the HFP volume can be adjusted independently of the A2DP stream, and
  MIC_MUTE=ON will mute the microphone.
  There are some parameters controlling HFP and PBAP connections, as well:
  ENABLE_HFP=value and
  ENABLE_PBAP=value can be
  ON or
  OFF to allow or disallow HFP and PBAP connections.
  WRITE
  RESET required after changes.
  FORCE_ANALOG_MIC=value forces the use of the analog input in HFP even if a digital audio interface is selected.
  WRITE
  RESET required after changes.
  Up Next: Usage Examples!
  Now we're going to explore how to connect BC127 modules to various targets, including a cell phone, another BC127 module and a generic Bluetooth module as serial port.): 'OPEN.
  Example: SPP Connection
  On this page, we'll provide an example Arduino sketch connecting two boards, each of which has a pushbutton and an LED, and pushing either button will light up both LEDs.
  For simplicity's sake, we're going to write this so the code and hardware for both processors is the same.
  The Hardware
  I'm going to keep this simple:
  - two SparkFun Arduino Pro Minis
  - two BC127 breakout boards
  - two buttons
  - two 10k linear potentiometers
  - four red LEDs (with 330-ohm current limiting resistors).
  As I said above, the hookup and code for the two boards will be identical.
  Here's a Fritzing diagram showing the connection of one half of the setup; make two of these:.
  Everything you need to know is in the comments.(3,2); // RX, TX // Create a BC127 and attach the software serial port to it. BC127 BTModu(&swPort); // Aliases for the input and output pins we're going to use. #define POTPIN A0 #define PWMLED 6 #define BUTTONPIN 7 #define DIGLED 8 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); // Blast the existing settings of the BC127 module, so I know that the module is // set to factory defaults. BTModu.exitDataMode(); // Just in case...do this or other commands won't take. BTModu.restore(); BTModu.writeConfig(); BTModu.reset(); // Configure the inputs and outputs. pinMode(BUTTONPIN, INPUT_PULLUP); pinMode(DIGLED, OUTPUT); String buffer; // We'll use this for capturing data from the module. I'm using // a String to make it easy to parse. // NB- we can assume that at this point our soft serial buffer is empty; that's // all handled by the restore/write/reset cycle at the top. For other programs, // your mileage may vary on this point, so it might not be a bad idea to purge // the buffer before you start reading in from it. // Okay, first tricky bit. Since we've got the same code on both boards, we need // some way to pair them. We want to wait here until the board is paired; what // we'll do is wait for the button to be pressed, and then initiate pairing. We // will also monitor traffic coming in from the BC127 and watch for the string // "OPEN_OK SPP\n\r"; if we see that, we can bail, since we know the module // is now connected. We *could* use the connectionState() function, *but* that // function has such a long latency (it takes about 500ms to get a definitive // answer from the module) that the chance of missing a button press is really // pretty high- you'd have to hold the button for 500ms to be sure to catch it. while (1) { // We're going to do two things in this loop: check for a connection message, // indicating that we were connected to by a remote device, and check for the // button press and try to connect when we see that. Here's the connection // message polling part. // We need to buffer our incoming serial data... if (swPort.available() > 0) buffer.concat((char)swPort.read()); // ...then, we need to check if it's a full line from the serial port, and // check its contents if it is. if (buffer.endsWith("\r")) { // If the buffer has a serial port connection message, we can break out of // the while loop after entering data mode. if (buffer.startsWith("OPEN_OK SPP")) { BTModu.enterDataMode(); Serial.println("Connected!"); break; // Exit the while loop. } buffer = ""; // Otherwise, clear the buffer and go back to waiting. } ////////////////////////////////////////////////////////////////////////////// // Okay, this next bit is the push button polling section. Note that once the // button has been pressed, it's quite a long time (10+ seconds) before we // return to what we were doing above. if (digitalRead(BUTTONPIN) == LOW) { Serial.println("Attempting to connect..."); if (BC127Connect() == BC127::SUCCESS) { Serial.println("Connection succeeded!"); break; } else Serial.println("Connection failed. Back to waiting!"); } } } // Ideally, I'd have made this a static variable and put it inside loop(), but that // causes Arduino to have a little hissy-fit, so I'll make it a global instead. String inBuffer = ""; // If we've gotten to loop(), we can assume that we're connected to the remote // device. We're going to pass a packet back and forth that looks like this: // xy\r // x - 8-bit value for the brightness of the dimmable LED. // y - 0x00 or 0x01 for whether the remote button is pressed or not. // \r - end of string value. \r is not a valid data byte, so it makes a good // check on complete packet receipt. void loop() { // These are the variables we need to get this job done. By making them static, // they only get initialized once and persist through loop calls. static byte outBuffer[3]; static int ledVal = 0; static boolean buttonVal = false; static unsigned long lastLoop = millis(); // This first bit is where we handle the receipt of characters from the remote // device. We'll handle our data collection and sending later. // Add to the buffer one character at a time... if (swPort.available() > 0) inBuffer.concat((char)swPort.read()); // ...then check to see if we've received an end-of-packet character... if (inBuffer.endsWith("\r")) { // ... and parse the packet if we have. ledVal = (int)inBuffer[0]; // This is a pre-linearized value from the pot on the // other board. digitalWrite(DIGLED, (int)inBuffer[1] ? LOW : HIGH); // This is the other board's // button state. We want to invert it, of course, so a received 1 // (indicating the other button is high/unpressed) results in a low // for this board's LED. inBuffer = ""; // Clear the buffer. } analogWrite(PWMLED, ledVal); // Our standard "loop without delay" method. if (lastLoop + 50 < millis()) { lastLoop = millis(); outBuffer[0] = (byte)(linearizeLED(analogRead(POTPIN))); outBuffer[1] = (boolean)digitalRead(BUTTONPIN); outBuffer[2] = '\r'; swPort.write(outBuffer[0]); swPort.write(outBuffer[1]); swPort.write(outBuffer[2]); } } // Sweet little function that takes a potentiometer's input and turns it into a // PWM values that will appear, to a user, to be a linear brightness increase // across the range of the potentiometer. int linearizeLED(int potVal) { int PWMArray[] = {0, 1, 2, 3, 5, 7, 9, 12, 16, 20, 25, 31, 38, 46, 54, 64, 75, 87, 100, 114, 130, 147, 165, 185, 207, 230, 255}; byte index = map(potVal, 0, 1024, 0, 26); return PWMArray[index]; } // Useful function which identifies a local BC127 module and connects to it. int BC127Connect() { int connectionResult = BC127::REMOTE_ERROR; // Our return value. Assume failure. BTModu.inquiry(10); // Spend 13 seconds seeking local devices. String address; // Buffer for addresses we've found. // This loop will scan through the addresses found (there will be a maximum of // five) and identify any BC127 modules (their addresses all start with "20FABB"). for (byte i = 0; i < 5; i++) { // If there IS an address at index i... if (BTModu.getAddress(i, address)) { // ...check to see if it's a BC127 and if it IS... if (address.startsWith("20FABB")) { // ...attempt to connect to it... connectionResult = BTModu.connect(address, BC127::SPP); break; // ...and quit looking at the rest of the addresses. } } } // Okay, hopefully, by now we've found and connected to a BC127. If not, return // an error... if (connectionResult != BC127::SUCCESS) return connectionResult; // ...but, if so, we want to try to enter data mode. else connectionResult = BTModu.enterDataMode(); return connectionResult; }
  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:
  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 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:); 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.
  As with the receiver, we want to watch for a failure in the connection, then reconnect.); 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); } }
  Resources and Going Further
  For more information on the BC127 module, check out these documents:
  - SparkFun Bluetooth Audio Breakout - BC127
  - SparkFun Purpletooth Jamboree - BC127 Development Board
  - Module Datasheet
  - Melody v5.0 Manual- this is the complete reference for the commands and behavior of the firmware that ships with the BC127 modules we sell
  - Melody v5.2 Manual- this is a pre-release and unsupported version of the firmware which neither we nor BlueCreation will offer support for. If you update your module's firmware to this (which we will not tell you how to do), you're on your own!
  - GitHub Code Repo: Arduino Library
  For more tutorial action, check out these related links: