Arduino

Write the program in Raku. Watch it run on a simulated board, then get a sketch that the Arduino IDE builds and uploads like any other. You need no board to start.

Without a boardBlink, and what the simulated board shows: the serial port, and every pin as it changes.
Onto a boardThe sketch, the Arduino IDE or arduino-cli, and the boards it builds for.
Raku while buildingTables computed in full Raku on your computer; the board gets only the numbers.
The LED matrixPictures on the Uno R4 WiFi's 12×8 matrix.
What a board program can useNative types, Raku's arithmetic, the Arduino core's functions.
Under RakudoWhat other Raku implementations say about use Arduino.

Without a board #

use Arduino;

pinMode(LED_BUILTIN, OUTPUT);
say "blink";

loop {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(500);
    digitalWrite(LED_BUILTIN, LOW);
    delay(500);
}

An Arduino sketch is two functions, and the program maps onto them by its shape: the code before the top-level loop { } is setup(), and one pass of the loop is one call of loop(). use Arduino gives you the core's own names, so the program reads like Arduino code.

rakupp blink.raku runs it on the simulated board in real time, until you press Ctrl-C. With RAKUPP_ARDUINO_STOP the clock is virtual, and that many milliseconds of board time pass at once:

$ RAKUPP_ARDUINO_STOP=2200 rakupp blink.raku
blink
[0 ms] pin 13 mode OUTPUT
[0 ms] pin 13 HIGH
[500 ms] pin 13 LOW
[1000 ms] pin 13 HIGH
[1500 ms] pin 13 LOW
[2000 ms] pin 13 HIGH
[2200 ms] stop

stdout is the serial port, and stderr is the board: one line for each pin change. Inputs read what RAKUPP_ARDUINO_PINS says, as in RAKUPP_ARDUINO_PINS="2=0,A0=512", so a run with a button held down gives the same transcript every time.

Onto a board #

The Arduino IDE wants each sketch in a folder of its own name:

mkdir blink
rakupp --target=arduino blink.raku -o blink/blink.ino

Open blink/blink.ino in the Arduino IDE, choose your board and port, and press Upload. With arduino-cli:

arduino-cli compile --fqbn arduino:avr:uno blink
arduino-cli upload  --fqbn arduino:avr:uno -p /dev/cu.usbmodem1101 blink
BoardCore, from the Boards ManagerFQBN
Arduino UnoArduino AVR Boardsarduino:avr:uno
Arduino Uno R4 WiFiArduino UNO R4 Boardsarduino:renesas_uno:unor4wifi
Arduino DueArduino SAM Boardsarduino:sam:arduino_due_x

The sketch is plain C++11 with the core's own headers, so it builds for each of these with its own compiler. It carries only the helpers the program calls; blink's sketch is the includes, setup() and loop().

With rakupp 5.6.2, the IDE stops with 'T' does not name a type: it adds a declaration for each function of a .ino file, and gets the helper templates of that version's sketches wrong. The next release writes sketches it accepts. Until then, put the sketch in a .cpp file beside an empty .ino, which the IDE compiles as it is: rakupp --target=arduino blink.raku -o blink/raku.cpp, then touch blink/blink.ino.

Raku while building #

constant LED   = 9;   # a PWM pin
constant @wave = (^32).map: { (127.5 + 127.5 * sin(2 * pi * $_ / 32)).Int };

Every constant is computed while the program is built, in full Raku, on your computer: sin, pi, .map, a file read, a grammar, a module. The board gets only the result, here 32 bytes of sine wave in flash:

static const uint8_t t_wave[32] RK_FLASH = {
    127, 152, 176, 198, 217, 233, 245, 252, 255, 252, 245, 233,
    217, 198, 176, 152, 127, 102, 78, 56, 37, 21, 9, 2,
    0, 2, 9, 21, 37, 56, 78, 102
};

The LED matrix #

On the Uno R4 WiFi, use Arduino::LEDMatrix draws on its 12×8 matrix. frame packs a picture into the three 32-bit words the matrix library takes, while building, so the board gets twelve bytes:

use Arduino;
use Arduino::LEDMatrix;

constant @RAKU = frame q:to/END/;
    ####....###.
    #...#..#...#
    ####...#####
    #...#..#...#
    ............
    #..#...#...#
    ###....#...#
    #..#....###.
    END

LEDMatrix.begin;
LEDMatrix.show(@RAKU);
RA over KU, as on the Learn Raku app's icon.

The simulated board draws each new picture on stderr with # and .. LEDMatrix.show also takes a picture the board computes as it runs, and LEDMatrix.clear darkens the matrix.

What a board program can use #

Anything else stops the build, with the line it is on:

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

Hashes, strings built at run time, classes and regexes are among them, and most are planned. A plain int is 64 bits, as in Raku; int16 or uint8 is what a small board wants. Choose a type the value fits: my int8 $d = 700 stores −68.

Under Rakudo #

use Arduino and use Arduino::LEDMatrix are built into rakupp; rakupp install skips both names and says so. Other Raku implementations can install stub modules of the same names, which stop the program at the use line and name the command to run it with:

zef install Arduino Arduino::LEDMatrix
$ rakudo blink.raku
===SORRY!=== Error while compiling blink.raku
This program needs Raku++: `use Arduino` is built into rakupp
(https://github.com/ash/rakupp), which runs it against a simulated board
and compiles it for a real one:
    rakupp blink.raku
    rakupp --target=arduino blink.raku