The code editor and compiling
One project per board, a real clang running in the tab, and diagnostics you can click.
One project per board
The right-hand pane is a workstation, not a text box. Every board in the diagram is programmed separately and has files of its own: a sketch, plus any headers and extra sources you add, exactly as a real project does. A board picker at the top chooses which board you are looking at; a file strip under it has tabs, and buttons to add, rename and delete a file.
Files travel with the diagram. They are saved next to it against the board's id, exported and imported with it, and deleted with the board.
A diagram with no board at all still has one sketch, so you can write code
before you have decided what will run it. File names may hold letters, digits,
_, . and -, and anything ending .ino, .c, .cpp, .cc, .h, .hpp
or .hh gets C++ highlighting.
What happens when you press Run
Each board is asked one question: does this need building? There are three answers.
- Run the image as it is. An uploaded ELF was not built from these files, and an untouched built-in example is already built.
- Reuse the last build. The decision is a hash of every file name and every byte in it, so a keystroke and an undo leave you exactly where you were.
- Build it. Compile, then run the result.
The build itself is a real clang and a real lld, compiled to WebAssembly and running in a Web Worker so a four second first build never costs the canvas a frame. Nothing is uploaded and there is no build server, no queue and no build minutes.
The first build, and every one after it
The toolchain is about seventy megabytes of clang, streamed once from our own storage and then kept in the browser's cache. The first build in a fresh browser takes a few seconds; a return visit is about a second and a half, and an edit and run after that is roughly two tenths of a second.
Alongside it comes the runtime: our own freestanding C and C++ for that board family, with the same headers, start-up code, linker script and flags the repository's own build script uses. That is why a sketch that includes one of the shared drivers compiles on any board that has them.
The Arduino language, on every board
The runtime is Mokxi's own, but it speaks the Arduino language reference: a sketch copied from a tutorial uses the same calls here as on a real board.
- Floating point.
floatanddoublearithmetic work everywhere, from a software floating-point library in the runtime, as on a real Uno, where the chip has no floating-point hardware either.doubleis 32 bits on the AVR boards (Uno, Nano, Mega, Leonardo, ATtiny85), exactly as in the Arduino AVR core, and 64 bits on the rest.Serial.print(x, 3)prints three places. - The math library.
sqrt,pow,sin,cos,tan,atan2,log,exp,floor,roundand the rest ofmath.h, plusPI,radians(),degrees(),map()andconstrain(). Include<math.h>or not; either works. - String. Arduino's
Stringclass:+and+=,indexOf,substring,toInt,toFloat,trim,replaceand the rest. Its text lives on the heap, which on an Uno is whatever of its 2 KB the sketch leaves free, so building long Strings in a loop runs out here as it does on the bench. - Reading Serial.
parseInt,parseFloat,readString,readStringUntil,readBytes,findandsetTimeout, and aserialEvent()function is called betweenloop()s when input arrives. - Timing a pulse.
pulseInandpulseInLongreturn the length of a pulse in microseconds, 0 on a timeout, which is how an HC-SR04 is read.shiftInandshiftOutclock a byte in or out. - Sound.
tone(pin, frequency)andtone(pin, frequency, duration)play a square wave from a timer interrupt without stopping the sketch, andnoTone(pin)stops it. On an Uno it takes timer 2, as the Arduino core does, so PWM on pins 3 and 11 pauses while a note plays. On the XIAO and the Uno R4, a note plays on the PWM pins.#include "pitches.h"gives theNOTE_names. - The C library.
sprintf,snprintf,atoi,atof,strtol,strcpy,strcmp,strtok,dtostrf,itoa,mallocand friends. As on a real Uno,%finsprintfprints?on the AVR boards; usedtostrfthere. - Characters.
isDigit,isAlpha,isSpace,isUpperCaseand the rest.
The ATtiny85 has 8 KB of flash and its calls only reach 4 KB, so a sketch that pulls in the math library or much floating point is often too big for it, here as on the bench.
Arduino libraries that compile as they are
Paste a tutorial and its includes work: the runtime carries the stock libraries people use most, under their usual names. Each is Mokxi's own header, written on the drivers for the parts in the bin; none of it is the upstream library's code, and each keeps the calls tutorials use.
| Header | What it drives | Boards |
|---|---|---|
Servo.h, ESP32Servo.h |
a hobby servo on any pin | every board that compiles |
Wire.h |
I2C as a master, on the board's own I2C pins or any two | every board that compiles |
SPI.h |
SPI on the board's own SPI pins | every board that compiles |
EEPROM.h |
read, write, update, get, put, EEPROM[i] |
every board that compiles |
LiquidCrystal_I2C.h |
the 16x2 LCD behind its I2C backpack | every board that compiles |
Adafruit_GFX.h, Adafruit_SSD1306.h |
the 128x64 I2C OLED | all but the ATtiny85 |
Adafruit_NeoPixel.h |
WS2812 strips and panels | ESP32-C3 and ESP32-C6 |
DHT.h |
the DHT11 and DHT22 | every board that compiles |
OneWire.h, DallasTemperature.h |
DS18B20 thermometers, any number on one pin | all but the ATtiny85 |
Adafruit_BME280.h, Adafruit_BMP280.h, SparkFunBME280.h |
the Bosch pressure sensors | all but the ATtiny85 |
RTClib.h |
the DS3231 and DS1307 clocks, DateTime and TimeSpan |
all but the ATtiny85 |
Adafruit_INA219.h |
the INA219 current monitor | all but the ATtiny85 |
Adafruit_ADS1X15.h |
the ADS1115 sixteen-bit ADC | all but the ATtiny85 |
Adafruit_MCP23X17.h |
the MCP23017 port expander | all but the ATtiny85 |
Where they differ from the upstream libraries, which each part's help page spells out:
- Servo sends one pulse per
write()rather than pulsing from a timer, and its default window is the part's 1000 to 2000 microseconds. - EEPROM is the chip's own EEPROM on the Uno, Nano, Mega, Leonardo and ATtiny85, and 4 KB of RAM on every other board, whose models have nothing writable that survives a reset. A fresh Run starts erased either way.
- The OLED's font is Mokxi's 5x7: capitals, digits and punctuation, and lower case prints as capitals.
- DHT hands back floats built from the sensor's whole tenths. They print,
isnanandcomputeHeatIndexwork, and so does any arithmetic of your own on them. - Wire is a master only, and bit-banged, like every bus here.
- The sensor libraries hand back floats the same way as DHT, built from
the chips' own counts.
DEVICE_DISCONNECTED_Ccompares with a reading as the tutorials do, and the pressure tutorials'readPressure() / 100.0Fworks as written;readPressureHPa()is there too.
Each board's help article says which pins Wire.begin() uses on it. Any other
library stops at clang's file not found, and the Build tab names the Mokxi
header that does the same job, or says there is none yet.
The Build tab
Under the file strip. It stays out of the way until there is something to say,
and then shows three things: the steps with their timings, so a slow first build
reads as progress rather than a hang; the compiler's diagnostics as lines you
can click to land on the file, line and column it is complaining about; and one
plain sentence at the end, such as Built esp1.elf, 1.5 KB, 0.21 s.
The four boards
Every board family compiles in the browser on one toolchain: the ESP32-C3
(riscv32 -march=rv32imc), the Arduino Uno (avr -mmcu=atmega328p), the Pico
(thumbv6m, Cortex-M0+) and the STM32F411 (thumbv7em, Cortex-M4, soft float).
The full detail, down to the command list and the cache keys, is in compiling in the browser.
If a build fails, the sketch does not compile walks through what the Build tab is telling you.