2020-02-19 09:29:58 +08:00
2020-02-18 23:14:08 +08:00
2020-02-19 09:29:58 +08:00

micro:bit MicroPython Cookbook (Updating)

A note for some Python tricks and experiments on BBC micro:bit.

Easer Eggs

Enter the following codes into REPL:

import this
import love
import antigravity

Also

this.authors()
love.badaboom()

Some Lesser Known Facts

Since Python and MicroPython are interpreted languages, they eat a lot of memory. Also, the hex file generated by micro:bit Python editors are consisted of 2 parts: the MicroPython firmware (up to 248 KB) and user's script (up to only 8 KB). See Firmware Hex File. Which means it's not possible to build big projects with micro:bit's MicroPython.

Also, how micro:bit get its own version of MicroPython anyway: The Story of MicroPython on the BBC micro:bit by Nicholas H. Tollervey, who also created the Mu editor, which is easier to use than the official online editor.

Fill LED Display

Light up every LEDs. Use fillScreen() as default.

from microbit import display, Image, sleep

def fillScreen(b = 9):
    f = (str(b) * 5 + ":") * 5
    display.show(Image(f[:len(f)-1]))


while True:
    
    for i in range(9):
        fillScreen(i)
        sleep(50)
    
    for i in reversed(range(9)):
        fillScreen(i)
        sleep(50)

A More Convenient Pin Class

Use namedtuple to "rename" pin methods as set() and get().

from microbit import pin0, sleep
from ucollections import namedtuple

Pin = namedtuple('Pin', ['set', 'get'])
setPin = lambda p: Pin(p.write_digital, p.read_digital)


led = setPin(pin0)

while True:
    led.set(1)
    sleep(500)
    led.set(0)
    sleep(500)

LED Bar Graph

from microbit import display, sleep

def plotBarGraph(value, maxValue, brightness = 9):
    bar = value / maxValue
    valueArray = ((0.96, 0.88, 0.84, 0.92, 1.00), 
                  (0.76, 0.68, 0.64, 0.72, 0.80),
                  (0.56, 0.48, 0.44, 0.52, 0.60), 
                  (0.36, 0.28, 0.24, 0.32, 0.40), 
                  (0.16, 0.08, 0.04, 0.12, 0.20))
    for y in range(5):
        for x in range(5):
            if bar >= valueArray[y][x]:
                display.set_pixel(x, y, brightness)
            else:
                display.set_pixel(x, y, 0)


while True:
    lightLevel = display.read_light_level()
    plotBarGraph(lightLevel, 255, 9) # or plotBarGraph(lightLevel, 255)
    sleep(50)

Since read_light_level() uses LEDs themselves as light sensors (see this video), a short delay is added, but the LED screen would flicker a bit.

Servo Control

from microbit import pin0, sleep

def servoWrite(pin, degree):
    pin.set_analog_period(20)
    pin.write_analog(round((degree * 92 / 180 + 30), 0))


servoPin = pin0

while True:
    servoWrite(servoPin, 0)
    sleep(1000)
    servoWrite(servoPin, 180)
    sleep(1000)

Do not use servos and buzzers at the same time. They require different PWM frequencies and would most microcontrollers can only set one frequency accross all pins at a time. Also micro

Value Mapping

Translate a value in a range to its corresponding value in anoher range. Borrowed from here.

def translate(value, leftMin, leftMax, rightMin, rightMax):
    leftSpan = leftMax - leftMin
    rightSpan = rightMax - rightMin
    valueScaled = float(value - leftMin) / float(leftSpan)
    return rightMin + (valueScaled * rightSpan)

Get Pitch and Roll Degrees

These function cannot tell if the board is facing up or down. Probably need to use accelerometer.get_z() for that.

from microbit import accelerometer, sleep
import math

def rotationPitch():
    return math.atan2(
            accelerometer.get_y(), 
            math.sqrt(accelerometer.get_x() ** 2 + accelerometer.get_z() ** 2)
            ) * (180 / math.pi)

def rotationRoll():
    return math.atan2(
            accelerometer.get_x(), 
            math.sqrt(accelerometer.get_y() ** 2 + accelerometer.get_z() ** 2)
            ) * (180 / math.pi)


while True:
    print("Pitch:", rotationPitch(), " / roll:", rotationRoll())
    sleep(100)

NeoPixel Rainbow/Rotation

This code needs at least 3 LEDs in the NeoPixel chain.

from microbit import pin0, sleep
from neopixel import NeoPixel
from micropython import const

led_num = const(12)
led_maxlevel = const(64) # max 255
led_pin = pin0

np = NeoPixel(led_pin, led_num)

def showRainbow():
    change_amount = int(led_maxlevel / (led_num / 3))
    index = [0, int(led_num / 3), int(led_num / 3 * 2)]
    for i in range(led_num):
        color = [0, 0, 0]
        for j in range(3):
            if abs(i - index[j]) <= int(led_num / 3):
                color[j] = led_maxlevel - abs(i - index[j]) * change_amount
                if color[j] < 0:
                    color[j]
        if i >= int(led_num / 3 * 2):
            color[0] = led_maxlevel - (led_num - i) * change_amount
            if color[0] < 0:
                color[0] = 0
        np[i] = (color[0], color[1], color[2])
    np.show()

def rotate():
    tmp = np[led_num - 1]
    for i in reversed(range(1, led_num)): # clockwise
        np[i] = np[i - 1]
    np[0] = tmp
    np.show()


showRainbow()

while True:
    rotate()
    sleep(50)

Description
Tricks and experiments using MicroPython on BBC micro:bit
Readme MIT 1.9 MiB
Languages
Python 100%