Continuous Bluetooth LE data transfer to iPhone using the RedBear BLE shield

This is an update on our work on creating a bluetooth home health monitor in my class BME 440/441 "Senior Design in Biomedical Engineering".  The idea is to create an iPhone app that can connect to several Bluetooth LE sensors (ECG, EEG, Galvanic Skin response) and then display and record the data.  There will also be a data analysis component to actively monitor the health of the subject.

This post will describe a simple Arduino sketch that measures an analog signal at regular time intervals and then sends it through the Bluetooth connection of the RedBear BLE Shield. The sketch uses a timer to set the frequency at which analog pin 5 is measured and writes it into a buffer that is then sent through the BLE shield. I had to add a flag analog_enabled to make sure that the BLE shield only receives data when connected to the iPhone app. Unfortunately, there is a bug in the RedBear BLE shield software that makes it necessary to first receive data before it can send (I used BLE_Shield_Library 1.0). I could not get this project to work without the iPhone first sending at least one byte of data. In our case, when the iPhone sends "I" then the BLE shield starts sending. When the iPhone sends "0" then the BLE shield stops sending. I also included the parameters for 100Hz and 2Hz data transmissions.  Here is the sketch:

untitled
#include <SPI.h>
#include <ble.h>

#define ANALOG_IN_PIN      A5

boolean analog_enabled = false;

void setup()
{
SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(LSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV16);
SPI.begin();
ble_begin();

// initialize timer1
noInterrupts();           // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1  = 0;

//100 hz timer setup
OCR1A = 2500;            // compare match register 16MHz/64/100Hz
TCCR1B |= (1 << CS11) | (1 << CS10);    // 64 prescaler
TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
TCCR1B |= (1 << WGM12);   // CTC mode

/*
//2 Hz Timer Setup
OCR1A = 31250;            // compare match register 16MHz/256/2Hz
TCCR1B |= (1 << CS12);    // 256 prescaler
TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
TCCR1B |= (1 << WGM12);   // CTC mode
*/
interrupts();             // enable all interrupts
}

ISR(TIMER1_COMPA_vect)          // timer compare interrupt service routine
{
if (analog_enabled)  // if connected
{
// Read and send out
uint16_t value = analogRead(ANALOG_IN_PIN);
ble_write(value >> 8);
ble_write(value);
}
}

void loop()
{
while(ble_available())
{
// read out command and data
byte data0 = ble_read();
// if data is "I" then turn on transmission
// if data is "0" then turn off transmission
if (data0==0x49) {
analog_enabled = true;
}
else if (data0==0x30) {
analog_enabled = false;
}
}
// Allow BLE Shield to send/receive data
ble_do_events();
if (!ble_connected()) {
analog_enabled = false;
}
}


Now to the iPhone app. It can be found here: http://github.com/hstrey/BLEShieldConnect

The entry screen is a table view that scans for BLE devices and add them to the table. I used the new iOS6 pull down to refresh method that is really neat. When you select any of the available BLE shields, a Bluetooth LE connection is established and a new screen appears that displays the RSSI, analog value, and number of bytes send.  The number of bytes send is a measure for how often the BLE shield sends the data that is accumulating in the arduino buffer.

A few remarks about the BLE SDK 0.4 that RedBear provides.  I was not very happy about the object design.  The sdk provides a ble object that has a method to scan for Bluetooth devices but then you can only connect to one of those devices.  That did not really make sense in terms of object oriented design.  There should be a more general class that is used to scan and then there should be individual BLE devices that you can connect to and those will provide protocols to receive and send data.

The iPhone program is quite simple but there was one aspect of its design that I struggled with for a while.  When switching views I had to transfer the ble object between view controllers.  In the table view I use the ble object to find all BLE shields in the area.  When I select one, I need to connect and then define all the protocols in the next view which all happens in the ble object.  Because the data protocols of the ble object are needed in the data view controller I need to pass the ble object to the data view controller in the prepareForSeque method as such:

untitled
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"Show Bluetooth Data"]) {
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
BSCViewController *s = segue.destinationViewController;
s.ble=self.ble;
s.path=path;
}
}

In the data view controller I need to set myself as delegate and connect to the BLE device in viewDidLoad. When I return to the table view I need to disconnect and tell the Arduino to stop sending data. At first, I tried to set the ble delegate to nil but that was not necessary.

untitled
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.ble.delegate=self;
[self.ble connectPeripheral:[self.ble.peripherals objectAtIndex:self.path.row]];
}

- (void) viewWillDisappear:(BOOL)animated
{
NSLog(@"ViewController will disappear");
if (self.ble.activePeripheral)
if(self.ble.activePeripheral.isConnected)
{
//send BLE shield "0" to turn off transmission
UInt8 buf[1] = {0x30};

NSData *data = [[NSData alloc] initWithBytes:buf length:1];
[self.ble write:data];
// after that cancel connection
[[self.ble CM] cancelPeripheralConnection:[self.ble activePeripheral]];
}
}

Back in the table view controller I simply reconnect the ble.delegate to self. This is necessary since viewDidLoad will only be called once.

untitled
-(void)viewWillAppear:(BOOL)animated
{
//reconnect delegate when coming back to table view
self.ble.delegate = self;
}

Now lets talk about the performance. With this setup, I was able to send 100 data points (2 bytes each) per second easily to the iPhone. At 200 data points per second the buffer overflows and the BLE arduino sketch crashes. Believe it or not, the RedBear BLE Arduino library does not protect from buffer overflows. I am planning to do a similar test with Dr. Kroll's BLE Shield because for our project we need 200 data points per second per sensor.

Let me know if you have any questions.

MOSFET LED Driver

In the past few months we switched all our microscopy illumination to LEDs.  LEDs have many advantages: 1) they are cheap ( few dollars a for high powered LED ); 2) they come in pretty colors; 3) they can switch very fast.  This post will explore how you can control and switch LEDs fast.  Specifically, we will build a setup that allows us to trigger a camera and then send a short (microsecond) LED pulse to illuminate the CCD camera chip.  This is important for applications for fast moving objects in microfluidic channels.  We also use this technique to measure the speed of droplets in channels.  In this case we send a trigger signal and then two LED pulses during the same exposure time.  That results in a double exposure image.  The distance between the two objects divided by the time difference is the speed of the droplet.  The trigger timing can be achieved by a microcontroller or a FPGA (I will write about this later).

But now I would like to describe our TTL driven MOSFET switch.  I was looking around on the web for solution but I could not find much detail on how to design such a switch.  Most designs on the web did not work for me or did not perform well in terms of switching speeds.  So here is my solution.  The basic idea is to use a MOSFET that is designed for low voltage gate switching (IRF520).  The other is to limit the supply voltage to around TTL level by a resistor that is in series with the LED (has to be 10W or so).  In this case we are using a high powered LED that can take 700mA.  In this configuration, we achieve 700mA at 5.6V supply voltage.  The rest is simple.  I included a pulldown resistor of 10k and a small resistor between the TTL in and gate.  It turns out that 300 Ohm is best for fastest switching times.

I also experimented with LED power supplies that control the current (Buckpack).  Unfortunately, these power supplies produce pretty high frequency oscillations that interfere with high speed switching.  We simply use cheap variable voltage power supplies for driving our LEDs.  This has the advantage that we can regulate the intensity of the LEDs.

Here is our oscilloscopes output for a 10µs TTL pulse.  The circuit switches the LED on at about a microsecond after the pulse arrives and turns it off about a microsecond after the pulse ends.  I have no clue where these oscillations at the end come from.  The LED visibly blinks down to about 1µs pulse width.

The whole circuit, including the LED, can be build for about 15 Dollars.  This is much much less than what companies charge for LED illumination.  Some of the cheapest LED solutions are on the order of 300-2000 Dollars.  In order to replace your standard microscopy illumination (usually a halogen lamp) with an LED you have to place the LED exactly at the same position as the halogen bulb.  In some cases we added a small x-y stage to optimize the placement.  Thorlabs sells collimation adaptors for most microscopes.  In our case we use a collimator for Zeiss Axioscope (COP4-A) and a coupler (SM2T2). The inside diameter of the coupler is a little less than 5cms and we simply mounted our LED in the middle of a 5cm circular heat sink and wedged it into the coupler.  The coupler screws into the collimation adaptor and allows us to optimize the distance between LED and the lens.

This is how the final assembly for our Zeiss microscope looks like.