notes on bluetooth

Hey guys,

This entry is long overdue but hopefully still helpful to those interested in working with bluetooth in your projects. Bluetooth technology is both 1) a desirable, relatively low energy way (in comparison to WiFi) to get separate microcontrollers to communicate wirelessly and 2) extremely confusing and frustrating, in my amateur opinion. I went through some trial and error working with it in the making of my Illuminati turn signal jacket and would like to share my findings with y’all.

First off, there is a big difference between Bluetooth classic and BLE (Bluetooth low energy). Bluetooth classic is designed for constant communication and more intensive data streaming between devices, while BLE is best for intermittent “small data” transfers and conserving battery life. More info on Bluetooth classic VS. BLE here.

The first bluetooth modules I purchased, rather naively, were the Adafruit Bluefruit LE modules designed for the Flora. This is when I learned that in the world of bluetooth, there are slaves and there are masters.

adafruit-flora-bluefruit-le-modul-bluetooth-ble

Now, a master can play the role of a slave, but a slave cannot play the role of a master. And a master can have many slaves, but a slave can have but one master. That sounds like the darker side of American history, or some kinky shit straight from the pages of 50 Shades of [Blue], but it has to do with the complexity and versatility of the bluetooth module and its programming capabilities. Essentially, masters initiate connections and ‘can do more stuff’, so master-capable boards have more junk on them. Many of the handy breakout boards you see on Sparkfun or Adafruit are examples of simpler slave modules, which are a lot easier and typically cheaper to work with. Adafruit and Sparkfun have even designed apps that allow you to interact with your project in specific ways. But if you are looking to do something outside of connecting your microcontroller to your phone or computer–i.e., connecting two or more of your microcontrollers–you’ll need to attain and work with master-capable modules.

Since I could not connect the Bluefruit modules to one another, I purchased two of these Bluetooth classic HC-05 modules (which can be either a master or slave):61b8oCGYJdL._SL1191_.jpgI had to configure one to be the slave (for the glove switches/remote) and one to be the master (for the jacket’s “brain”), a process that involved controlling power flow to the HC-05s, connecting to a serial console and use of AT commands, as well as setting specific baud rates. Here is a nice blog post that explains all this in greater detail, as well as how to pair or bond the modules. I used these HC-05s to make my tester units talk to each other, a very exciting moment! seen here:

Programming for master units is a little difficult because 1) these kinds of modules must be programmed separately from the microcontroller and 2) none of the sample sketches readily available through Sparkfun or Adafruit contain examples of code that utilize bluetooth modules as masters (for obvious reasons). Here’s the source code for the glove’s HC-05, communicating the status of its contact switches to its master:

#include <BLE_API.h>
#define DEVICE_NAME "HRM1"
BLE ble;
Timeout timeout;
static uint8_t bpm = 0;
static const uint8_t location = 0x03;
static uint32_t cnt;
static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE};
GattCharacteristic hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, &bpm, sizeof(bpm), sizeof(bpm), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic *hrmChars[] = {&hrmRate, };
GattService hrmService(GattService::UUID_HEART_RATE_SERVICE, hrmChars, sizeof(hrmChars) / sizeof(GattCharacteristic *));
void disconnectionCallBack(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
 ble.startAdvertising();
}
void m_uart_rx_handle()
{ //update characteristic data
 ble.updateCharacteristicValue(hrmRate.getValueAttribute().getHandle(), &bpm, 1);
}
void uart_handle(uint32_t id, SerialIrq event)
{ /* Serial rx IRQ */
 if(event == RxIrq) {
 uint8_t newState = 0;
 while(Serial.available()) {
 newState = Serial.read();
 }
 if(newState != bpm) {
 bpm = newState;
 timeout.attach_us(m_uart_rx_handle, 100000);
 }
 }
}
void setup() {
 Serial.begin(9600);
 Serial.attach(uart_handle);
ble.init();
 ble.onDisconnection(disconnectionCallBack);
// setup adv_data and srp_data
 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
 ble.accumulateAdvertisingPayload(GapAdvertisingData::HEART_RATE_SENSOR_HEART_RATE_BELT);
 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
// set adv_type
 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
 // add service
 ble.addService(hrmService);
 // set device name
 ble.setDeviceName((const uint8_t *)DEVICE_NAME);
 // set tx power,valid values are -40, -20, -16, -12, -8, -4, 0, 4
 ble.setTxPower(4);
 // set adv_interval, 100ms in multiples of 0.625ms.
 ble.setAdvertisingInterval(160);
 // set adv_timeout, in seconds
 ble.setAdvertisingTimeout(0);
 // start advertising
 ble.startAdvertising();
}
void loop() {
 ble.waitForEvent();
}

And the source code for the turn signal’s HC-05, receiving and responding to the UART data being sent from the glove’s:

// SERIAL LOOP SKETCH FOR COMMUNICATING WITH A BLUETOOTH SPP MODULE
// BASE HC-05 Config Commands
// AT+ORGL (Restore the factory default state)
// AT+UART=115200,0,0 (Set transmission rate to 115200 bps, one stop bit and no parity bit)
// AT+NAME=Smoothie
// AT+PSWD=0000 Set pairing code to 0000
#include <SoftwareSerial.h>
#define rxPin 10
#define txPin 11
SoftwareSerial mySerial(rxPin, txPin); // RX, TX
char myChar ;
void setup() {
 Serial.begin(9600); 
 Serial.println("AT");
 mySerial.begin(38400);
 mySerial.println("AT");
}
void loop() {
 while (mySerial.available()) {
 myChar = mySerial.read();
 Serial.print(myChar);
 }
 while (Serial.available()) {
 myChar = Serial.read();
 Serial.print(myChar); //echo
 mySerial.print(myChar);
 }
}

Disclaimer: this code was thrown together just to get the testers working. To do so, some sample codes were hacked together for the glove–that is why heart rate belts were referenced.

After getting the testers to work, I realized that BLE units would work a lot better for my purposes. The only data I needed to communicate between the jacket and glove was the status of the contact switches on the glove, so I could save a lot of battery life by switching over to BLE. I found these tiny, cute little modules, the Redbear BLE Nano:

static1.squarespace.png

BLE is a completely different technology from Bluetooth classic. Here is a useful “crash course” on BLE that contains some sample code for utilizing BLE modules as master/server. I will refrain from providing the code used on my project seen in crit unless requested, and then only privately, as I received a lot of help on it and feel it is not my intellectual property to share. It is still in need of further development, and as we are in the process of applying for a patent for our product, I have been advised to not “over share”.

I hope this helped a bit and if you have any questions, please ask!

And if anyone knows about Zigbee, please share!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s