Velxio is a fully local, open-source Arduino emulator that runs entirely in your browser.
Write Arduino C++ code, compile it with a real arduino-cli backend, and simulate it using
true AVR8 / RP2040 CPU emulation — with 48+ interactive electronic components, all without installing
any software on your machine.
| Board | CPU | Emulator |
|---|---|---|
| Arduino Uno | ATmega328p @ 16 MHz | avr8js |
| Arduino Nano | ATmega328p @ 16 MHz | avr8js |
| Arduino Mega | ATmega2560 @ 16 MHz | avr8js |
| Raspberry Pi Pico | RP2040 @ 133 MHz | rp2040js |
Follow these steps to simulate your first Arduino sketch.
No installation needed — go to{' '} https://velxio.dev{' '} and start coding immediately.
Run a single Docker command to start a fully local instance:
{`docker run -d \\
--name velxio \\
-p 3080:80 \\
-v $(pwd)/data:/app/data \\
ghcr.io/davidmonterocrespo24/velxio:master`}
Then open http://localhost:3080 in your browser.
Prerequisites: Node.js 18+, Python 3.12+, arduino-cli
{`git clone https://github.com/davidmonterocrespo24/velxio.git
cd velxio`}
{`cd backend
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8001`}
{`cd frontend
npm install
npm run dev`}
Open http://localhost:5173.
{`arduino-cli core update-index
arduino-cli core install arduino:avr
# For Raspberry Pi Pico support:
arduino-cli config add board_manager.additional_urls \\
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
arduino-cli core install rp2040:rp2040`}
{`void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500);
}`}
arduino-cli and returns a .hex file.| Problem | Solution |
|---|---|
arduino-cli: command not found |
Install arduino-cli and add it to your PATH. |
| LED doesn't blink | Check the browser console for port listener errors; verify pin assignment in the component property dialog. |
| Serial Monitor is empty | Ensure Serial.begin() is called inside setup() before any Serial.print(). |
| Compilation errors | Check the compilation console at the bottom of the editor for full arduino-cli output. |
Velxio uses real CPU emulation rather than a simplified model. This document describes how each layer of the simulation works.
{`User Code (Monaco Editor)
│
▼
Zustand Store (useEditorStore)
│
▼
FastAPI Backend ──► arduino-cli ──► .hex / .uf2 file
│
▼
AVRSimulator / RP2040Simulator
│ loadHex()
▼
CPU execution loop (~60 FPS via requestAnimationFrame)
│
▼
Port listeners (PORTB / PORTC / PORTD)
│
▼
PinManager ──► Component state ──► React re-renders`}
The AVR backend uses avr8js, which implements a complete ATmega328p / ATmega2560 processor.
Each animation frame executes approximately 267,000 CPU cycles (16 MHz ÷ 60 FPS):
{`avrInstruction(cpu); // decode and execute one AVR instruction
cpu.tick(); // advance peripheral timers and counters`}
| Peripheral | Details |
|---|---|
| GPIO | PORTB (pins 8–13), PORTC (A0–A5), PORTD (pins 0–7) |
| Timer0 / Timer1 / Timer2 | millis(), delay(), PWM via analogWrite() |
| USART | Full transmit and receive — powers the Serial Monitor |
| ADC | 10-bit, 5 V reference on pins A0–A5 |
| SPI | Hardware SPI (enables ILI9341, SD card, etc.) |
| I2C (TWI) | Hardware I2C with virtual device bus |
| Arduino Pin | AVR Port | Bit |
|---|---|---|
| 0–7 | PORTD | 0–7 |
| 8–13 | PORTB | 0–5 |
| A0–A5 | PORTC | 0–5 |
The RP2040 backend uses rp2040js.
Arduino compilation produces Intel HEX format. The parser in hexParser.ts:
:Uint8Array of program bytesAVRSimulator converts this to a Uint16Array (16-bit words, little-endian)| File | Purpose |
|---|---|
frontend/src/simulation/AVRSimulator.ts | AVR8 CPU emulator wrapper |
frontend/src/simulation/PinManager.ts | Maps Arduino pins to UI components |
frontend/src/utils/hexParser.ts | Intel HEX parser |
frontend/src/components/simulator/SimulatorCanvas.tsx | Canvas rendering |
backend/app/services/arduino_cli.py | arduino-cli wrapper |
backend/app/api/routes/compile.py | Compilation API endpoint |
Velxio ships with 48+ interactive electronic components powered by{' '} wokwi-elements. All components can be placed on the simulation canvas, connected with wires, and interact with your Arduino sketch in real time.
| Color | Signal Type |
|---|---|
| Red | VCC (power) |
| Black | GND (ground) |
| Blue | Analog |
| Green | Digital |
| Purple | PWM |
| Gold | I2C (SDA/SCL) |
| Orange | SPI (MOSI/MISO/SCK) |
| Cyan | USART (TX/RX) |
| Component | Description |
|---|---|
| LED | Single LED with configurable color |
| RGB LED | Three-color LED (red, green, blue channels) |
| 7-Segment Display | Single digit numeric display |
| LCD 16×2 | 2-line character LCD (I2C or parallel) |
| LCD 20×4 | 4-line character LCD |
| ILI9341 TFT | 240×320 color TFT display (SPI) |
| Buzzer | Passive piezo buzzer |
| NeoPixel | Individually addressable RGB LED strip |
| Component | Description |
|---|---|
| Push Button | Momentary push button |
| Slide Switch | SPDT slide switch |
| Potentiometer | Analog voltage divider (ADC input) |
| Rotary Encoder | Incremental rotary encoder |
| Keypad 4×4 | 16-button matrix keypad |
| Joystick | Dual-axis analog joystick |
| Component | Description |
|---|---|
| HC-SR04 | Ultrasonic distance sensor |
| DHT22 | Temperature and humidity sensor |
| PIR Motion | Passive infrared motion sensor |
| Photoresistor | Light-dependent resistor (LDR) |
| IR Receiver | 38 kHz infrared receiver |
| Component | Description |
|---|---|
| Resistor | Standard resistor (configurable value) |
| Capacitor | Electrolytic capacitor |
| Inductor | Coil inductor |
Each component has a Property Dialog accessible by clicking it on the canvas:
| Property | Description |
|---|---|
| Arduino Pin | The digital or analog pin this component is connected to |
| Color | Visual color (LEDs, wires) |
| Value | Component value (e.g., resistance in Ω) |
| Rotation | Rotate in 90° increments |
| Delete | Remove the component from the canvas |
Features that are implemented, in progress, and planned for future releases of Velxio.
arduino-cli (multi-file sketch support).zip filesmainVelxio is a fully local Arduino emulator using official Wokwi repositories for maximum compatibility. It features real AVR8 CPU emulation, 48+ interactive electronic components, a comprehensive wire system, and a build-time component discovery pipeline.
{`Browser (React + Vite)
├── Monaco Editor ──► useEditorStore (Zustand)
├── SimulatorCanvas ──► useSimulatorStore (Zustand)
│ ├── AVRSimulator (avr8js) 16 MHz AVR8 CPU
│ ├── RP2040Simulator (rp2040js)
│ ├── PinManager pin → component mapping
│ ├── PartSimulationRegistry 16 interactive parts
│ └── 48+ wokwi-elements Lit Web Components
└── HTTP (Axios) ──► FastAPI Backend (port 8001)
└── ArduinoCLIService ──► arduino-cli subprocess`}
{`Click "Compile"
→ EditorToolbar reads all workspace files
→ POST /api/compile/ { files, board_fqbn }
→ Backend: ArduinoCLIService writes temp dir
→ arduino-cli compile --fqbn --output-dir build/
→ Returns hex_content (Intel HEX string)
→ useSimulatorStore.setCompiledHex() → loadHex()`}
{`Click "Run"
→ AVRSimulator.start()
→ requestAnimationFrame loop @ ~60 FPS
→ Each frame: Math.floor(267 000 × speed) cycles
├── avrInstruction(cpu) — decode + execute one AVR instruction
└── cpu.tick() — advance Timer0/1/2, USART, ADC
→ PORTB/C/D write listeners fire
→ PinManager.updatePort() → per-pin callbacks
→ PartSimulationRegistry.onPinStateChange()
→ wokwi-elements update visually`}
{`User presses button on canvas
→ wokwi web component fires 'button-press' event
→ DynamicComponent catches event
→ PartSimulationRegistry.attachEvents() handler
→ AVRSimulator.setPinState(arduinoPin, LOW)
→ AVRIOPort.setPin() injects external pin state
→ CPU reads pin in next instruction`}
| Store | Key State | Purpose |
|---|---|---|
useEditorStore | files[], activeFileId | Multi-file Monaco workspace |
useSimulatorStore | simulator, components, wires, running | Simulation + canvas state |
useAuthStore | user, token | Auth (persisted localStorage) |
useProjectStore | projectId, slug | Currently open project |
| Route | Description |
|---|---|
POST /api/compile/ | Compile sketch files → Intel HEX / UF2 |
GET /api/compile/boards | List available boards |
GET/POST /api/auth/* | Email/password + Google OAuth |
GET/POST /api/projects/* | CRUD project persistence (SQLite) |
GET /api/libraries/* | Arduino Library Manager integration |
GET /health | Health check endpoint |
Wires are stored as objects with start/end endpoints tied to component pin positions:
{`{
id: string
start: { componentId, pinName, x, y }
end: { componentId, pinName, x, y }
color: string
signalType: 'digital' | 'analog' | 'power-vcc' | 'power-gnd'
}`}
Velxio uses official Wokwi open-source repositories cloned locally in wokwi-libs/.
This gives you up-to-date, compatible emulation engines and visual components without npm registry
dependencies.
| Library | Location | Purpose |
|---|---|---|
| wokwi-elements | wokwi-libs/wokwi-elements/ |
48+ Lit Web Components (LEDs, LCDs, sensors, buttons…) |
| avr8js | wokwi-libs/avr8js/ |
ATmega328p / ATmega2560 CPU emulator at 16 MHz |
| rp2040js | wokwi-libs/rp2040js/ |
Raspberry Pi Pico (RP2040) emulator |
frontend/vite.config.ts uses path aliases so imports resolve to the local builds:
{`resolve: {
alias: {
'avr8js': '../wokwi-libs/avr8js/dist/esm',
'@wokwi/elements': '../wokwi-libs/wokwi-elements/dist/esm',
},
}`}
{`# Windows
update-wokwi-libs.bat`}
{`cd wokwi-libs/wokwi-elements
git pull origin main
npm install && npm run build
cd ../avr8js
git pull origin main
npm install && npm run build
cd ../rp2040js
git pull origin main
npm install && npm run build`}
Regenerate component metadata so new components appear in the picker:
{`cd frontend
npx tsx ../scripts/generate-component-metadata.ts`}
| Category | Components |
|---|---|
| Boards | Arduino Uno, Mega, Nano, ESP32 DevKit |
| Sensors | DHT22, HC-SR04, PIR, Photoresistor, NTC, Joystick |
| Displays | LCD 16×2, LCD 20×4, 7-Segment |
| Input | Push button, 6mm button, Slide switch, DIP switch 8, Potentiometer |
| Output | LED, RGB LED, LED bar graph, Buzzer, NeoPixel |
| Motors | Servo, Stepper motor |
| Passive | Resistor, Slide potentiometer, LED ring, Matrix keypad |
| Other | IR receiver, DS1307 RTC, breadboards, etc. |
{`import { CPU, avrInstruction, AVRTimer, AVRUSART, AVRADC, AVRIOPort } from 'avr8js';
const cpu = new CPU(programMemory); // ATmega328p at 16 MHz
const portB = new AVRIOPort(cpu, portBConfig); // digital pins 8-13
const portC = new AVRIOPort(cpu, portCConfig); // analog pins A0-A5
const portD = new AVRIOPort(cpu, portDConfig); // digital pins 0-7
function runFrame() {
const cycles = Math.floor(267_000 * speed);
for (let i = 0; i < cycles; i++) {
avrInstruction(cpu); // execute one AVR instruction
cpu.tick(); // advance timers + peripherals
}
requestAnimationFrame(runFrame);
}`}
Velxio exposes a{' '} Model Context Protocol {' '} (MCP) server that lets AI agents (Claude, Cursor, and others) create circuits, generate code, and compile Arduino sketches directly.
| Tool | Description |
|---|---|
compile_project | Compile Arduino sketch files → Intel HEX / binary |
run_project | Compile and mark artifact as simulation-ready |
import_wokwi_json | Parse a Wokwi diagram.json → Velxio circuit |
export_wokwi_json | Serialise a Velxio circuit → Wokwi diagram.json |
create_circuit | Create a new circuit definition |
update_circuit | Merge changes into an existing circuit |
generate_code_files | Generate starter .ino code from a circuit |
{`cd backend
python mcp_server.py`}
Claude Desktop config (~/.claude/claude_desktop_config.json):
{`{
"mcpServers": {
"velxio": {
"command": "python",
"args": ["/absolute/path/to/velxio/backend/mcp_server.py"]
}
}
}`}
{`cd backend
python mcp_sse_server.py --port 8002`}
MCP client config:
{`{
"mcpServers": {
"velxio": { "url": "http://localhost:8002/sse" }
}
}`}
Velxio circuits are plain JSON objects:
{`{
"board_fqbn": "arduino:avr:uno",
"version": 1,
"components": [
{ "id": "led1", "type": "wokwi-led", "left": 200, "top": 100,
"rotate": 0, "attrs": { "color": "red" } }
],
"connections": [
{ "from_part": "uno", "from_pin": "13",
"to_part": "led1", "to_pin": "A", "color": "green" }
]
}`}
| Board | FQBN |
|---|---|
| Arduino Uno | arduino:avr:uno |
| Arduino Mega | arduino:avr:mega |
| Arduino Nano | arduino:avr:nano |
| Raspberry Pi Pico | rp2040:rp2040:rpipico |
{`// Step 1 — Create a circuit
{
"tool": "create_circuit",
"arguments": {
"board_fqbn": "arduino:avr:uno",
"components": [
{ "id": "led1", "type": "wokwi-led",
"left": 150, "top": 100, "attrs": { "color": "red" } },
{ "id": "r1", "type": "wokwi-resistor",
"left": 150, "top": 180, "attrs": { "value": "220" } }
],
"connections": [
{ "from_part": "uno", "from_pin": "13",
"to_part": "led1", "to_pin": "A", "color": "green" },
{ "from_part": "led1", "from_pin": "C",
"to_part": "r1", "to_pin": "1", "color": "black" },
{ "from_part": "r1", "from_pin": "2",
"to_part": "uno", "to_pin": "GND.1", "color": "black" }
]
}
}
// Step 2 — Generate code
{
"tool": "generate_code_files",
"arguments": {
"circuit": "",
"sketch_name": "blink",
"extra_instructions": "Blink the red LED every 500ms"
}
}
// Step 3 — Compile
{
"tool": "compile_project",
"arguments": {
"files": [
{
"name": "blink.ino",
"content": "void setup(){pinMode(13,OUTPUT);}\\nvoid loop(){digitalWrite(13,HIGH);delay(500);digitalWrite(13,LOW);delay(500);}"
}
],
"board": "arduino:avr:uno"
}
}`}
{`cd backend
pip install -r requirements.txt
# Ensure arduino-cli is installed
arduino-cli version
arduino-cli core update-index
arduino-cli core install arduino:avr
# Run tests
python -m pytest tests/test_mcp_tools.py -v`}
A comprehensive overview of all features currently implemented in Velxio.
| Feature | Status |
|---|---|
| ATmega328p CPU at 16 MHz | ✅ Working |
| Timer0, Timer1, Timer2 | ✅ Working |
| USART (Serial) | ✅ Working |
ADC (analogRead) | ✅ Working |
| Full GPIO (PORTB / PORTC / PORTD) | ✅ Working |
| ~60 FPS loop (267k cycles/frame) | ✅ Working |
| Speed control (0.1× – 10×) | ✅ Working |
| PWM monitoring (6 channels) | ✅ Working |
| External pin injection (inputs) | ✅ Working |
| Feature | Status |
|---|---|
| Automatic discovery via AST | ✅ 48 components detected |
| ComponentPickerModal with search | ✅ Working |
| 9 categories with filters | ✅ Working |
| Generic DynamicComponent renderer | ✅ Working |
| Drag-and-drop on canvas | ✅ Working |
| Rotation (90° increments) | ✅ Working |
| Properties dialog (single-click) | ✅ Working |
| Pin overlay (clickable cyan dots) | ✅ Working |
| Part | Type | Status |
|---|---|---|
| LED | Output | ✅ |
| RGB LED | Output (digital + PWM) | ✅ |
| LED Bar Graph (10 LEDs) | Output | ✅ |
| 7-Segment Display | Output | ✅ |
| Pushbutton | Input | ✅ |
| Pushbutton 6mm | Input | ✅ |
| Slide Switch | Input | ✅ |
| DIP Switch 8 | Input | ✅ |
| Potentiometer | Input (ADC) | ✅ |
| Slide Potentiometer | Input (ADC) | ✅ |
| Photoresistor | Input / Output | ✅ |
| Analog Joystick | Input (ADC + digital) | ✅ |
| Servo | Output | ✅ |
| Buzzer | Output (Web Audio) | ✅ |
| LCD 1602 | Output (full HD44780) | ✅ |
| LCD 2004 | Output (full HD44780) | ✅ |
| Feature | Status |
|---|---|
| Pin-to-pin creation with click | ✅ Working |
| Real-time preview (green dashed) | ✅ Working |
| Orthogonal routing (no diagonals) | ✅ Working |
| Segment editing (perpendicular drag) | ✅ Working |
| 8 colours by signal type | ✅ Working |
| Auto-update when moving components | ✅ Working |
| Grid snapping (20 px) | ✅ Working |
| Wire selection and deletion | ✅ Working |
| Example | Category | Difficulty |
|---|---|---|
| Blink LED | Basics | Beginner |
| Traffic Light | Basics | Beginner |
| Button Control | Basics | Beginner |
| Fade LED (PWM) | Basics | Beginner |
| Serial Hello World | Communication | Beginner |
| RGB LED Colors | Basics | Intermediate |
| Simon Says Game | Games | Advanced |
| LCD 20×4 Display | Displays | Intermediate |
| Problem | Solution |
|---|---|
| Components not displayed | |
Cannot find module 'avr8js' |
|
| LED doesn't blink | Compile first, then click Run. Check pin assignment in the component property dialog. |
| New component not in picker | |