SimDuino SimDuino v0.14.0-preview

Docs

How to drive SimDuino, what it simulates, and the JSON diagram format.

1. Quick start

  1. Open the Studio. It loads with a Blink circuit already wired and a starter sketch in the editor.
  2. Click Run. The sketch compiles on our server, downloads as Intel HEX, and runs in a real ATmega328p emulator (avr8js). The on-board L13 LED starts blinking; pin 13 on the virtual Uno toggles every 500 ms.
  3. Click Demos  ▾ to load any of the bundled circuits + sketches. Each demo clears the canvas, places the components, wires them, and loads the matching sketch.
Sketch.ino editor arduino-cli avr-gcc → HEX avr8js ATmega328p 16 MHz · cycle-accurate Studio bus pin events Render MNA Sketch → HEX → emulator → studio Pin events fan out to component visuals and the DC solver in parallel.
From sketch text to live visuals: arduino-cli compiles, avr8js executes, the studio event bus distributes pin transitions.

2. The Studio

The Studio is a single SVG canvas that holds three layers:

  • Components — Arduino, breadboards, resistors, LEDs, sensors. Click a part in the palette and drop it on the canvas (or tap to place at canvas centre).
  • Wires — click one pin then another to wire them. Pins glow when the mouse is within 14 px; the wire snaps to the nearest pin.
  • Overlay — the selection ring, drag ghost, and pin highlights.

The Parts palette on the left has a search box (type "uno", "led", "resistor"…) and collapsible category headers. Categories include Boards · Prototyping · Inputs · Sensors · Outputs · Drivers · Passives · Active.

The Inspector on the right shows the selected component's props: resistor value, LED colour, pot wiper value, LDR brightness, capacitor capacitance, etc. Sliders update live while a sketch is running — twist a pot and the AVR sees the new analogRead() value on the next loop iteration.

Below the canvas: the code editor + serial monitor.

3. View modes

Three view buttons in the canvas toolbar:

  • Breadboard — pseudo-physical view. Components look like real parts.
  • Schematic — symbol view (resistor zigzag, transistor triangle, etc.). Wires unchanged.
  • JSON — Wokwi-inspired editable diagram document. Edit it and click Apply to replace the live circuit. Useful for templating, sharing, or batch edits. Format spec below.
Same circuit · three lenses Breadboard pseudo-physical UNO Schematic symbol view UNO D13 GND R1 JSON round-trippable diagram.json { "parts": [ { "type":"led"… } ], "connections":[…] } ▶ Apply Breadboard + Schematic render only · JSON is the editable source of truth.
Same circuit, three lenses. JSON is the only one where edits round-trip — Breadboard and Schematic are pure render modes.

4. Sketch editor

Plain <textarea> with monospace font. Standard Arduino C++. Compiled by arduino-cli on our own Hetzner box using --fqbn arduino:avr:uno; resulting HEX cached by sketch hash so repeat runs are instant.

  • Reset button restores the starter sketch.
  • Copy button puts the current sketch on your clipboard.
  • Cmd/Ctrl + Enter runs the sketch from inside the editor.
  • Tab inserts two spaces.
  • Autosaved to localStorage on every change.

Standard libraries already installed on the build server: LiquidCrystal, Servo. Need another? Open an issue or use the contact link.

5. Serial monitor

USART output from the AVR streams in real time. Cmd/Ctrl+Enter from the editor runs the sketch and clears the monitor. Bytes are accumulated and decoded as UTF-8 on newline, so °, , µ, em-dashes, and emoji all render correctly. Capped at 500 lines so a runaway Serial.println() loop can't grow the page.

Copy button on the monitor dumps the visible lines (with timestamps) to your clipboard.

6. Demos

Each demo loads a fully-wired circuit AND the matching sketch. Below: the topology behind the simplest one — Blink.

ARDUINO UNO ATMEGA328P D13 GND 220 Ω K A D13 → 220 Ω → LED.A · LED.K → GND Sketch toggles D13 every 500 ms; the LED follows.
The Blink demo's circuit: 220 Ω current-limit resistor in series with a red LED, driven by D13.

The complete demo list:

  • Blink — D13 → 220Ω → LED → GND. The Hello World.
  • PWM LED FadeanalogWrite() on D9 makes the LED breathe.
  • RGB Color Mix — Common-cathode RGB on D9 / D10 / D11.
  • Live Pot → analogRead — Twist the pot, watch Serial.
  • Button → LEDINPUT_PULLUP idiom.
  • Buzzer melody — C-major scale with tone().
  • LDR night-light — Photoresistor → PWM brightness.
  • Knight Rider — Six LEDs on D2–D7 swept back and forth.
  • NPN Low-Side Switch · PNP High-Side Switch — Discrete transistor demos.
  • Capacitor blocks DC — Demonstrates the cap-as-open at DC steady-state.
  • LCD 16×2 Hello — Scrolling text + live millis() counter.
  • HC-SR04 Distance — Ultrasonic ping; slider sets simulated range.
  • Pot → ServoanalogRead drives Servo.write in real time.
  • Relay click — D7 toggles a 5 V coil once per second.
  • Thermistor → A0 — 10 kΩ NTC with Steinhart Beta-equation decoding.
  • DC Motor + L293D — Direction + PWM speed via H-bridge.

7. Component reference

Every part exposes a type, size, pins, defaultProps, a render() and (sometimes) an onCircuitChange() callback. Pins always have an id; many have a dir (up / down / left / right) that drives the Manhattan wire router.

TypePinsNotes
unoD0–D13 (top), VIN / 5V / 3V3 / GND / GND2 / RST / IOREF / A0–A5 (bottom)The ATmega328p emulator; output pins drive 5V through a 25 Ω internal R.
breadboardtA-row-col / bA-row-col + power railsHalf-rows in standard 5-tie / 5-tie layout.
ledA, KForward-biased only when A is higher than K. Brightness scales with current; burns out above 35 mA.
rgb_ledR, G, B, C (common cathode)Per-channel PWM mixing.
resistor1, 2props.ohms sets the value. Used in the DC solver; values matter.
cap_ceramic / cap_electrolytic1, 2 / +, -props.value string ("100nF", "10uF", "470µF"). Integrated over time with backward-Euler.
npn / pnpC, B, EModelled as a switch with VCE,sat ≈ 0.2 V (2 Ω on-resistance) when conducting.
button1, 2Clicked = pins shorted. Two-position.
pot1, W, 3Inspector slider sets props.value (0–1023). Wiper feeds the connected analog pin.
ldr1, 2Inspector "brightness" maps directly to ADC reading.
thermistor1, 210 kΩ NTC; inspector temperature → ADC via piecewise NTC table.
buzzer+, -Web Audio square-wave oscillator at the AVR's measured pin-toggle frequency.
motorM1, M2Spin direction + RPM derived from differential voltage / PWM.
servoVCC, SIG, GNDPulse-width decoded to 0–180°; horn rotates.
h_bridgeVCC, GND, ENA, IN1, IN2, OUT1, OUT2L293D-style. Forward / reverse / brake. ENA PWM passes through to outputs.
relayVCC, IN, GND, COM, NO, NCIN HIGH → coil energised → status LED on, COM ↔ NO.
hc_sr04VCC, TRIG, ECHO, GNDInspector distance (cm). TRIG falling edge → ECHO pulse of distance × 58 µs scheduled cycle-accurately.
lcdVSS, VDD, RS, E, D4D7HD44780 4-bit. Tracks E falling edge to latch nibbles. Standard LiquidCrystal sketches work.

8. JSON diagram format

Switch to JSON view to see (and edit) the circuit as a Wokwi-inspired document:

{
  "version": 1,
  "parts": [
    { "id": "c0", "type": "uno",      "x": 40,  "y": 280, "rot": 0, "attrs": {} },
    { "id": "c1", "type": "resistor", "x": 440, "y": 100, "rot": 0, "attrs": { "ohms": 220 } },
    { "id": "c2", "type": "led",      "x": 620, "y": 180, "rot": 0, "attrs": { "color": "red" } }
  ],
  "connections": [
    ["c0:D13", "c1:1",  "auto"],
    ["c1:2",   "c2:A",  "auto"],
    ["c2:K",   "c0:GND", "auto"]
  ]
}

Fields:

  • version — always 1.
  • parts[].id — unique string. The serializer uses "c<n>" but anything works.
  • parts[].type — one of the catalog names from the component table (uno, led, lcd, …). Wokwi's wokwi-arduino-uno prefix is not mapped — use our names directly.
  • parts[].x / y — canvas-space pixels.
  • parts[].rot — 0 / 90 / 180 / 270 degrees.
  • parts[].attrs — the same object as props on the live component (resistor ohms, LED color, cap value, etc.).
  • connections[]["partId:pinId", "partId:pinId", color]. The color string is informational; "auto" lets the studio pick from its palette.

Hit Apply to swap the canvas for the parsed JSON. Validation runs first: unknown types, duplicate IDs, malformed endpoints all surface as errors before anything changes.

Wokwi's wire mini-language ("v10", "h-5", "*") is parsed but ignored — the studio's Manhattan auto-router places every wire.

9. Circuit solver — what's actually simulated

Resistor values, LED forward voltages, transistor saturation, and capacitor charge are all modelled by a Modified Nodal Analysis solver that runs on every pin event plus a 33 Hz tick when capacitors are present. Lives in assets/js/circuit-solver.js.

Runs on every pin event · 33 Hz tick when caps are present Components + wires + props Net topology union-find G · V = z MNA stamps Gauss-Jordan + Newton diodes up to 16 iter V I solution Brightness · fried · cap Vprev written back to component props feedback
The MNA solver builds a conductance matrix for the visible circuit, solves it, and writes LED currents + cap voltages back to the components.

Specifically:

  • Resistors use their real ohms. Swap 220 Ω for 47 Ω and the LED gets visibly brighter; swap for 10 kΩ and it dims.
  • LEDs are piecewise-linear diodes with per-colour Vf (red 2.0 V, green 2.2 V, blue 3.1 V) and 10 Ω on-resistance. Current ≥ 35 mA flags the LED fried and the body re-renders burnt.
  • Voltage sources — Uno's 5V / 3V3 / VIN rails are ideal sources. Output pins are 5 V (HIGH) / 0 V (LOW) through a 25 Ω internal R that matches the AVR's output stage.
  • Transistors — NPN / PNP modelled as a 2 Ω switch when conducting (VCE,sat ≈ 0.2 V at typical Ic). Base decision still binary.
  • Capacitors — backward-Euler transient integration. props._capV persists across solves. RC time constants are real (try a 470 µF cap with a 1 kΩ resistor and watch the LED fade).

Deliberately not modelled: inductors, AC analysis, op-amps, Shockley diode equation, h-parameter transistors. Open the About page or the roadmap for current scope.

10. Keyboard shortcuts

KeyAction
Cmd / Ctrl + ZUndo
Cmd / Ctrl + Shift + Z · Cmd+YRedo
Cmd / Ctrl + EnterRun sketch (from inside the editor)
RRotate selected component 90°
DDuplicate selected component
Del / BackspaceDelete selected component or wire
EscCancel in-progress wire / deselect
Cmd / Ctrl + scrollZoom canvas
Pinch (touch)Zoom canvas; two-finger drag pans

11. Known limits

  • Voltage dividers with resistor-as-conductor demos still work because the solver sees real resistors — but the live cell at analogRead goes through the studio's pinSources path, which doesn't run through the solver. Wire a pot to a real voltage divider and twist it: the AVR reads the slider directly, not the divided voltage.
  • Mobile drag-drop works but the canvas is busy on a small screen. Pinch-zoom helps. The action toolbar gets a phone-specific layout at ≤ 1080 px.
  • Compile errors come from avr-gcc via arduino-cli on our server. If our endpoint is down, the runner falls back to hexi.wokwi.com.
  • The HEX cache is keyed by sketch text. Adding a comment changes the digest. Identical sketches return instantly on second run.
  • tone() pitch depends on the AVR actually toggling the pin at audio rate. noTone() stops it. Multiple buzzers play independently.