From The Game of Life to the Internet of Things: Issues with Bluetooth Low Energy

In July I began a project to implement the Game of Life on
a number of Bluetooth Low Energy (BLE, a.k.a. Bluetooth Smart)-enabled
microcontrollers. At the end of the project, I was unsuccessful. But I feel I
have learned a lot on the way, and would like to share some of what I've learned and a few
reflections on what BLE is and isn't useful for at the moment.

The project

This project was part of an internship in a systems biology lab, and the
ultimate goal was to create an educational tool that could be used to
introduce some simple biology to students from computer science backgrounds.

The lab had received 64 nRF51822 mkit microcontrollers. These are
microcontrollers with a couple of buttons, a couple of LEDs, and BLE
capability, which can be programmed via the online mbed interface. The idea
was to implement Conway's Game of Life, using the microcontrollers as cells,
with other interesting features such as being able to change the update rules
for individual cells by pressing the buttons on the microcontrollers. They
were to communicate with their neighbours via BLE, and all state updates would be
calculated locally. In that way the system would mimic
biological cell behaviour to some extent (as the system behaviour would arise from the cell behaviour directly, rather than from a central computer storing and computing the whole grid).

Early signs of trouble

The mbed system is really easy to get up and running with. By lunch time on my
first day I had the lights flashing in a fibonacci sequence, and was
controlling them with the buttons (on top of my new lab's health and safety stuff and
meeting everyone). The next step would be to get the Bluetooth in action.
That's when the trouble began.

By default, these boards are not able to scan for other BLE devices. I might
write another post about how BLE actually works, but briefly:

  • Some BLE devices act as peripherals. A canonical example would be a digital, BLE enabled thermometer.
  • Other devices are so-called central devices. This might be a smartphone, or a raspberry pi with a bluetooth dongle.
  • A peripheral device advertises its existence. A central device scans for peripheral devices, and tries to initiate a connection.
  • A peripheral device can connect to one central device at a time. A central device can connect to many (the number is usually limited by the hardware or software implementation of BLE).

->BLE star topology<-

The gist of it is that we need one central device and one peripheral device,
and these boards could only act as peripheral devices. This was not a hardware
limitation: these boards run a bit of software called a SoftDevice (SD), which acts
as an interface to the hardware. They come loaded with the S110 SD, which only
supports peripheral behaviour. There is another SD available called S120,
which supports central but not peripheral behaviour. Finally, there is a
recently-released alpha version of the S130 SD, which supports both central
and peripheral behaviour.

The S130 sounds ideal for our purpose, and I spent a significant amount of
time getting it to work, with no success. It's an alpha release, and (at least at the time) had no available documentation. There was also little to no support for
the free gcc toolchain which I was using. (There was some support for the
expensive and Windows-only Keil toolchain).

(It took me quite a while to realise that the mbed platform only supported the S110 SD, and therefore didn't support any
scanning behaviour, which was not obvious to me at the time. I think mbed is a fantastic platform, but it could use more documentation in some places).

Plan B: could a dongle save my Life?

Although we couldn't get the boards to connect to each other directly, it was
quite easy to get simple peripheral behaviour working with mbed. That was made
even simpler when I came across the Puck library. I had the idea of getting a
Bluetooth dongle to connect to my laptop (or a Raspberry Pi). Then the laptop
could act as a central device and pass messages between the peripherals. For
example, the laptop could scan for and connect to microcontroller A and
microcontroller B. Microcontroller A could send the laptop a message saying
"Send B the message that my state is 1", then the laptop would sent B that message. This was a much less neat solution than just having the boards
communicate directly, but it would get us around the limited capabilities of
the SoftDevice on the boards we were using.

I found a useful node.js module called
Noble which provides a fairly nice interface to BLE in linux. Like the Puck library, Noble is mostly documented
by examples, and after a bit of fiddling around with those I was able to get
BLE communication between my laptop and the microcontrollers. I wrote a little
test program to notify the laptop when a button is pressed on the
microcontroller, and for the laptop to respond by sending a message to turn on
an LED on the microcontroller. (The code for that is on Github if anyone wants to play with it). This was promising: we had
microcontroller-to-microcontoller messaging at last.

The new problem was that it was very slow. Latency from an unconnected state over
BLE is claimed to be about 3ms, but sending a single byte of data indicating that a
button had been pressed and responding with another byte of data indicating
that an LED should be turned on takes about 1.5 seconds with our set-up. I
don't know where the speed problems are coming from (it could be the hardware
BLE implementation on the microcontroller or our BLE dongle, or a software
issue). For a fully-functioning Game of Life with 64 microcontrollers, each
needing to know the state of eight other microcontrollers for a single state
update, this was clearly much too slow for our purposes.

Another limitation was that depending on the BLE implementation, there is a
limit to the number of connections a central device can have open at a time.
Having to connect to different groups of microcontrollers in turn would
further add to the time overhead.

And, frankly, it seemed a bit silly to use a laptop to pass a byte from one
BLE-enabled microcontroller to another.

Lessons: what BLE is useful for and what it isn't

Bluetooth Low Energy was designed for a certain kind of device. One which
sends small amounts of data to a smartphone, or maybe a tablet, and does so no
more than once every few seconds. It's still a good solution for this kind of
purpose: sending small updates to a central device like a phone or a tablet.

However, due to the current state of BLE implementations, it is not currently
a good solution for communication between peripheral devices without an
intermediary central device. This isn't really a technical limitation: device
manufacturers could be doing more to make this kind of use easier. But for
now, I wouldn't recommend BLE for that kind of project.

I think this is a shame, because while the Game of Life on microcontrollers is
quite an esoteric use-case, I think there are more practical situations where
this would be useful. For instance, we could hook up our BLE thermometer to
another small BLE device which controlled an actuator to open or close a
window. This would be a nice, low energy solution without requiring a laptop
or other central device in the middle.

BLE is also not the right solution for situations where significant amounts of data need to be transferred between devices. I haved talked about 'sending messages', but actually communicated over BLE focusses on updating characteristics, which are small blocks of data usually storing the state of one thing (for example, the temperature read by a thermometer, or the live/dead state of a Game of Life cell). There are ways around this (splitting files into chunks of a few bytes at a time and updating characteristics with these chunks), but using BLE for these applications might be making your life needlessly harder.

These are all things that are worth keeping in minded before embarking on a BLE-based project, especially for Internet of Things (IoT)-type applications.

The future

The situation can change as the BLE ecosystem matures.

  • Currently, BLE support on platforms like Android is buggy and unreliable. Since BLE is currently so focussed on interfacing with such devices, improving support on major smartphone/tablet platforms would do a lot for BLE in general.
  • Manufacturers should recognise the broader scope for potential uses of BLE and provide better software support for them (as the hardware mostly already supports them).
  • There is a lot of incomplete documentation out there, and 'documentation by example'. More complete and clear documentation would make it a lot easier for people to understand what is possible with this technology, and how to use it.

Final note: the community

This blog post is a bit of a moan about the state of BLE
support in general. However, there's one thing that I have failed to
mention: the community. In my struggles many people were quick to offer advice
and help. The mbed community in particular, and the wider community of people
struggling to use BLE with microcontrollers, are full of kind and knowledgable
people. I would like to especially thank two people who were particularly
responsive to my many questions:

To get in touch about BLE (or anything else), I'm @ModusGolems on Twitter and jimi AT jfhcullen.com by email.