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 board | Blink, and what the simulated board shows: the serial port, and every pin as it changes. |
| Onto a board | The sketch, the Arduino IDE or arduino-cli, and the boards it builds for. |
| Raku while building | Tables computed in full Raku on your computer; the board gets only the numbers. |
| The LED matrix | Pictures on the Uno R4 WiFi's 12×8 matrix. |
| What a board program can use | Native types, Raku's arithmetic, the Arduino core's functions. |
| Under Rakudo | What 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.
Install rakupp The walkthrough, with every program →
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
| Board | Core, from the Boards Manager | FQBN |
|---|---|---|
| Arduino Uno | Arduino AVR Boards | arduino:avr:uno |
| Arduino Uno R4 WiFi | Arduino UNO R4 Boards | arduino:renesas_uno:unor4wifi |
| Arduino Due | Arduino SAM Boards | arduino: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.inofile, 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.cppfile beside an empty.ino, which the IDE compiles as it is:rakupp --target=arduino blink.raku -o blink/raku.cpp, thentouch 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);
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 #
- Native types:
int8…int64,uint8…uint64,num,num32,Bool, and shaped arrays of them, such asmy uint8 @buf[16], with every subscript checked. - Raku's arithmetic: integers computed in 64 bits,
divand%rounding down, and a value cut to its type's width when it is stored. - Control flow:
if,unless,while,until,repeat,loop,for ^N,for @table,next,last. - Subs with native signatures:
sub f(int16 $x --> int16) { … }. - The core's functions:
pinMode,digitalWrite,digitalRead,analogRead,analogWrite,delay,millis,micros,Serial, andsay,printandnoteof literals, integers and Bools.
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