Sunday 14 June 2020

BBC Micro:Bit Menu system (with persistent choice)

The BBC Micro:Bit is a simple microcontroller with a 5 x 5 matrix of LEDs, two buttons, 3D magnetic and acceleration sensors and a CPU temperature sensor.
The two buttons can make complicated interfaces rather difficult, however it is possible to build one.
One aadditional feature of this menu system is that your choices are persistent. If you select menu item, power off the Micro:Bit then subsequently power it back one, it will remember the choice (subject to it not being reflashed of course).

Code

This was written in Micropython using the Mu editor.
from microbit import *
import os
import utime
menuitem = 0
if 'choice.opt' in os.listdir():
    with open('choice.opt') as choice:
        menuitem = int(choice.read())
display.scroll("Menu item" + str(menuitem))
start = utime.ticks_ms()+6000
interval = 2000
while True:
    now = utime.ticks_ms()
    if start > now or now - start > interval:
        if menuitem == 0:
            temp = temperature()
            interval = 2000
            display.scroll(str(temp) + 'C', delay=100, wait=False)
        elif menuitem == 1:
            temp = temperature()
            interval = 2000
            display.scroll(str(temp + 273.15) + 'K', delay=100, wait=False)
        elif menuitem == 2:
            level = display.read_light_level()
            interval = 2000
            display.scroll(str(level) + ' light', delay=100, wait=False)
        elif menuitem == 3:
            level = compass.get_field_strength()
            interval = 6000
            display.scroll(str(level) + ' nTesla', delay=100, wait=False)
        elif menuitem == 4:
            display.scroll("Menu test")
        start = now 
    if button_a.is_pressed():
        display.scroll("Menu", delay = 100)
        sleep(50)
        while not button_a.is_pressed():
            display.set_pixel(4,menuitem,5)
            if button_b.is_pressed():
                display.set_pixel(4,menuitem,0)
                menuitem = menuitem + 1
                if menuitem > 4:
                    menuitem = 0
                with open('choice.opt','w') as choice:
                    choice.write(str(menuitem))
                display.scroll("Menu item" + str(menuitem), delay = 100)
            sleep(100)
            display.set_pixel(4,menuitem,5)
            sleep(100) 
    sleep(400)
The persistent choice is handled by this code:
menuitem = 0
if 'choice.opt' in os.listdir():
    with open('choice.opt') as choice:
        menuitem = int(choice.read())
The menu item is given a default value (0).
The file 'choice.opt' is checked if it exists in the directory list, if it is, then the value of the menu item is read from the file and assigned to the menuitem variable. When a subsequent decision is made to change the menuitem, this value is written out to the file, making it available the next time the Micro:Bit is switched on.

The main loop is entered after the start variable is set in advance of the current tick count and the display interval is set (strictly speaking the interval should be dependent on the menu choice but it only affects the first cycle).

Each loop, if the difference between the ticks now and the (loop) start ticks is greater than the interval, then the menuitem is used to choose what to do.
In this example it is used to choose which sensor is read and the results displayed.
Menu choices are:

  1. Temperature in degrees Celsius.
  2. Temperature in Kelvin
  3. Light level (based on the light falling on the LED matrix)
  4. Magnetic field strength in nanoTesla (using the compass module)
  5. A message.
The first three keep the interval at two seconds, but the magnetic field strength is a longer piece of text, so that is stretched to six seconds by setting the interval.
The Start ticks value is set to the Now value.

The next part of the code checks for the A button (left side) being pressed.
If so, it then loops until the button is pressed again.
Inside that loop, pressing the B (right hand) button increments the menuitem value, writes it to the file and shows a pixel on the right hand column indication which option is currently chosen.
Pressing button A exits the loop and recommences the outer infinite loop.

Disadvantages

This does mean that during normal operation, button A is not available. This might not be an issue but is something to bear in mind.

References