Introduction
The BBC micro:bit device is based around the nRF51 SoC (System on Chip), which has a built in 2.4 GHz radio. A natural progression of the coffee timer project was to make the sensor device broadcast its information over the air. Then we could create receiver devices which could notify users about fresh coffee, as well as let them check how old the current coffee was. We decided to make the receiver device battery powered, so that it could sit on a shelf or be moved around to where it was needed. The wireless method used had to allow for one-to-many communication, where the sensor device would broadcast its data to the receiver devices.
Concepts of Low Power Wireless
The concept ULP (Ultra low power) wireless is mostly used in small battery driven devices, such as a step tracker, pulse belt or wireless beacon. It is expected that a ULP device can last years on a 3v coin cell battery. So how do we create a device that uses a minimum amount of power?
- Use the radio as little as possible
- Sleep as much as possible
When we say “sleep” here, we are talking about a deep sleep which consumes as little power as possible. In a typical microcontroller system, this includes turning off most features, and only keeping on a low power clock. This clock works as a “alarm clock” which wakes the system up at the right time.
The radio is on both when sending data, as well as when a device is listening for data. Both these actions are a major power consumers in a ULP wireless system. Some devices will typically mostly send data (like a pulse belt), and other will mostly receive data (like a pulse watch). For a pulse belt, a good solution is to send data very fast, and with a long time between each transfer. However, this will impact the battery life of the pulse watch. If the watch is to receive all the data from the belt, it must listen for data a large portion of the time in order to always be listening when the belt is sending. In order to save battery on the watch, we could reduce the time it is listening for data, but then we risk missing data from the belt. If we know that the belt is sending data every second, we could allow the watch to sleep for one second every time it receives new data. Now we have synchronized the two devices, which allows both of them to sleep most of the time. This is one of the core concepts of ULP wireless solutions, and is used for example in Bluetooth Low Energy Technology.
This leads us to three options for creating ULP wireless devices:
- One device sends data rarely (low power), while the other device is listening all the time (high power).
- One device sends data very often (high power), while the other device is listening at short intervals (low power).
- The two devices are synchronized, and wakes up at the same time to communicate before going to sleep again. (both are low power).
Wireless Options on the micro:bit
As mentioned in the previous post in this series, there are several ways of programming the micro:bit device. Because of this, there are several APIs which interface with the built in radio of the nRF51.
- Bluetooth Low Energy (BLE) through Microsoft Block Editor and Microsoft Touch develop.
- Bluetooth Low Energy(BLE) through the uBit class in mBed.
- The uBit.radio interface of the uBit class in mBed.
- The radio interface of MicroPython.
- The bluetooth Low Energy(BLE) API in the Nordic nRF5 SDK.
- The Electronic ShockBurst API in the Nordic nRF5 SDK.
- Use the radio hardware directly (Custom protocol) with the Nordic nRF5 SDK.
The block editor and the rest of the editors intended for kids, offer a simplistic interface to bluetooth. One is easily able to create a wireless remote or similar which can be connected to with a smartphone. It does not allow for direct control of the BLE advertising, which is the way to broadcast data in BLE. This is the method used by for example BLE beacons to broadcast data to its surroundings. Since broadcasts are not available, we could not use these options in this project. As far as we know, there is no option to send generic data either, just predefined things like remote control buttons or camera triggers.
The mBed BLE API seemed to be the way to go, as it allows for direct control over the broadcasting. We created a working implementation using BLE to broadcast the “time since last brew” data. This data could be picked up by any BLE observer devices, like a smartphone (Read about BLE roles here). When we started to implement our own BLE observer on a micro:bit, we found out (after a lot of debugging) that the micro:bit does not support the BLE observer role out of the box. Which BLE roles a project supports, is dependant on which BLE stack is compiled into the application by mBed. We know that the nRF51 supports the observer role with the right BLE stack, but it is no obvious way to chance which stack mBed compiles into the application. This is decided by which target is chosen in the mBed online compiler, and probably by a #define
somewhere hidden a couple of layers down. It is definitely possible to make the micro:bit support the BLE observer role by fiddling with the target settings, but we decided not to invest even more time into that.
The “radio” classes of both MicroPython and the uBit C++ framework provide very generic radio capabilities. We can send data, as well as set up events which notify us when new data has been received. It is not clear how these transmissions are implemented on a lower level, but we guess that is kinda the point. These radio APIs are not low power, as the devices are always listening for received data in order to notify the program immediately. This is the option we ended up using, simply because it was the easiest to implement, and it worked out of the box. The receiver units are no longer ULP devices, but can last a couple of days on a battery if need be. We currently power ours with USB power, or a USB power bank if we need to move it around.
When using the last three methods (nRF5 SDK), we are treating the micro:bit as any other nRF51 device, and hence we lost all the nice micro:bit libraries for using the buttons, LED matrix, accelerometer and magnetometer. All of this is still available to us, but we must write our own drivers. The main reason for choosing these options are to gain complete control over what is happening, and to be able to implement a ULP solution to the problem. It must be said that the nRF5 SDK is in a totally different league in terms of complexity and size compared to the other options mentioned. One is only able to benefit from this option by knowing the SDK from other projects, or be prepared to spend time to learn about the nRF5 ecosystem. We did not experiment with this option in this project, based on the time it would take to write the drivers for the micro:bit hardware like the LED matrix. In hindsight, we probably should have started here instead of spending a lot of time making mBed BLE work.
Summary
When using Bluetooth Low Energy (BLE) , most approaches make it easy to make a BLE peripheral device, i.e a device which typically connects with a smartphone or laptop. For communication between two micro:bits, the proprietary protocols of the uBit class and the microPython framework work well, but do not provide options for low power operation. Treating the micro:bit like any nRF51 device will give full customizability, but with a significant increase in complexity.