Follow:

micro:bit IoT In C - The LED Display

The micro:bit's LED display may only be 5x5 but it is very versatile. If you want to make use of it directly then you are going to have to master some lower level functions.

Mostly the functions provided by the framework are all you need to work with the LED display. They are also fairly self explanatory and easy to use so there is no point in going over them. You can look them up in the documentation and use them in programs without too much trouble. In this chapter we cover the structure of the LED display and some interesting ways of using it in the hope that you might find creative ways to use the display.

Getting Started With C/C++
Anyone who wants to use the BBC micro:bit to its full potential as an IoT device needs to look outside the coding environments provided by its own website. As an mbed device, however, the micro:bit is capable of being programmed in C/C++. Here we look at how to use the mbed online compiler for a simple demo program.

Offline C/C++ Development
We have already discovered how to use the online editor to create a C/C++ program. Now we are going to move to the desktop with an offline approach. This has the advantage that we can use any tools we care to select and no Internet connection is needed.

First Steps With The GPIO
The most basic task when working with the micro:bit is controlling the I/O lines. This isn't difficult if you use the framework provided but there some subtle points to watch out for. This chapter looks a the basics of using the GPIO.

Working Directly With The Hardware - Memory Mapping.
The framework makes working with the GPIO and other devices as easy as it can be but there are many layers of software to go through before you get to the hardware. Writing directly to the hardware can make things up to ten times faster and give you access to things that their framework doesn't. It is also an educational experience to deal with the raw hardware directly.

I2C
The I2C bus is one of the most useful ways of connecting moderately sophisticated sensors and peripherals to the any processor. The only problem is that it can seem like a nightmare confusion of hardware, low level interaction and high level software. There are few general introductions to the subject because at first sight every I2C device is different, but here we present one.

I2C Temperature Measurement
Using I2C devices is fairly easy once you have successfully used one - and hence know what information you need and what to look for in a working system. In this chapter we use the HTU21D temperature and humidity sensor as a case study of I2C in action. It also happens to be a useful sensor.

The SPI Bus
The SPI bus can be something of a problem because it doesn't have a well defined standard that every device conforms to. Even so if you only want to work with one specific device it is usually easy to find a configuration that works - as long as you understand what the possibilities are.

SPI MCP3008/4 AtoD
The SPI bus can be difficult to make work at first but once you know what to look for about how the slave claims to work it gets easier. To demonstrate how its done let's add eight channels of 12 bit AtoD using the MCP3008.

Serial Connections
The serial port is one of the oldest of ways of connecting devices together but it is still very, very useful. The micro:bit has a single serial interface but it can be directed to use any of the GPIO piins as Rx and Tx.

WiFi
The micro:bit has a radio that works in Bluetooth LE and point-to-point ad-hoc mode, but at the moment it lacks WiFi connectivity. The solution is to use the low cost ESP8266 to make the connection via the micro:bit's serial port.

LED Display
The micro:bit's LED display may only be 5x5 but it is very versatile. If you want to make use of it directly then you are going to have to master some lower level functions.

Driving The LEDs

The basic structure of the LED array is fairly simple and obvious if you have ever done anything similar. The LEDs are arranged in a grid of three rows and five columns. Each row has a GPIO line to drive it and each row has a GPIO line that acts as ground or not depending on whether the LED should be on or off.

The arrangement of LEDs and GPIO lines is:

As you can see there are two LEDs missing from the grid. If we had the full set of 3x9 LEDs we would have 27 and a 5x5 array only needs 25.

The LEDs are also not arranged in a neat row column numbering. Instead they are arranged in an order that makes the PCB layout easier:

So to illuminate a given LED i.e. one at position row,column all we have to do is set the row GPIO high and the column GPIO low - this picks out just one LED to be on.

For example to select the center LED 2,3 you would need to set GPIO line p14 high and line p6 low. The problem is that the framework only provides objects for GPIO lines that are brought out to the the edge connector and none of the row lines are and only some of the column lines are..

The solution is to make us of the mbed functions that the framework is built in. The disadvantage of this is that you don't get any of the event handling facilities. There are mbed functions for most of the hardware facilities that we have used and you can use them if you want to. They are slightly faster than the framework functions because in general the framework functions call the mbed functions to get the work done.

Notice that to take control of the GPIO lines that work with the display you either have to not create the uBit object or you have to call the disable method of the display. After this the program simply sets col3 to zero and toggles row2 to flash the LED.

We could equally well have used:

DigitalOut col3(COL3,0);
DigitalOut row2(ROW2);

If you think about the hardware for a moment it should be obvious that we can turn on any LED in a single row by setting its row to on and multiple columns to off.

How then can we create a display where LEDs in different rows are on at the same time?

The answer is that we turn then on an off so fast that the human eye can't see the flashing.

For example to turn the LEDs on in column 3 and rows 1, 2 and 3 you could use:

If you run this program you will see the LEDs on the diagonal flash one after another. Now take out the wait function calls - you will see all three LEDs on the diagonal on apparently at the same time.

This is what the framework display object does for you automatically. It scans the three rows turning on and off LEDs in that row to create a complete display. It is another job performed by the framework's event handling system.

If you want to do this sort of job at a reasonable speed you need to set and unset all of the LEDs in a single row in one operation as explained in the chapter on fast memory mapped GPIO. The mbed library has functions that you can use to do this or you can write your own.

Grey Scale

One of the features of the framework's support for the LED display that isn't so obvious is that you can use it as a grey scale display. The reason it isn't so obvious is that there isn't a setValue type function for a single LED. It doesn't have any functions that let you work with a single LED at all.

However the display object uses a buffer which is a MicroBitImage object. The basic idea is that the render function displays what ever is in the buffer. You can create MicroBitImage objects and print them to the display or you can work directly with the buffer MicroBitImage object to display "live" graphics.

The key method is:

int setPixelValue( int16_t x,int16_t y,uint8_t value)

and the value can be anything from 0 to 255. The brightness is created by simply turning the LED on and off in the correct ration as in PWM. However PWM isn't used in the display it is a simple consequence of the repeated rendering of the display and the percentage of time a pixel is set to on.

Notice that you have to set the greyscale mode because this is more complex and hence not the default.

You can explore the possibilities of using MicroBitImage object to perform animation and other graphical techniques.

However the real problem is that no matter how clever your software you only have a 5x5 display.

Using Aliasing To Increase Resolution

As an example of how you can use the grey level resolution of the display to increase its effective spatial resolution let's implement a traditional BBC Micro game - Commando Jump. This is a very simple game where a figure's height above the baseline is controlled by how fast the user clicks a button. It is a simple game but only showing the commando in five positions makes it a little crude.

As an alternative to simply moving the commando by one LED for every ten button clicks we can move the brightness from one to another gradually. You can think of this as locating the commando in the gaps between the LEDs if you want but it is also the standard anti-aliasing technique from higher resolution graphics.

The commando is at x,y and p is used to indicate how close to being at x+vx and y+vy he is. For example suppose p is 0 then the first LED is set to 10*25 i.e. 250 and the second to 0. If p is 3 then the first is set to 7*25 and the second to 3*25. Finally is p is 10 the first is set to 0 and the second to 10*25. As p varies from 0 to 10 the position of the brightness moves from the first to the second LED.

We also need something to record how many times the button has been clicked. This can be done using an event handler that counts clicks using a global variable. There is no doubt that this would be better implemented as an object using C++ with methods such as getValue and reset and so on but for simplicity we will use C.

If you try it out you will discover that the use of grey scale to increase the resolution works well but it works even better if you scale the LED brightness using a power law as given in the chapter on PWM.

I don't think that the 5x5 display is going to be hosting an implementation of Doom any time soon but ... who knows.

Getting Started With C/C++
Anyone who wants to use the BBC micro:bit to its full potential as an IoT device needs to look outside the coding environments provided by its own website. As an mbed device, however, the micro:bit is capable of being programmed in C/C++. Here we look at how to use the mbed online compiler for a simple demo program.

Offline C/C++ Development
We have already discovered how to use the online editor to create a C/C++ program. Now we are going to move to the desktop with an offline approach. This has the advantage that we can use any tools we care to select and no Internet connection is needed.

First Steps With The GPIO
The most basic task when working with the micro:bit is controlling the I/O lines. This isn't difficult if you use the framework provided but there some subtle points to watch out for. This chapter looks a the basics of using the GPIO.

Working Directly With The Hardware - Memory Mapping.
The framework makes working with the GPIO and other devices as easy as it can be but there are many layers of software to go through before you get to the hardware. Writing directly to the hardware can make things up to ten times faster and give you access to things that their framework doesn't. It is also an educational experience to deal with the raw hardware directly.

I2C
The I2C bus is one of the most useful ways of connecting moderately sophisticated sensors and peripherals to the any processor. The only problem is that it can seem like a nightmare confusion of hardware, low level interaction and high level software. There are few general introductions to the subject because at first sight every I2C device is different, but here we present one.

I2C Temperature Measurement
Using I2C devices is fairly easy once you have successfully used one - and hence know what information you need and what to look for in a working system. In this chapter we use the HTU21D temperature and humidity sensor as a case study of I2C in action. It also happens to be a useful sensor.

The SPI Bus
The SPI bus can be something of a problem because it doesn't have a well defined standard that every device conforms to. Even so if you only want to work with one specific device it is usually easy to find a configuration that works - as long as you understand what the possibilities are.

SPI MCP3008/4 AtoD
The SPI bus can be difficult to make work at first but once you know what to look for about how the slave claims to work it gets easier. To demonstrate how its done let's add eight channels of 12 bit AtoD using the MCP3008.

Serial Connections
The serial port is one of the oldest of ways of connecting devices together but it is still very, very useful. The micro:bit has a single serial interface but it can be directed to use any of the GPIO piins as Rx and Tx.

WiFi
The micro:bit has a radio that works in Bluetooth LE and point-to-point ad-hoc mode, but at the moment it lacks WiFi connectivity. The solution is to use the low cost ESP8266 to make the connection via the micro:bit's serial port.

LED Display
The micro:bit's LED display may only be 5x5 but it is very versatile. If you want to make use of it directly then you are going to have to master some lower level functions.