Use your BBC micro:bit to display time, temperature, and more!
Overview of the hardware
This tutorial will show you how to connect various i2c components to your micro:bit, such as a pressure/temperature sensor, a real-time clock, and a big 7-segment display. The resulting demo can display the current temperature, or the current time. It also plays music using a piezo.
The tutorial will cover wiring, as well as API usage within TouchDevelop. This is more of a draft; feel free to do a better demo (such as an alarm clock that wakes you up using the piezo!).
This tutorial assumes cursory knowledge about: soldering, electronics, resistors, etc. Here's the final result (showing the current time):
Technical specs
The micro:bit has a 100kHz i2c bus with internal pull-ups. At the time of this writing (11/12) the current revision of the board is wired as follows. Please note that this wiring is incorrect for prototype green boards, and please note that the wiring is very likely to change for the final revision of the boards.
Some of the components we will use in this demo need a 5V input. When your micro:bit is plugged in via USB, you can hack a 5V line on a tiny circular pad on the back of the board:
Again, please double-check with your own board using a multimeter.
Then, use your soldering skills to get ahold of SDA, SCL, 3V and GND on the edge connector.
Using a breadboard adapter
An alternative way to get 5V and the other wires is to use a breadboard adapter that takes in a USB power supply, powers the micro:bit via the edge connector, and also breaks out the 5V and 3.3V lines on your circuit. Here's a prototype:
The connector thingy can be bought on digikey ↗. You would have to design the pcb yourself (hopefully someone will step up and manufacture the breadboard adapters...).
3V vs. 3.3V
The micro:bit works fine with both. Also, you can draw current from the 3V edge connector (when plugged in via USB or battery); or, you can power the micro:bit using the edge connector.
Hardware issues
Currently, driving the display while using i2c results in some voltage spikes on the SDA/SCL wires. We speculate that this is due to the power adapter on the micro:bit not reacting fast enough to the display drawing extra current. The net result is that there's garbage on SDA/SCL, which results in incorrect i2c transmissions, a bus lockup, followed by a software reset of the i2c module of the nrf51822. The lockup can last for a couple seconds! So don't use the display and i2c at the same time.
Software issues
The micro:bit sometimes freezes. We have yet to determine why, so the demo script resets itself every ten minutes...
Components
Basically, anything that works over i2c with a raspberry pi or an arduino will work with the micro:bit. You just have to be careful and make sure the i2c logic is at 3V. Here's the components we will use in this demo:
- a 7-segment display with i2c backpack (sold on adafruit ↗; pimoroni is based in the UK and has a similar, but smaller version ↗)
- a combined pressure & temperature sensor (pimoroni ↗, adafruit ↗)
- a real-time clock (keeps the time correct when the micro:bit is powered off) (adafruit ↗, pimoroni ↗)
- a piezo; anything will work (adafruit ↗, pimoroni ↗)
Soldering
Follow the instructions on Adafruit for the display ↗ and the pressure sensor ↗.
Important note for the RTC module:
- adafruit version: do NOT solder in the two pull-up resistors for the DS1307 module (so that the i2c logic remains at 3V); instructions are here ↗ but again, don't solder in the two resistors!
- pimoroni version: clear the jumper to disable i2c 5V pull-up (see schematic ↗) and get 3V instead
Wiring
Plug in the micro:bit onto a breadboard. Then, connect each component to the micro:bit. For all three components, there are labels next to each pin.
- display: this is a little bit tricky; you need five wires: IO is 3V, + is 5V, - is GND, D is SDA, C is SCL (board is 5V-powered but logic is 3V)
- ds1307: this is standard; just connect the four wires (board is 5V-powered but logic is 3V)
- bmp180: don't be confused, this board is 3V-powered and the logic is at 3V, so: VIn = 3V
For my demo, I also added my own 2.2kΩ pull-up resistors between 3V and SDA/SCL to make sure I had a good signal. I also have a few capacitors between 5V/GND and 3V/GND to smooth the signal.
If you examine the picture closely, you'll see that I have re-routed the two buttons from the micro:bit onto the breadboard. That makes sure I don't put extra pressure on the connector by pressing the micro:bit buttons, and use the ones on the breadboard instead.
Programming the thing
The script is available online. Search for "clock demo" and grab the latest version, or click here ↗ then hit update.
- The script uses three libraries, one for each hardware component.
- The main logic of the script is pretty simple: the
mode
variable controls the type of information that's currently displayed (temperature or time); one fiber takes care of blinking the colon on the 7-segment display; two other fibers take care of showing the time or temperature, when enabled. - If you hit the script name in the left pane, you'll see, below the script description, that "Uses C++ compiler is checked". More explanations about this in a minute.
- First task: write a script that uses the ds1307 library, and just calls
adjust
with the right values to make sure that your clock is set with the correct time! Make sure you flash your script at the right moment!
The 7-segment display library
The i2c protocol for the 7-segment display is fairly simple, so the entire library is programmed in TouchDevelop. The
♻ micro:bit extras
library contains i2c write
(write a byte at a given address) and i2c write2
(write two bytes at a given address) which, actually, is enough to drive the display. (The i2c "backpack" for the display uses simple registers and bitmasks to control each segment. There's a register for each digit, and another one for the colon.) The library also exports a bunch of constants for the various blink modes. The library was written by reading the Adafruit documentation ↗The ds1307 library
This library is a hybrid: some parts of it were written in TouchDevelop and some other parts were written in C++. Basically, writing more than two bytes over i2c is painful in TouchDevelop, so we might as well do it in C++. The implementation of the various functions is on GitHub in our glue layer ↗. The TouchDevelop library contains special
{shim:...}
annotations that basically mean: "when calling this function, really, generate a call to the « shim'd » C++ function".When you compile a script that has the "use C++ compiler" checkbox checked, some C++ is generated (hold Ctrl down when clicking on "compile" to see it). We then take the repository on GitHub, replace "main.cpp" with the generated C++, then compile everything together.
The bmp180 library.
Everything is written in C++ because there's a lot of floating-point computations to recover the temperature and pressure, and TouchDevelop only does integer arithmetic. The code is also on GitHub ↗ and was adapted from the Arduino library.
More hardware projects!
It would be really cool to expose more hardware components in TouchDevelop, but we're short on time. So if you want to help, feel free to write a library for extra components (i2c FRAM, lux sensor, GPS...), possibly send a pull request on GitHub, then let us know about it!