micro:bit

Write a BBC micro:bit program in Raku, with the names you know from MicroPython. Watch it run on a simulated micro:bit, then build it into the .hex file you copy onto the board. You need no board to start.

Without a boardThe tilt, as an arrow: what the simulated micro:bit shows.
PicturesMicroPython's 64 built-in pictures, and your own, made while building.
Buttons and sensorsButtons, the touch logo, gestures, and pressing them with no board.
Onto a boardFrom the C++ rakupp writes to the .hex on the board, step by step.
What a program can useNative types, Raku's arithmetic, and every name of use MicroBit.
Under RakudoWhat other Raku implementations say about use MicroBit.

Without a board #

use MicroBit;

loop {
    my int16 $acc = accelerometer.x;
    say $acc;
    display.show: $acc > 0 ?? Image.ARROW-E !! Image.ARROW-W;
    pause 100;
}

This is the first program of the accelerometer chapter at python-online.ch, in Raku. The names are MicroPython's, spelt the Raku way: accelerometer.get_x() is accelerometer.x, Image.ARROW_E is Image.ARROW-E, and sleep(100) is pause 100.

rakupp tilt.raku runs it on the simulated micro:bit in real time. With RAKUPP_MICROBIT_STOP the clock is virtual, and with RAKUPP_MICROBIT_ACCEL you tilt the board, here left and then right:

$ RAKUPP_MICROBIT_STOP=600 RAKUPP_MICROBIT_ACCEL="0:-200,0,-1000;300:250,0,-950" rakupp tilt.raku
-200
[0 ms] display 00900:09000:99999:09000:00900
-200
-200
250
[300 ms] display 00900:00090:99999:00090:00900
250
250
[600 ms] stop

stdout is the serial port, and stderr is the board: one line each time the LEDs change, written as MicroPython writes a picture, five rows of five brightnesses from 0 to 9.

Pictures #

Image has MicroPython's 64 pictures, by their names spelt as Raku: Image.HEART, Image.ARROW-NE, Image.MUSIC-QUAVER. image makes your own, from five rows of brightnesses or from # and .:

use MicroBit;

constant GLOW = image q:to/END/;
    03030
    39993
    39993
    03930
    00300
    END

loop {
    display.show(Image.HEART);
    pause 300;
    display.show(GLOW);
    pause 500;
}
Image.HEART: 09090:99999:99999:09990:00900.

image runs while building, on your computer, so the board gets 25 bytes in flash. display.scroll and display.show also take text put together as the board runs, such as "T: {temperature}C", and display.set-pixel lights one LED.

Buttons and sensors #

my int $count = 0;
display.show($count);
loop {
    my int $was = $count;
    $count += button-a.get-presses;
    if button-b.was-pressed && $count > 0 { $count-- }
    if pin-logo.is-touched { $count = 0 }
    display.show($count) if $count != $was;
    pause 50;
}

A counter: button A counts up, B counts down, and touching the logo starts again from 0. On the simulated board the buttons are pressed by RAKUPP_MICROBIT_BUTTONS="A@200,A@600,B@1500,logo@2500", and the tilt, gestures, compass heading, temperature, light level and pins come from the environment too, so a run gives the same transcript every time. accelerometer.was-gesture('shake') and randint(1, 6) make a die.

Onto a board #

--target=microbit writes the program as one C++ file for the board's own runtime, CODAL, the one MakeCode runs on. CODAL's build project turns it into MICROBIT.hex, and a micro:bit plugged in over USB is a drive called MICROBIT: copying the file onto it is all flashing takes. Once, an ARM compiler and the build project:

git clone https://github.com/lancaster-university/microbit-v2-samples ~/microbit-v2-samples
cd ~/microbit-v2-samples && python3 build.py

Then, for each program:

rakupp --target=microbit tilt.raku -o ~/microbit-v2-samples/source/main.cpp
cd ~/microbit-v2-samples && python3 build.py
cp MICROBIT.hex /Volumes/MICROBIT/

The build needs arm-none-eabi-gcc on the PATH before its first run; on a Mac with the Arduino IDE and its Uno R4 core, one is installed already. The guide's step-by-step section has every system, and what to do when a step goes wrong.

What a program can use #

RakuMicroPythonWhat it does
display.show, .scroll, .cleardisplay.show() …a picture, a number or text on the LEDs
display.set-pixel(x, y, b)display.set_pixel()one LED, brightness 0 to 9
button-a.is-pressed, .was-pressed, .get-pressesbutton_a.is_pressed() …the buttons
pin-logo.is-touchedpin_logo.is_touched()the touch logo
accelerometer.x, .was-gesture('shake')accelerometer.get_x() …the tilt, and gestures
compass.heading, temperaturecompass.heading(), temperature()the compass, the temperature
pin0.read-analog … pin20pin0.read_analog() …the edge connector
pause, running-time, randintsleep(), running_time(), random.randint()time and chance

The rest is the board subset shared with the Arduino: native types such as int16 and uint8, shaped arrays, Raku's arithmetic, if, loop, for, and subs with native signatures. Anything else stops the build, with the line it is on:

$ rakupp --target=microbit -e 'use MicroBit; my $x = 5; say $x'
rakupp --target=microbit: -e, line 1: the untyped variable $x — give it a native type, as in `my int16 $x`

The micro:bit FAQ answers what a MicroPython or MakeCode user asks first: what changes from MicroPython, pause and Raku's own sleep, showing a number, making a picture and animating it, and why a button press went missing.

Under Rakudo #

use MicroBit is built into rakupp; rakupp install skips the name and says so. Other Raku implementations can install a stub module of the same name, which stops the program at the use line and names the command to run it with:

zef install MicroBit
$ rakudo hello.raku
===SORRY!=== Error while compiling hello.raku
This program needs Raku++: `use MicroBit` is built into rakupp
(https://github.com/ash/rakupp), which runs it on a simulated micro:bit
and compiles it for a real one:
    rakupp hello.raku
    rakupp --target=microbit hello.raku