velxio/frontend/src/data/examples-circuits.ts

1616 lines
65 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Circuit-focused example projects — analog, digital, electromechanical.
*
* These examples showcase the SPICE electrical simulation mode with real
* component models (transistors, op-amps, regulators, gates, relays).
* Each example has a matching ngspice test in test/test_circuit/test/spice_examples.test.js.
*/
import type { ExampleProject } from './examples';
// ─── Helper: standard Arduino Uno at (100,100) ─────────────────────────────
const UNO = { type: 'wokwi-arduino-uno', id: 'arduino-uno', x: 100, y: 100, properties: {} };
const MEGA = { type: 'wokwi-arduino-mega', id: 'arduino-mega', x: 80, y: 80, properties: {} };
const ESP32 = { type: 'wokwi-esp32-devkit-v1', id: 'esp32', x: 80, y: 80, properties: {} };
function w(id: string, from: [string, string], to: [string, string], color = '#00aaff') {
return {
id,
start: { componentId: from[0], pinName: from[1] },
end: { componentId: to[0], pinName: to[1] },
color,
};
}
export const circuitExamples: ExampleProject[] = [
// ════════════════════════════════════════════════════════════════════════════
// PASSIVE / ANALOG (10 examples)
// ════════════════════════════════════════════════════════════════════════════
{
id: 'voltage-divider',
title: 'Voltage Divider',
description: 'R1 + R2 divide 5V into a lower voltage read by ADC. Fundamental analog circuit.',
category: 'circuits',
difficulty: 'beginner',
code: `// Voltage Divider — reads V_out = 5 * R2/(R1+R2)
void setup() { Serial.begin(9600); }
void loop() {
int raw = analogRead(A0);
float v = raw * 5.0 / 1023.0;
Serial.print("V_out = "); Serial.print(v, 3); Serial.println(" V");
delay(500);
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'r1', x: 350, y: 80, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'r2', x: 350, y: 200, properties: { value: '10000' } },
],
wires: [
w('w1', ['arduino-uno', '5V'], ['r1', '1'], '#ff0000'),
w('w2', ['r1', '2'], ['r2', '1'], '#00aaff'),
w('w3', ['r2', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w4', ['r1', '2'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
{
id: 'rc-low-pass-filter',
title: 'RC Low-Pass Filter',
description: 'PWM output filtered by RC gives smooth analog voltage. Classic DAC trick.',
category: 'circuits',
difficulty: 'beginner',
code: `// RC Low-Pass Filter
// PWM on pin 9 → R=10k → C=10uF → smooth DC on A0
// DC steady-state: V_out ≈ duty × Vcc = 0.5 × 5 = 2.5 V
void setup() { Serial.begin(9600); analogWrite(9, 128); } // 50% duty
void loop() {
float v = analogRead(A0) * 5.0 / 1023.0;
Serial.print("Filtered V = "); Serial.println(v, 2);
delay(200);
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'r1', x: 350, y: 100, properties: { value: '10000' } },
{ type: 'wokwi-capacitor', id: 'c1', x: 420, y: 200, properties: { value: '10u' } },
],
wires: [
w('w1', ['arduino-uno', '9'], ['r1', '1'], '#00aaff'),
w('w2', ['r1', '2'], ['arduino-uno', 'A0'], '#ffaa00'),
w('w3', ['r1', '2'], ['c1', '1'], '#ffaa00'),
w('w4', ['c1', '2'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'wheatstone-bridge',
title: 'Wheatstone Bridge',
description:
'Four-resistor bridge detects tiny resistance changes. Used in strain gauges and load cells.',
category: 'circuits',
difficulty: 'intermediate',
code: `// Wheatstone Bridge — detects R imbalance
void setup() { Serial.begin(9600); }
void loop() {
float vA = analogRead(A0) * 5.0 / 1023.0;
float vB = analogRead(A1) * 5.0 / 1023.0;
float diff = vA - vB;
Serial.print("V_diff = "); Serial.print(diff * 1000, 1); Serial.println(" mV");
delay(500);
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'r1', x: 350, y: 60, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'r2', x: 500, y: 60, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'r3', x: 350, y: 200, properties: { value: '11000' } },
{ type: 'wokwi-resistor', id: 'r4', x: 500, y: 200, properties: { value: '10000' } },
],
wires: [
w('w1', ['arduino-uno', '5V'], ['r1', '1'], '#ff0000'),
w('w2', ['arduino-uno', '5V'], ['r2', '1'], '#ff0000'),
w('w3', ['r1', '2'], ['r3', '1'], '#00aaff'),
w('w4', ['r2', '2'], ['r4', '1'], '#00aaff'),
w('w5', ['r3', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w6', ['r4', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w7', ['r1', '2'], ['arduino-uno', 'A0'], '#ffaa00'),
w('w8', ['r2', '2'], ['arduino-uno', 'A1'], '#ffaa00'),
],
},
{
id: 'ntc-temperature',
title: 'NTC Temperature Sensor',
description:
'NTC breakout module (built-in 10k pull-up). Calculates temperature via beta model.',
category: 'circuits',
difficulty: 'beginner',
code: `// NTC Temperature Sensor (beta model)
#define NTC_PIN A0
#define R_PULL 10000.0
#define NTC_R0 10000.0
#define NTC_T0 298.15
#define NTC_BETA 3950.0
void setup() { Serial.begin(9600); }
void loop() {
int raw = analogRead(NTC_PIN);
float v = raw * 5.0 / 1023.0;
float rNtc = R_PULL * v / (5.0 - v);
float tK = 1.0 / (1.0/NTC_T0 + log(rNtc/NTC_R0)/NTC_BETA);
float tC = tK - 273.15;
Serial.print("Temp = "); Serial.print(tC, 1); Serial.println(" C");
delay(1000);
}`,
components: [
UNO,
{
type: 'wokwi-ntc-temperature-sensor',
id: 'ntc',
x: 350,
y: 150,
properties: { temperature: '25' },
},
],
wires: [
w('w1', ['arduino-uno', '5V'], ['ntc', 'VCC'], '#ff0000'),
w('w2', ['ntc', 'GND'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['ntc', 'OUT'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
{
id: 'led-current-limiting',
title: 'LED with Current-Limiting Resistor',
description: 'Calculate R to set LED current to 10mA. I = (Vcc-Vf)/R.',
category: 'circuits',
difficulty: 'beginner',
code: `// LED with current-limiting resistor
// R = (5V - 2V) / 10mA = 300 ohm
void setup() { pinMode(13, OUTPUT); }
void loop() {
digitalWrite(13, HIGH); delay(1000);
digitalWrite(13, LOW); delay(1000);
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'r1', x: 380, y: 120, properties: { value: '330' } },
{ type: 'wokwi-led', id: 'led1', x: 380, y: 220, properties: { color: 'red' } },
],
wires: [
w('w1', ['arduino-uno', '13'], ['r1', '1'], '#00aaff'),
w('w2', ['r1', '2'], ['led1', 'A'], '#00aaff'),
w('w3', ['led1', 'C'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'parallel-resistors',
title: 'Parallel Resistors',
description: 'Three resistors in parallel: R_total = 1/(1/R1+1/R2+1/R3). Measure with ADC.',
category: 'circuits',
difficulty: 'beginner',
code: `// Parallel Resistors — measure equivalent R via voltage divider
// R_series = 10k, R_parallel = 1/(1/10k + 1/10k + 1/10k) = 3.33k
// V_out = 5 * R_par / (R_ser + R_par) = 5 * 3.33 / 13.33 = 1.25V
void setup() { Serial.begin(9600); }
void loop() {
float v = analogRead(A0) * 5.0 / 1023.0;
Serial.print("V = "); Serial.println(v, 3);
delay(500);
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'rs', x: 350, y: 80, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'r1', x: 350, y: 200, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'r2', x: 420, y: 200, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'r3', x: 490, y: 200, properties: { value: '10000' } },
],
wires: [
w('w1', ['arduino-uno', '5V'], ['rs', '1'], '#ff0000'),
w('w2', ['rs', '2'], ['r1', '1'], '#ffaa00'),
w('w3', ['rs', '2'], ['r2', '1'], '#ffaa00'),
w('w4', ['rs', '2'], ['r3', '1'], '#ffaa00'),
w('w5', ['r1', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w6', ['r2', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w7', ['r3', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w8', ['rs', '2'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
{
id: 'pot-adc-reader',
title: 'Potentiometer ADC Reader',
description: 'Turn the potentiometer knob to vary the voltage on A0 from 0 to 5V.',
category: 'circuits',
difficulty: 'beginner',
code: `// Potentiometer reader
void setup() { Serial.begin(9600); }
void loop() {
int raw = analogRead(A0);
float pct = raw * 100.0 / 1023.0;
Serial.print("Position: "); Serial.print(pct, 1); Serial.println("%");
delay(200);
}`,
components: [UNO, { type: 'wokwi-potentiometer', id: 'pot', x: 380, y: 160, properties: {} }],
wires: [
w('w1', ['arduino-uno', '5V'], ['pot', 'VCC'], '#ff0000'),
w('w2', ['pot', 'GND'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['pot', 'SIG'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
{
id: 'photoresistor-light',
title: 'Photoresistor Light Sensor',
description:
'LDR + pull-down resistor. Brighter light = lower LDR resistance = higher voltage.',
category: 'circuits',
difficulty: 'beginner',
code: `// Photoresistor light sensor
void setup() { Serial.begin(9600); }
void loop() {
int raw = analogRead(A0);
float lux = map(raw, 0, 1023, 0, 100);
Serial.print("Light: "); Serial.print(lux, 0); Serial.println("%");
delay(300);
}`,
components: [
UNO,
{ type: 'wokwi-photoresistor-sensor', id: 'ldr', x: 380, y: 150, properties: { lux: '500' } },
],
wires: [
w('w1', ['arduino-uno', '5V'], ['ldr', 'VCC'], '#ff0000'),
w('w2', ['ldr', 'GND'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['ldr', 'AO'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
{
id: 'multi-led-bar',
title: 'LED Bar Graph',
description: '5 LEDs driven from digital pins with individual resistors. Bargraph display.',
category: 'circuits',
difficulty: 'beginner',
code: `// LED Bar Graph — 5 LEDs on pins 2-6
void setup() { for(int i=2;i<=6;i++) pinMode(i,OUTPUT); }
void loop() {
for(int i=2;i<=6;i++) { digitalWrite(i,HIGH); delay(200); }
for(int i=6;i>=2;i--) { digitalWrite(i,LOW); delay(200); }
}`,
components: [
UNO,
...Array.from({ length: 5 }, (_, i) => ({
type: 'wokwi-resistor',
id: `r${i}`,
x: 350,
y: 60 + i * 50,
properties: { value: '220' },
})),
...Array.from({ length: 5 }, (_, i) => ({
type: 'wokwi-led',
id: `led${i}`,
x: 450,
y: 60 + i * 50,
properties: { color: ['red', 'yellow', 'green', 'blue', 'white'][i] },
})),
],
wires: [
...Array.from({ length: 5 }, (_, i) =>
w(`wa${i}`, ['arduino-uno', `${i + 2}`], [`r${i}`, '1']),
),
...Array.from({ length: 5 }, (_, i) => w(`wb${i}`, [`r${i}`, '2'], [`led${i}`, 'A'])),
...Array.from({ length: 5 }, (_, i) =>
w(`wc${i}`, [`led${i}`, 'C'], ['arduino-uno', 'GND'], '#000000'),
),
],
},
{
id: 'capacitor-charge-curve',
title: 'Capacitor Charging Curve',
description: 'Charge a capacitor through a resistor, read the exponential V(t) via ADC.',
category: 'circuits',
difficulty: 'intermediate',
code: `// RC Charging — observe exponential curve
// tau = R*C = 10k * 100uF = 1 second
void setup() {
Serial.begin(9600);
pinMode(8, OUTPUT);
digitalWrite(8, HIGH); // start charging
}
void loop() {
float v = analogRead(A0) * 5.0 / 1023.0;
Serial.print("V_cap = "); Serial.println(v, 3);
delay(100);
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'r1', x: 380, y: 100, properties: { value: '10000' } },
{ type: 'wokwi-capacitor', id: 'c1', x: 450, y: 200, properties: { value: '100u' } },
],
wires: [
w('w1', ['arduino-uno', '8'], ['r1', '1'], '#00aaff'),
w('w2', ['r1', '2'], ['c1', '1'], '#ffaa00'),
w('w3', ['r1', '2'], ['arduino-uno', 'A0'], '#ffaa00'),
w('w4', ['c1', '2'], ['arduino-uno', 'GND'], '#000000'),
],
},
// ════════════════════════════════════════════════════════════════════════════
// TRANSISTOR / SEMICONDUCTOR (8 examples)
// ════════════════════════════════════════════════════════════════════════════
{
id: 'npn-led-switch',
title: 'NPN Transistor LED Switch',
description: '2N2222 NPN switches a high-current LED from a low-current MCU pin.',
category: 'circuits',
difficulty: 'intermediate',
code: `// NPN switch — pin 9 drives base through 1k, collector drives LED
void setup() { pinMode(9, OUTPUT); }
void loop() {
digitalWrite(9, HIGH); delay(1000);
digitalWrite(9, LOW); delay(1000);
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'rb', x: 380, y: 100, properties: { value: '1000' } },
{ type: 'wokwi-resistor', id: 'rc', x: 480, y: 60, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'led1', x: 480, y: 160, properties: { color: 'green' } },
{ type: 'wokwi-bjt-2n2222', id: 'q1', x: 480, y: 260, properties: {} },
],
wires: [
// Base drive: pin 9 → 1k → base
w('w1', ['arduino-uno', '9'], ['rb', '1']),
w('w2', ['rb', '2'], ['q1', 'B']),
// Load path: 5V → Rc → LED → collector
w('w3', ['arduino-uno', '5V'], ['rc', '1'], '#ff0000'),
w('w4', ['rc', '2'], ['led1', 'A']),
w('w5', ['led1', 'C'], ['q1', 'C']),
// Emitter to ground
w('w6', ['q1', 'E'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'pnp-high-side-switch',
title: 'PNP High-Side Switch',
description: '2N3906 PNP switches a load to Vcc when base is pulled LOW.',
category: 'circuits',
difficulty: 'intermediate',
code: `// PNP high-side switch
// Pin 9 LOW = load ON, Pin 9 HIGH = load OFF
void setup() { pinMode(9, OUTPUT); }
void loop() {
digitalWrite(9, LOW); delay(2000); // ON
digitalWrite(9, HIGH); delay(2000); // OFF
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'rb', x: 380, y: 100, properties: { value: '1000' } },
{ type: 'wokwi-resistor', id: 'rl', x: 520, y: 200, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'led1', x: 520, y: 280, properties: { color: 'red' } },
{ type: 'wokwi-bjt-2n3906', id: 'q1', x: 420, y: 160, properties: {} },
],
wires: [
// Pin 9 → Rb → Base (LOW = ON for PNP)
w('w1', ['arduino-uno', '9'], ['rb', '1']),
w('w2', ['rb', '2'], ['q1', 'B']),
// Emitter to 5V (high-side)
w('w3', ['q1', 'E'], ['arduino-uno', '5V'], '#ff0000'),
// Collector → Rl → LED → GND
w('w4', ['q1', 'C'], ['rl', '1']),
w('w5', ['rl', '2'], ['led1', 'A']),
w('w6', ['led1', 'C'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'mosfet-pwm-led',
title: 'MOSFET PWM LED Dimmer',
description: '2N7000 N-MOSFET as low-side switch. Gate driven by PWM on pin 9 dims the LED.',
category: 'circuits',
difficulty: 'intermediate',
code: `// MOSFET PWM LED dimmer
void setup() { pinMode(9, OUTPUT); }
void loop() {
for(int b=0; b<=255; b+=5) { analogWrite(9, b); delay(30); }
for(int b=255; b>=0; b-=5) { analogWrite(9, b); delay(30); }
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'rl', x: 420, y: 60, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'led1', x: 420, y: 160, properties: { color: 'white' } },
{ type: 'wokwi-mosfet-2n7000', id: 'q1', x: 420, y: 260, properties: {} },
// Gate pull-down keeps the MOSFET off when the GPIO is high-impedance
// (e.g. before setup() runs) — avoids ghost glow during boot.
{ type: 'wokwi-resistor', id: 'rg', x: 320, y: 290, properties: { value: '100000' } },
],
wires: [
// LED: 5V → R → LED anode → cathode → MOSFET drain
w('w1', ['arduino-uno', '5V'], ['rl', '1'], '#ff0000'),
w('w2', ['rl', '2'], ['led1', 'A']),
w('w3', ['led1', 'C'], ['q1', 'D']),
// Source to GND (low-side switch)
w('w4', ['q1', 'S'], ['arduino-uno', 'GND'], '#000000'),
// PWM gate drive from pin 9, plus pull-down to GND
w('w5', ['arduino-uno', '9'], ['q1', 'G'], '#ffaa00'),
w('w6', ['q1', 'G'], ['rg', '1']),
w('w7', ['rg', '2'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'diode-rectifier',
title: 'Half-Wave Rectifier',
description: 'Diode passes only positive half-cycles. Read rectified output on ADC.',
category: 'circuits',
difficulty: 'intermediate',
code: `// Half-wave rectifier — observe on Serial plotter
void setup() { Serial.begin(115200); }
void loop() {
int raw = analogRead(A0);
Serial.println(raw);
delay(5);
}`,
components: [
UNO,
{
type: 'wokwi-signal-generator',
id: 'sg1',
x: 300,
y: 200,
properties: { waveform: 'sine', frequency: 50, amplitude: 5, offset: 0 },
},
{ type: 'wokwi-diode-1n4007', id: 'd1', x: 400, y: 200, properties: {} },
{ type: 'wokwi-resistor', id: 'rl', x: 500, y: 200, properties: { value: '1000' } },
],
wires: [
// SG out → diode anode → cathode → Rl → GND
w('w1', ['sg1', 'SIG'], ['d1', 'A']),
w('w2', ['d1', 'C'], ['rl', '1']),
w('w3', ['rl', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w4', ['sg1', 'GND'], ['arduino-uno', 'GND'], '#000000'),
// A0 probes the rectified output
w('w5', ['d1', 'C'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
{
id: 'zener-regulator',
title: 'Zener Voltage Regulator',
description: '5.1V Zener clamps output. Even if input varies, output stays at 5.1V.',
category: 'circuits',
difficulty: 'intermediate',
code: `// Zener 5.1V regulator
// Input = 9V battery, Rs = 220 ohm, Zener clamps to 5.1V
void setup() { Serial.begin(9600); }
void loop() {
float v = analogRead(A0) * 5.0 / 1023.0;
Serial.print("V_regulated = "); Serial.println(v, 2);
delay(500);
}`,
components: [
UNO,
{ type: 'wokwi-battery-9v', id: 'bat', x: 260, y: 160, properties: {} },
{ type: 'wokwi-resistor', id: 'rs', x: 380, y: 100, properties: { value: '220' } },
{ type: 'wokwi-zener-1n4733', id: 'z1', x: 480, y: 180, properties: {} },
],
wires: [
// 9V battery → Rs → Zener cathode (regulated node → A0)
w('w1', ['bat', '+'], ['rs', '1'], '#ff0000'),
w('w2', ['rs', '2'], ['z1', 'C']),
w('w3', ['z1', 'C'], ['arduino-uno', 'A0'], '#ffaa00'),
// Zener anode and battery minus → GND
w('w4', ['z1', 'A'], ['arduino-uno', 'GND'], '#000000'),
w('w5', ['bat', ''], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'schottky-reverse-protection',
title: 'Reverse Polarity Protection',
description: 'Schottky diode protects circuit from accidental reverse battery connection.',
category: 'circuits',
difficulty: 'beginner',
code: `// Schottky reverse-polarity protection
// 1N5817: low Vf = 0.3V, minimal power loss
void setup() { Serial.begin(9600); }
void loop() {
Serial.println("Protected circuit running...");
delay(1000);
}`,
components: [
UNO,
{ type: 'wokwi-battery-9v', id: 'bat', x: 260, y: 180, properties: {} },
{ type: 'wokwi-diode-1n5817', id: 'd1', x: 380, y: 140, properties: {} },
{ type: 'wokwi-resistor', id: 'rl', x: 500, y: 140, properties: { value: '1000' } },
],
wires: [
// Battery + → Schottky anode → cathode → load R → GND (battery )
w('w1', ['bat', '+'], ['d1', 'A'], '#ff0000'),
w('w2', ['d1', 'C'], ['rl', '1']),
w('w3', ['rl', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w4', ['bat', ''], ['arduino-uno', 'GND'], '#000000'),
// Probe the protected rail
w('w5', ['d1', 'C'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
{
id: 'bjt-common-emitter',
title: 'Common-Emitter Amplifier',
description: 'NPN BJT amplifies a small AC signal. Gain = -Rc/Re.',
category: 'circuits',
difficulty: 'advanced',
code: `// Common-emitter amplifier
// Biased at Vcc/2, gain ~ -Rc/Re = -4.7
void setup() { Serial.begin(115200); }
void loop() {
int raw = analogRead(A0);
Serial.println(raw);
delay(1);
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'rb1', x: 350, y: 60, properties: { value: '47000' } },
{ type: 'wokwi-resistor', id: 'rb2', x: 350, y: 180, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'rc', x: 450, y: 60, properties: { value: '4700' } },
{ type: 'wokwi-resistor', id: 're', x: 450, y: 280, properties: { value: '1000' } },
{ type: 'wokwi-bjt-2n2222', id: 'q1', x: 450, y: 170, properties: {} },
{
type: 'wokwi-signal-generator',
id: 'sg1',
x: 240,
y: 140,
properties: { waveform: 'sine', frequency: 1000, amplitude: 0.05, offset: 0 },
},
// Small "coupling" resistor from SG to the base node so SG can wiggle
// the biased base without DC-shifting it.
{ type: 'wokwi-resistor', id: 'rin', x: 300, y: 140, properties: { value: '10000' } },
],
wires: [
// Bias divider: 5V → Rb1 → (base) → Rb2 → GND
w('w1', ['arduino-uno', '5V'], ['rb1', '1'], '#ff0000'),
w('w2', ['rb1', '2'], ['q1', 'B']),
w('w3', ['q1', 'B'], ['rb2', '1']),
w('w4', ['rb2', '2'], ['arduino-uno', 'GND'], '#000000'),
// Collector: 5V → Rc → collector
w('w5', ['arduino-uno', '5V'], ['rc', '1'], '#ff0000'),
w('w6', ['rc', '2'], ['q1', 'C']),
// Emitter → Re → GND
w('w7', ['q1', 'E'], ['re', '1']),
w('w8', ['re', '2'], ['arduino-uno', 'GND'], '#000000'),
// AC input into base through coupling R
w('w9', ['sg1', 'SIG'], ['rin', '1']),
w('w10', ['rin', '2'], ['q1', 'B']),
w('w11', ['sg1', 'GND'], ['arduino-uno', 'GND'], '#000000'),
// A0 probes the collector
w('w12', ['q1', 'C'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
{
id: 'darlington-high-current',
title: 'Darlington Pair (High Current)',
description:
'Two NPN BJTs cascaded for beta-squared current gain. Drives heavy loads from MCU.',
category: 'circuits',
difficulty: 'advanced',
code: `// Darlington pair — beta-squared gain drives LED from tiny base current.
// Fade in/out so you can SEE the Darlington proportionally amplifying.
void setup() { pinMode(9, OUTPUT); }
void loop() {
for (int d = 0; d <= 255; d += 5) { analogWrite(9, d); delay(15); }
for (int d = 255; d >= 0; d -= 5) { analogWrite(9, d); delay(15); }
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'rb', x: 340, y: 140, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'rl', x: 520, y: 40, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'led1', x: 520, y: 120, properties: { color: 'red' } },
{ type: 'wokwi-bjt-2n2222', id: 'q1', x: 440, y: 200, properties: {} },
{ type: 'wokwi-bjt-2n2222', id: 'q2', x: 520, y: 280, properties: {} },
],
wires: [
// Pin 9 → Rb → Q1 base
w('w1', ['arduino-uno', '9'], ['rb', '1']),
w('w2', ['rb', '2'], ['q1', 'B']),
// Q1 emitter drives Q2 base (darlington pair)
w('w3', ['q1', 'E'], ['q2', 'B']),
// Collectors tied together — common collector node
w('w4', ['q1', 'C'], ['q2', 'C']),
// High-side load: 5V → Rl → LED anode, LED cathode → common collector
w('w5', ['arduino-uno', '5V'], ['rl', '1'], '#ff0000'),
w('w6', ['rl', '2'], ['led1', 'A']),
w('w7', ['led1', 'C'], ['q1', 'C']),
// Q2 emitter → GND
w('w8', ['q2', 'E'], ['arduino-uno', 'GND'], '#000000'),
],
},
// ════════════════════════════════════════════════════════════════════════════
// OP-AMP (5 examples)
// ════════════════════════════════════════════════════════════════════════════
{
id: 'opamp-inverting',
title: 'Inverting Amplifier (LM358)',
description: 'Vout = -(Rf/Rin) * Vin. Gain=-10 with Rin=1k, Rf=10k.',
category: 'circuits',
difficulty: 'intermediate',
code: `// Inverting amplifier — gain = -Rf/Rin = -10
void setup() { Serial.begin(9600); }
void loop() {
float vin = analogRead(A0) * 5.0 / 1023.0;
float vout = analogRead(A1) * 5.0 / 1023.0;
Serial.print("Vin="); Serial.print(vin,2);
Serial.print(" Vout="); Serial.println(vout,2);
delay(500);
}`,
components: [
UNO,
{ type: 'wokwi-potentiometer', id: 'pot', x: 260, y: 160, properties: {} },
{ type: 'wokwi-resistor', id: 'rin', x: 350, y: 100, properties: { value: '1000' } },
{ type: 'wokwi-resistor', id: 'rf', x: 450, y: 100, properties: { value: '10000' } },
// IN+ bias divider — two 10k from 5V / GND keep IN+ at 2.5V
{ type: 'wokwi-resistor', id: 'rbp1', x: 350, y: 240, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'rbp2', x: 350, y: 320, properties: { value: '10000' } },
{ type: 'wokwi-opamp-lm358', id: 'u1', x: 460, y: 200, properties: {} },
],
wires: [
// Pot → Vin (A0 probes the input)
w('w1', ['arduino-uno', '5V'], ['pot', 'VCC'], '#ff0000'),
w('w2', ['pot', 'GND'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['pot', 'SIG'], ['arduino-uno', 'A0'], '#ffaa00'),
// Vin → Rin → IN-
w('w4', ['pot', 'SIG'], ['rin', '1']),
w('w5', ['rin', '2'], ['u1', 'IN-']),
// Feedback Rf from OUT → IN-
w('w6', ['u1', 'OUT'], ['rf', '1']),
w('w7', ['rf', '2'], ['u1', 'IN-']),
// IN+ biased at Vcc/2
w('w8', ['arduino-uno', '5V'], ['rbp1', '1'], '#ff0000'),
w('w9', ['rbp1', '2'], ['u1', 'IN+']),
w('w10', ['u1', 'IN+'], ['rbp2', '1']),
w('w11', ['rbp2', '2'], ['arduino-uno', 'GND'], '#000000'),
// A1 probes the output
w('w12', ['u1', 'OUT'], ['arduino-uno', 'A1'], '#ffaa00'),
],
},
{
id: 'opamp-voltage-follower',
title: 'Voltage Follower (Buffer)',
description: 'Op-amp with 100% feedback. Vout = Vin. High Z input, low Z output.',
category: 'circuits',
difficulty: 'beginner',
code: `// Voltage follower — Vout tracks Vin exactly
void setup() { Serial.begin(9600); }
void loop() {
float vin = analogRead(A0) * 5.0 / 1023.0;
float vout = analogRead(A1) * 5.0 / 1023.0;
Serial.print("Vin="); Serial.print(vin,3);
Serial.print(" Vout="); Serial.println(vout,3);
delay(500);
}`,
components: [
UNO,
{ type: 'wokwi-potentiometer', id: 'pot', x: 350, y: 160, properties: {} },
{ type: 'wokwi-opamp-lm358', id: 'u1', x: 470, y: 160, properties: {} },
],
wires: [
w('w1', ['arduino-uno', '5V'], ['pot', 'VCC'], '#ff0000'),
w('w2', ['pot', 'GND'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['pot', 'SIG'], ['arduino-uno', 'A0'], '#ffaa00'),
// Pot → IN+, OUT tied directly to IN- (100% negative feedback → buffer)
w('w4', ['pot', 'SIG'], ['u1', 'IN+']),
w('w5', ['u1', 'OUT'], ['u1', 'IN-']),
w('w6', ['u1', 'OUT'], ['arduino-uno', 'A1'], '#ffaa00'),
],
},
{
id: 'opamp-comparator',
title: 'Comparator with LED',
description: 'Op-amp compares pot voltage vs 2.5V reference. LED indicates which is higher.',
category: 'circuits',
difficulty: 'intermediate',
code: `// Comparator — LED lights when pot > 2.5V
void setup() { Serial.begin(9600); }
void loop() {
float vpot = analogRead(A0) * 5.0 / 1023.0;
Serial.print("Pot = "); Serial.print(vpot,2);
Serial.println(vpot > 2.5 ? " > ref -> LED ON" : " < ref -> LED OFF");
delay(300);
}`,
components: [
UNO,
{ type: 'wokwi-potentiometer', id: 'pot', x: 280, y: 120, properties: {} },
// Vref = 2.5V from two 10k from 5V/GND
{ type: 'wokwi-resistor', id: 'rref1', x: 280, y: 240, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'rref2', x: 280, y: 320, properties: { value: '10000' } },
{ type: 'wokwi-opamp-lm358', id: 'u1', x: 400, y: 160, properties: {} },
{ type: 'wokwi-resistor', id: 'rl', x: 520, y: 80, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'led1', x: 520, y: 200, properties: { color: 'green' } },
],
wires: [
// Pot on IN+
w('w1', ['arduino-uno', '5V'], ['pot', 'VCC'], '#ff0000'),
w('w2', ['pot', 'GND'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['pot', 'SIG'], ['u1', 'IN+']),
w('w4', ['pot', 'SIG'], ['arduino-uno', 'A0'], '#ffaa00'),
// 2.5V reference on IN-
w('w5', ['arduino-uno', '5V'], ['rref1', '1'], '#ff0000'),
w('w6', ['rref1', '2'], ['u1', 'IN-']),
w('w7', ['u1', 'IN-'], ['rref2', '1']),
w('w8', ['rref2', '2'], ['arduino-uno', 'GND'], '#000000'),
// OUT → Rl → LED → GND
w('w9', ['u1', 'OUT'], ['rl', '1']),
w('w10', ['rl', '2'], ['led1', 'A']),
w('w11', ['led1', 'C'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'opamp-difference',
title: 'Difference Amplifier',
description: 'Vout = Gain * (V2 - V1). Useful for bridge sensors and differential signals.',
category: 'circuits',
difficulty: 'advanced',
code: `// Difference amplifier — Gain=10, Vout = 10*(V2-V1)
void setup() { Serial.begin(9600); }
void loop() {
float v1 = analogRead(A0) * 5.0 / 1023.0;
float v2 = analogRead(A1) * 5.0 / 1023.0;
float vout = analogRead(A2) * 5.0 / 1023.0;
Serial.print("V1="); Serial.print(v1,2);
Serial.print(" V2="); Serial.print(v2,2);
Serial.print(" Vout="); Serial.println(vout,2);
delay(500);
}`,
components: [
UNO,
// V1 → R1 → IN-, feedback Rf from OUT
{ type: 'wokwi-resistor', id: 'r1', x: 350, y: 80, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'rf', x: 350, y: 160, properties: { value: '100000' } },
// V2 → R2 → IN+, Rg from IN+ to GND
{ type: 'wokwi-resistor', id: 'r2', x: 350, y: 240, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'rg', x: 350, y: 320, properties: { value: '100000' } },
{ type: 'wokwi-opamp-lm358', id: 'u1', x: 460, y: 160, properties: {} },
// Two bias pots to generate V1 and V2 (so the example has real inputs)
{ type: 'wokwi-potentiometer', id: 'pot1', x: 240, y: 80, properties: {} },
{ type: 'wokwi-potentiometer', id: 'pot2', x: 240, y: 240, properties: {} },
],
wires: [
// Pot1 provides V1
w('w1', ['arduino-uno', '5V'], ['pot1', 'VCC'], '#ff0000'),
w('w2', ['pot1', 'GND'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['pot1', 'SIG'], ['arduino-uno', 'A0'], '#ffaa00'),
// Pot2 provides V2
w('w4', ['arduino-uno', '5V'], ['pot2', 'VCC'], '#ff0000'),
w('w5', ['pot2', 'GND'], ['arduino-uno', 'GND'], '#000000'),
w('w6', ['pot2', 'SIG'], ['arduino-uno', 'A1'], '#ffaa00'),
// V1 → R1 → IN-
w('w7', ['pot1', 'SIG'], ['r1', '1']),
w('w8', ['r1', '2'], ['u1', 'IN-']),
// Rf from OUT to IN-
w('w9', ['u1', 'OUT'], ['rf', '1']),
w('w10', ['rf', '2'], ['u1', 'IN-']),
// V2 → R2 → IN+
w('w11', ['pot2', 'SIG'], ['r2', '1']),
w('w12', ['r2', '2'], ['u1', 'IN+']),
// Rg from IN+ to GND
w('w13', ['u1', 'IN+'], ['rg', '1']),
w('w14', ['rg', '2'], ['arduino-uno', 'GND'], '#000000'),
// A2 probes OUT
w('w15', ['u1', 'OUT'], ['arduino-uno', 'A2'], '#ffaa00'),
],
},
{
id: 'opamp-schmitt-trigger',
title: 'Schmitt Trigger',
description: 'Op-amp with positive feedback creates hysteresis. Cleans up noisy signals.',
category: 'circuits',
difficulty: 'advanced',
code: `// Schmitt trigger — cleans noisy input
void setup() { Serial.begin(9600); }
void loop() {
int raw = analogRead(A0);
int out = analogRead(A1);
Serial.print(raw); Serial.print(","); Serial.println(out);
delay(10);
}`,
components: [
UNO,
{ type: 'wokwi-potentiometer', id: 'pot', x: 260, y: 160, properties: {} },
// Vref = 2.5V divider on IN+
{ type: 'wokwi-resistor', id: 'rref1', x: 370, y: 240, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'rref2', x: 370, y: 320, properties: { value: '10000' } },
// Positive feedback network: Rin from Vref to IN+, Rfb from OUT to IN+
{ type: 'wokwi-resistor', id: 'rin', x: 420, y: 100, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'rfb', x: 520, y: 100, properties: { value: '100000' } },
{ type: 'wokwi-opamp-lm358', id: 'u1', x: 460, y: 200, properties: {} },
],
wires: [
// Pot → IN- (inverting input, signal to compare)
w('w1', ['arduino-uno', '5V'], ['pot', 'VCC'], '#ff0000'),
w('w2', ['pot', 'GND'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['pot', 'SIG'], ['u1', 'IN-']),
w('w4', ['pot', 'SIG'], ['arduino-uno', 'A0'], '#ffaa00'),
// Vref divider to Rin node (2.5V reference)
w('w5', ['arduino-uno', '5V'], ['rref1', '1'], '#ff0000'),
w('w6', ['rref1', '2'], ['rin', '1']),
w('w7', ['rin', '1'], ['rref2', '1']),
w('w8', ['rref2', '2'], ['arduino-uno', 'GND'], '#000000'),
// Rin → IN+, and Rfb from OUT → IN+ (positive feedback → hysteresis)
w('w9', ['rin', '2'], ['u1', 'IN+']),
w('w10', ['u1', 'OUT'], ['rfb', '1']),
w('w11', ['rfb', '2'], ['u1', 'IN+']),
// A1 probes OUT
w('w12', ['u1', 'OUT'], ['arduino-uno', 'A1'], '#ffaa00'),
],
},
// ════════════════════════════════════════════════════════════════════════════
// LOGIC GATES (6 examples)
// ════════════════════════════════════════════════════════════════════════════
{
id: 'mixed-and-transistor-driver',
title: 'Mixed: MCU + AND gate + transistor (coexistence test)',
description:
'Coexistence of digital and analog in ONE circuit: the Arduino drives two ' +
'logic levels (one steady HIGH "enable", one blinking), a physical AND gate ' +
'combines them, and the AND output switches an NPN transistor that drives the ' +
'"motor" LED. The LED should blink — proving MCU -> logic gate -> transistor ' +
'-> load works through the digital and analog (ngspice) motors together.',
category: 'circuits',
difficulty: 'intermediate',
code: `// MCU + AND gate + transistor coexistence.
// pin 5 = steady enable, pin 6 = blink. AND(5,6) -> transistor -> motor LED.
void setup() { pinMode(5, OUTPUT); pinMode(6, OUTPUT); }
void loop() {
digitalWrite(5, HIGH); // enable
digitalWrite(6, (millis() / 500) & 1); // ~1 Hz blink
}`,
components: [
UNO,
{ type: 'velxio-logic-gate-and', id: 'u1', x: 360, y: 120, properties: {} },
{ type: 'wokwi-resistor', id: 'rb', x: 480, y: 130, properties: { value: '1000' } },
{ type: 'wokwi-bjt-2n2222', id: 'q1', x: 580, y: 160, properties: {} },
{ type: 'wokwi-resistor', id: 'rl', x: 560, y: 40, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'motor', x: 560, y: 100, properties: { color: 'green' } },
],
wires: [
// MCU drives the two AND inputs
w('w1', ['arduino-uno', '5'], ['u1', 'A']),
w('w2', ['arduino-uno', '6'], ['u1', 'B']),
// AND output -> base resistor -> transistor base
w('w3', ['u1', 'Y'], ['rb', '1']),
w('w4', ['rb', '2'], ['q1', 'B']),
// Load: 5V -> Rl -> LED -> collector ; emitter -> GND
w('w5', ['arduino-uno', '5V'], ['rl', '1'], '#ff3030'),
w('w6', ['rl', '2'], ['motor', 'A']),
w('w7', ['motor', 'C'], ['q1', 'C']),
w('w8', ['q1', 'E'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'and-gate-alarm',
title: 'AND Gate Alarm',
description:
'Two arming switches feed an AND gate — the alarm LED lights ONLY when BOTH ' +
'are ON (e.g. both doors closed). They are slide switches, so they latch: ' +
'slide each one ON and it stays, so you can hold both at once. Pure logic, ' +
'no MCU — runs on the digital gate engine.',
category: 'circuits',
difficulty: 'beginner',
boardFilter: 'digital',
code: `// Pure digital circuit — no MCU. Slide BOTH switches ON to arm the alarm.
void setup() {}
void loop() {}`,
components: [
{ type: 'wokwi-signal-generator', id: 'src', x: 40, y: 200, properties: { waveform: 'dc', offset: 5, amplitude: 0, frequency: 1 } },
{ type: 'wokwi-slide-switch', id: 'sw1', x: 220, y: 90, properties: { value: 0 } },
{ type: 'wokwi-slide-switch', id: 'sw2', x: 220, y: 250, properties: { value: 0 } },
{ type: 'wokwi-resistor', id: 'rpd1', x: 340, y: 140, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'rpd2', x: 340, y: 300, properties: { value: '10000' } },
{ type: 'velxio-logic-gate-and', id: 'u1', x: 470, y: 170, properties: {} },
{ type: 'wokwi-resistor', id: 'rl', x: 620, y: 130, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'led1', x: 620, y: 220, properties: { color: 'red' } },
],
wires: [
// Switch 1 → AND input A (slide ON = rail HIGH; pull-down holds it LOW when OFF)
w('w1', ['src', 'SIG'], ['sw1', '1'], '#ff3030'),
w('w2', ['sw1', '2'], ['u1', 'A']),
w('w3', ['sw1', '2'], ['rpd1', '1']),
w('w4', ['rpd1', '2'], ['src', 'GND'], '#000000'),
// Switch 2 → AND input B
w('w5', ['src', 'SIG'], ['sw2', '1'], '#ff3030'),
w('w6', ['sw2', '2'], ['u1', 'B']),
w('w7', ['sw2', '2'], ['rpd2', '1']),
w('w8', ['rpd2', '2'], ['src', 'GND'], '#000000'),
// AND output → series resistor → alarm LED → GND
w('w9', ['u1', 'Y'], ['rl', '1']),
w('w10', ['rl', '2'], ['led1', 'A']),
w('w11', ['led1', 'C'], ['src', 'GND'], '#000000'),
],
},
{
id: 'xor-toggle-detector',
title: 'XOR Toggle Detector',
description: 'XOR gate detects when two switches are in different positions.',
category: 'circuits',
difficulty: 'beginner',
code: `// XOR — LED on when switches differ (physical XOR gate drives LED)
void setup() {
pinMode(2, INPUT_PULLUP); pinMode(3, INPUT_PULLUP);
pinMode(5, OUTPUT); pinMode(6, OUTPUT);
}
void loop() {
digitalWrite(5, !digitalRead(2));
digitalWrite(6, !digitalRead(3));
}`,
components: [
UNO,
{ type: 'wokwi-pushbutton', id: 'sw1', x: 260, y: 80, properties: {} },
{ type: 'wokwi-pushbutton', id: 'sw2', x: 260, y: 180, properties: {} },
{ type: 'velxio-logic-gate-xor', id: 'u1', x: 400, y: 130, properties: {} },
{ type: 'wokwi-resistor', id: 'rl', x: 520, y: 60, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'led1', x: 520, y: 160, properties: { color: 'yellow' } },
],
wires: [
w('w1', ['arduino-uno', '2'], ['sw1', '1.l']),
w('w2', ['sw1', '2.l'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['arduino-uno', '3'], ['sw2', '1.l']),
w('w4', ['sw2', '2.l'], ['arduino-uno', 'GND'], '#000000'),
// MCU → XOR inputs
w('w5', ['arduino-uno', '5'], ['u1', 'A']),
w('w6', ['arduino-uno', '6'], ['u1', 'B']),
// XOR Y → LED
w('w7', ['u1', 'Y'], ['rl', '1']),
w('w8', ['rl', '2'], ['led1', 'A']),
w('w9', ['led1', 'C'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'nand-sr-latch',
title: 'NAND SR Latch',
description: 'Two cross-coupled NAND gates form a Set-Reset latch. Memory without a clock!',
category: 'circuits',
difficulty: 'intermediate',
code: `// Software NAND SR latch simulation
bool q = false;
void setup() { Serial.begin(9600); pinMode(2,INPUT_PULLUP); pinMode(3,INPUT_PULLUP); pinMode(13,OUTPUT); }
void loop() {
bool s = !digitalRead(2), r = !digitalRead(3);
if(s && !r) q = true;
if(r && !s) q = false;
digitalWrite(13, q);
Serial.print("S="); Serial.print(s); Serial.print(" R="); Serial.print(r);
Serial.print(" Q="); Serial.println(q);
delay(200);
}`,
components: [
UNO,
{ type: 'wokwi-pushbutton', id: 'setBtn', x: 260, y: 80, properties: {} },
{ type: 'wokwi-pushbutton', id: 'rstBtn', x: 260, y: 240, properties: {} },
// Pull-ups so S' and R' rest HIGH; pressing a button pulls LOW
{ type: 'wokwi-resistor', id: 'rpuS', x: 320, y: 40, properties: { value: '10000' } },
{ type: 'wokwi-resistor', id: 'rpuR', x: 320, y: 280, properties: { value: '10000' } },
// Cross-coupled NANDs
{ type: 'velxio-logic-gate-nand', id: 'g1', x: 420, y: 100, properties: {} },
{ type: 'velxio-logic-gate-nand', id: 'g2', x: 420, y: 220, properties: {} },
{ type: 'wokwi-resistor', id: 'rl', x: 540, y: 60, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'qled', x: 540, y: 160, properties: { color: 'green' } },
],
wires: [
// S' / R' pull-ups to 5V
w('w1', ['arduino-uno', '5V'], ['rpuS', '1'], '#ff0000'),
w('w2', ['rpuS', '2'], ['setBtn', '1.l']),
w('w3', ['setBtn', '2.l'], ['arduino-uno', 'GND'], '#000000'),
w('w4', ['arduino-uno', '5V'], ['rpuR', '1'], '#ff0000'),
w('w5', ['rpuR', '2'], ['rstBtn', '1.l']),
w('w6', ['rstBtn', '2.l'], ['arduino-uno', 'GND'], '#000000'),
// MCU can also read S' and R' (pin 2 / 3)
w('w7', ['rpuS', '2'], ['arduino-uno', '2'], '#ffaa00'),
w('w8', ['rpuR', '2'], ['arduino-uno', '3'], '#ffaa00'),
// NAND1: inputs S' + Q', output Q
w('w9', ['rpuS', '2'], ['g1', 'A']),
// NAND2: inputs R' + Q, output Q'
w('w10', ['rpuR', '2'], ['g2', 'A']),
// Cross-couple
w('w11', ['g1', 'Y'], ['g2', 'B']),
w('w12', ['g2', 'Y'], ['g1', 'B']),
// Q → LED
w('w13', ['g1', 'Y'], ['rl', '1']),
w('w14', ['rl', '2'], ['qled', 'A']),
w('w15', ['qled', 'C'], ['arduino-uno', 'GND'], '#000000'),
// Also route Q to Arduino pin 13 (software mirror)
w('w16', ['g1', 'Y'], ['arduino-uno', '13'], '#ffaa00'),
],
},
{
id: 'full-adder',
title: 'Full Adder (1-bit)',
description: 'Sum = A XOR B XOR Cin, Cout = (A AND B) OR (Cin AND (A XOR B)).',
category: 'circuits',
difficulty: 'intermediate',
code: `// 1-bit full adder in software
void setup() {
Serial.begin(9600);
pinMode(2,INPUT_PULLUP); pinMode(3,INPUT_PULLUP); pinMode(4,INPUT_PULLUP);
pinMode(5,OUTPUT); pinMode(6,OUTPUT);
}
void loop() {
bool a=!digitalRead(2), b=!digitalRead(3), cin=!digitalRead(4);
bool sum = a ^ b ^ cin;
bool cout = (a&b) | (cin&(a^b));
digitalWrite(5, sum);
digitalWrite(6, cout);
Serial.print("A="); Serial.print(a); Serial.print(" B="); Serial.print(b);
Serial.print(" Cin="); Serial.print(cin); Serial.print(" Sum="); Serial.print(sum);
Serial.print(" Cout="); Serial.println(cout);
delay(300);
}`,
components: [
UNO,
{ type: 'wokwi-pushbutton', id: 'bA', x: 350, y: 60, properties: {} },
{ type: 'wokwi-pushbutton', id: 'bB', x: 350, y: 140, properties: {} },
{ type: 'wokwi-pushbutton', id: 'bCin', x: 350, y: 220, properties: {} },
{ type: 'wokwi-resistor', id: 'rSum', x: 440, y: 100, properties: { value: '220' } },
{ type: 'wokwi-resistor', id: 'rCout', x: 440, y: 200, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'sumLed', x: 540, y: 100, properties: { color: 'green' } },
{ type: 'wokwi-led', id: 'coutLed', x: 540, y: 200, properties: { color: 'red' } },
],
wires: [
w('w1', ['arduino-uno', '2'], ['bA', '1.l']),
w('w2', ['bA', '2.l'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['arduino-uno', '3'], ['bB', '1.l']),
w('w4', ['bB', '2.l'], ['arduino-uno', 'GND'], '#000000'),
w('w5', ['arduino-uno', '4'], ['bCin', '1.l']),
w('w6', ['bCin', '2.l'], ['arduino-uno', 'GND'], '#000000'),
// Sum LED: pin 5 → 220Ω → LED → GND
w('w7', ['arduino-uno', '5'], ['rSum', '1']),
w('w8', ['rSum', '2'], ['sumLed', 'A']),
w('w9', ['sumLed', 'C'], ['arduino-uno', 'GND'], '#000000'),
// Cout LED: pin 6 → 220Ω → LED → GND
w('w10', ['arduino-uno', '6'], ['rCout', '1']),
w('w11', ['rCout', '2'], ['coutLed', 'A']),
w('w12', ['coutLed', 'C'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'binary-counter-leds',
title: '4-bit Binary Counter',
description: 'Count from 0 to 15 displayed on 4 LEDs. Each LED = one bit.',
category: 'circuits',
difficulty: 'beginner',
code: `// 4-bit binary counter on LEDs
int count = 0;
void setup() { for(int i=2;i<=5;i++) pinMode(i,OUTPUT); }
void loop() {
for(int i=0;i<4;i++) digitalWrite(i+2, (count>>i)&1);
count = (count+1) % 16;
delay(500);
}`,
components: [
UNO,
...Array.from({ length: 4 }, (_, i) => ({
type: 'wokwi-resistor',
id: `r${i}`,
x: 380,
y: 60 + i * 60,
properties: { value: '220' },
})),
...Array.from({ length: 4 }, (_, i) => ({
type: 'wokwi-led',
id: `led${i}`,
x: 460,
y: 60 + i * 60,
properties: { color: ['red', 'yellow', 'green', 'blue'][i] },
})),
],
wires: [
...Array.from({ length: 4 }, (_, i) =>
w(`wa${i}`, ['arduino-uno', `${i + 2}`], [`r${i}`, '1']),
),
...Array.from({ length: 4 }, (_, i) => w(`wb${i}`, [`r${i}`, '2'], [`led${i}`, 'A'])),
...Array.from({ length: 4 }, (_, i) =>
w(`wc${i}`, [`led${i}`, 'C'], ['arduino-uno', 'GND'], '#000000'),
),
],
},
{
id: 'logic-probe',
title: 'Logic Probe (HIGH/LOW/FLOATING)',
description:
'Read any digital pin state and show on 3 LEDs: green=HIGH, red=LOW, yellow=floating.',
category: 'circuits',
difficulty: 'intermediate',
code: `// Logic probe — tests pin 7
void setup() {
pinMode(10,OUTPUT); pinMode(11,OUTPUT); pinMode(12,OUTPUT); // R,Y,G
pinMode(7,INPUT);
Serial.begin(9600);
}
void loop() {
int val = digitalRead(7);
digitalWrite(12, val == HIGH); // Green = HIGH
digitalWrite(10, val == LOW); // Red = LOW
Serial.println(val ? "HIGH" : "LOW");
delay(200);
}`,
components: [
UNO,
{ type: 'wokwi-led', id: 'gLed', x: 400, y: 60, properties: { color: 'green' } },
{ type: 'wokwi-led', id: 'rLed', x: 400, y: 140, properties: { color: 'red' } },
{ type: 'wokwi-resistor', id: 'rg', x: 400, y: 10, properties: { value: '220' } },
{ type: 'wokwi-resistor', id: 'rr', x: 400, y: 90, properties: { value: '220' } },
],
wires: [
w('w1', ['arduino-uno', '12'], ['rg', '1']),
w('w2', ['rg', '2'], ['gLed', 'A']),
w('w3', ['gLed', 'C'], ['arduino-uno', 'GND'], '#000000'),
w('w4', ['arduino-uno', '10'], ['rr', '1']),
w('w5', ['rr', '2'], ['rLed', 'A']),
w('w6', ['rLed', 'C'], ['arduino-uno', 'GND'], '#000000'),
],
},
// ════════════════════════════════════════════════════════════════════════════
// ELECTROMECHANICAL (4 examples)
// ════════════════════════════════════════════════════════════════════════════
{
id: 'relay-led-switch',
title: 'Relay-Controlled LED',
description:
'NPN transistor drives a relay. Relay switches an LED connected to a separate supply.',
category: 'circuits',
difficulty: 'intermediate',
code: `// Relay control via NPN transistor
void setup() { pinMode(9, OUTPUT); }
void loop() {
digitalWrite(9, HIGH); delay(2000); // relay ON
digitalWrite(9, LOW); delay(2000); // relay OFF
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'rb', x: 340, y: 140, properties: { value: '1000' } },
{ type: 'wokwi-bjt-2n2222', id: 'q1', x: 420, y: 200, properties: {} },
{ type: 'velxio-relay', id: 'rly', x: 520, y: 140, properties: { coil_voltage: 5 } },
{ type: 'wokwi-resistor', id: 'rl', x: 640, y: 60, properties: { value: '220' } },
{ type: 'wokwi-led', id: 'led1', x: 640, y: 160, properties: { color: 'red' } },
],
wires: [
// Pin 9 → Rb → Q1 base (NPN low-side driver for the relay coil)
w('w1', ['arduino-uno', '9'], ['rb', '1']),
w('w2', ['rb', '2'], ['q1', 'B']),
// 5V → relay COIL+ ; COIL- → collector ; emitter → GND
w('w3', ['arduino-uno', '5V'], ['rly', 'COIL+'], '#ff0000'),
w('w4', ['rly', 'COIL-'], ['q1', 'C']),
w('w5', ['q1', 'E'], ['arduino-uno', 'GND'], '#000000'),
// Switched load: COM → Rl → LED → GND, NO → 5V (so pressed NO closes 5V to LED)
w('w6', ['arduino-uno', '5V'], ['rly', 'NO'], '#ff0000'),
w('w7', ['rly', 'COM'], ['rl', '1']),
w('w8', ['rl', '2'], ['led1', 'A']),
w('w9', ['led1', 'C'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'optocoupler-signal',
title: 'Optocoupler Signal Isolation',
description: '4N25 optocoupler isolates MCU from a higher-voltage circuit.',
category: 'circuits',
difficulty: 'intermediate',
code: `// Optocoupler 4N25 — MCU drives LED side, reads phototransistor side
void setup() { pinMode(9,OUTPUT); Serial.begin(9600); }
void loop() {
digitalWrite(9,HIGH); delay(500);
int val = analogRead(A0);
Serial.print("Isolated signal: "); Serial.println(val);
digitalWrite(9,LOW); delay(500);
val = analogRead(A0);
Serial.print("Isolated signal: "); Serial.println(val);
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'rled', x: 340, y: 80, properties: { value: '270' } },
{ type: 'velxio-opto-4n25', id: 'u1', x: 450, y: 120, properties: {} },
{ type: 'wokwi-resistor', id: 'rpull', x: 560, y: 80, properties: { value: '10000' } },
],
wires: [
// Drive side: pin 9 → Rled → LED anode (AN), cathode → GND
w('w1', ['arduino-uno', '9'], ['rled', '1']),
w('w2', ['rled', '2'], ['u1', 'AN']),
w('w3', ['u1', 'CAT'], ['arduino-uno', 'GND'], '#000000'),
// Receive side: 5V → Rpull → collector, emitter → GND; A0 probes collector
w('w4', ['arduino-uno', '5V'], ['rpull', '1'], '#ff0000'),
w('w5', ['rpull', '2'], ['u1', 'COL']),
w('w6', ['u1', 'COL'], ['arduino-uno', 'A0'], '#ffaa00'),
w('w7', ['u1', 'EMIT'], ['arduino-uno', 'GND'], '#000000'),
],
},
{
id: 'l293d-motor-control',
title: 'DC Motor Control (L293D)',
description: 'L293D H-bridge drives a DC motor forward, reverse, and brake.',
category: 'circuits',
difficulty: 'intermediate',
code: `// L293D motor control — forward, reverse, brake
#define EN 9
#define IN1 7
#define IN2 8
void setup() { pinMode(EN,OUTPUT); pinMode(IN1,OUTPUT); pinMode(IN2,OUTPUT); }
void forward() { digitalWrite(IN1,HIGH); digitalWrite(IN2,LOW); analogWrite(EN,200); }
void reverse() { digitalWrite(IN1,LOW); digitalWrite(IN2,HIGH); analogWrite(EN,200); }
void brake() { digitalWrite(IN1,LOW); digitalWrite(IN2,LOW); analogWrite(EN,0); }
void loop() {
forward(); delay(2000);
brake(); delay(500);
reverse(); delay(2000);
brake(); delay(500);
}`,
components: [
UNO,
{ type: 'velxio-motor-driver-l293d', id: 'u1', x: 420, y: 140, properties: {} },
// Simple resistive motor model (5Ω winding)
{ type: 'wokwi-resistor', id: 'rm', x: 560, y: 200, properties: { value: '5' } },
],
wires: [
// Control signals from Arduino
w('w1', ['arduino-uno', '9'], ['u1', 'EN1']),
w('w2', ['arduino-uno', '7'], ['u1', 'IN1']),
w('w3', ['arduino-uno', '8'], ['u1', 'IN2']),
// Logic supply VCC1 = 5V, motor supply VCC2 = 5V (toy example)
w('w4', ['arduino-uno', '5V'], ['u1', 'VCC1'], '#ff0000'),
w('w5', ['arduino-uno', '5V'], ['u1', 'VCC2'], '#ff0000'),
// Shared GND pins
w('w6', ['u1', 'GND.1'], ['arduino-uno', 'GND'], '#000000'),
w('w7', ['u1', 'GND.2'], ['arduino-uno', 'GND'], '#000000'),
// Motor between OUT1 and OUT2
w('w8', ['u1', 'OUT1'], ['rm', '1']),
w('w9', ['u1', 'OUT2'], ['rm', '2']),
],
},
{
id: 'l293d-speed-pwm',
title: 'Motor Speed Control (PWM)',
description: 'Potentiometer controls motor speed via PWM on L293D enable pin.',
category: 'circuits',
difficulty: 'intermediate',
code: `// Motor speed via potentiometer + L293D
#define EN 9
#define IN1 7
#define IN2 8
void setup() { pinMode(EN,OUTPUT); pinMode(IN1,OUTPUT); pinMode(IN2,OUTPUT);
digitalWrite(IN1,HIGH); digitalWrite(IN2,LOW); }
void loop() {
int pot = analogRead(A0);
int speed = map(pot, 0, 1023, 0, 255);
analogWrite(EN, speed);
Serial.print("Speed: "); Serial.println(speed);
delay(100);
}`,
components: [
UNO,
{ type: 'wokwi-potentiometer', id: 'pot', x: 260, y: 200, properties: {} },
{ type: 'velxio-motor-driver-l293d', id: 'u1', x: 420, y: 140, properties: {} },
{ type: 'wokwi-resistor', id: 'rm', x: 560, y: 200, properties: { value: '5' } },
],
wires: [
// Pot → A0
w('w1', ['arduino-uno', '5V'], ['pot', 'VCC'], '#ff0000'),
w('w2', ['pot', 'GND'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['pot', 'SIG'], ['arduino-uno', 'A0'], '#ffaa00'),
// L293D control
w('w4', ['arduino-uno', '9'], ['u1', 'EN1']),
w('w5', ['arduino-uno', '7'], ['u1', 'IN1']),
w('w6', ['arduino-uno', '8'], ['u1', 'IN2']),
// Power rails + GND
w('w7', ['arduino-uno', '5V'], ['u1', 'VCC1'], '#ff0000'),
w('w8', ['arduino-uno', '5V'], ['u1', 'VCC2'], '#ff0000'),
w('w9', ['u1', 'GND.1'], ['arduino-uno', 'GND'], '#000000'),
w('w10', ['u1', 'GND.2'], ['arduino-uno', 'GND'], '#000000'),
// Motor between OUT1 / OUT2
w('w11', ['u1', 'OUT1'], ['rm', '1']),
w('w12', ['u1', 'OUT2'], ['rm', '2']),
],
},
// ════════════════════════════════════════════════════════════════════════════
// POWER / REGULATOR (3 examples)
// ════════════════════════════════════════════════════════════════════════════
{
id: 'power-supply-7805',
title: '7805 Regulated Power Supply',
description: '9V battery → 7805 → stable 5V for the Arduino. Classic linear regulator.',
category: 'circuits',
difficulty: 'beginner',
code: `// 7805 power supply — regulated 5V from 9V battery
// The 7805 provides stable 5V regardless of battery voltage (7-12V range)
void setup() { Serial.begin(9600); }
void loop() {
float v = analogRead(A0) * 5.0 / 1023.0;
Serial.print("Regulated voltage: "); Serial.print(v,2); Serial.println(" V");
delay(1000);
}`,
components: [
UNO,
{ type: 'wokwi-battery-9v', id: 'bat', x: 260, y: 200, properties: {} },
{ type: 'wokwi-reg-7805', id: 'u1', x: 380, y: 160, properties: {} },
{ type: 'wokwi-resistor', id: 'rload', x: 500, y: 160, properties: { value: '1000' } },
],
wires: [
// Battery + → VIN ; battery / GND pin → GND
w('w1', ['bat', '+'], ['u1', 'VIN'], '#ff0000'),
w('w2', ['bat', ''], ['u1', 'GND'], '#000000'),
w('w3', ['u1', 'GND'], ['arduino-uno', 'GND'], '#000000'),
// Regulated output → load → GND, A0 probes
w('w4', ['u1', 'VOUT'], ['rload', '1'], '#ff0000'),
w('w5', ['rload', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w6', ['u1', 'VOUT'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
{
id: 'lm317-adjustable-psu',
title: 'LM317 Adjustable PSU',
description: 'LM317 with R1/R2 divider. Vout = 1.25 * (1 + R2/R1). Set any voltage 1.25-37V.',
category: 'circuits',
difficulty: 'intermediate',
code: `// LM317 adjustable regulator
// R1 = 240, R2 = 720 -> Vout = 1.25 * (1 + 720/240) = 5.0V
void setup() { Serial.begin(9600); }
void loop() {
float v = analogRead(A0) * 5.0 / 1023.0;
Serial.print("LM317 Vout = "); Serial.print(v,2); Serial.println(" V");
delay(500);
}`,
components: [
UNO,
{ type: 'wokwi-battery-9v', id: 'bat', x: 240, y: 220, properties: {} },
{ type: 'wokwi-reg-lm317', id: 'u1', x: 360, y: 140, properties: {} },
// R1 = 240Ω between VOUT and ADJ, R2 = 720Ω between ADJ and GND
// Vout = 1.25 * (1 + R2/R1) = 5.0V
{ type: 'wokwi-resistor', id: 'r1', x: 480, y: 100, properties: { value: '240' } },
{ type: 'wokwi-resistor', id: 'r2', x: 480, y: 200, properties: { value: '720' } },
{ type: 'wokwi-resistor', id: 'rload', x: 600, y: 100, properties: { value: '1000' } },
],
wires: [
// Battery into LM317 VIN
w('w1', ['bat', '+'], ['u1', 'VIN'], '#ff0000'),
w('w2', ['bat', ''], ['arduino-uno', 'GND'], '#000000'),
// VOUT → R1 → ADJ → R2 → GND
w('w3', ['u1', 'VOUT'], ['r1', '1'], '#ff0000'),
w('w4', ['r1', '2'], ['u1', 'ADJ']),
w('w5', ['u1', 'ADJ'], ['r2', '1']),
w('w6', ['r2', '2'], ['arduino-uno', 'GND'], '#000000'),
// Load + ADC probe
w('w7', ['u1', 'VOUT'], ['rload', '1'], '#ff0000'),
w('w8', ['rload', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w9', ['u1', 'VOUT'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
{
id: 'battery-voltage-monitor',
title: 'Battery Voltage Monitor',
description: 'Voltage divider scales 9V battery down to 0-5V range for ADC measurement.',
category: 'circuits',
difficulty: 'beginner',
code: `// Battery voltage monitor
// R1=20k + R2=10k divider: V_adc = V_bat * 10k / 30k
// V_bat = V_adc * 3
void setup() { Serial.begin(9600); }
void loop() {
float vAdc = analogRead(A0) * 5.0 / 1023.0;
float vBat = vAdc * 3.0;
Serial.print("Battery: "); Serial.print(vBat,1); Serial.println(" V");
if(vBat < 7.0) Serial.println("WARNING: Battery low!");
delay(1000);
}`,
components: [
UNO,
{ type: 'wokwi-resistor', id: 'r1', x: 350, y: 80, properties: { value: '20000' } },
{ type: 'wokwi-resistor', id: 'r2', x: 350, y: 200, properties: { value: '10000' } },
],
wires: [
w('w1', ['r1', '2'], ['r2', '1']),
w('w2', ['r2', '2'], ['arduino-uno', 'GND'], '#000000'),
w('w3', ['r1', '2'], ['arduino-uno', 'A0'], '#ffaa00'),
],
},
// ════════════════════════════════════════════════════════════════════════════
// ESP32 / MEGA / NANO (4 board-specific examples)
// ════════════════════════════════════════════════════════════════════════════
{
id: 'esp32-dual-adc',
title: 'ESP32 Dual ADC Reader',
description:
'ESP32 reads two analog channels (GPIO34, GPIO35) simultaneously at 12-bit resolution.',
category: 'circuits',
difficulty: 'beginner',
boardType: 'esp32',
code: `// ESP32 dual ADC — 12-bit, 3.3V reference
void setup() {
Serial.begin(115200);
analogReadResolution(12);
}
void loop() {
int ch1 = analogRead(34);
int ch2 = analogRead(35);
float v1 = ch1 * 3.3 / 4095.0;
float v2 = ch2 * 3.3 / 4095.0;
Serial.printf("CH1=%.3fV CH2=%.3fV\\n", v1, v2);
delay(500);
}`,
components: [
ESP32,
{ type: 'wokwi-potentiometer', id: 'pot1', x: 400, y: 80, properties: {} },
{ type: 'wokwi-potentiometer', id: 'pot2', x: 400, y: 220, properties: {} },
],
wires: [
w('w1', ['esp32', '3V3'], ['pot1', 'VCC'], '#ff0000'),
w('w2', ['pot1', 'GND'], ['esp32', 'GND'], '#000000'),
w('w3', ['pot1', 'SIG'], ['esp32', '34'], '#ffaa00'),
w('w4', ['esp32', '3V3'], ['pot2', 'VCC'], '#ff0000'),
w('w5', ['pot2', 'GND'], ['esp32', 'GND'], '#000000'),
w('w6', ['pot2', 'SIG'], ['esp32', '35'], '#ffaa00'),
],
},
{
id: 'mega-multi-led',
title: 'Arduino Mega 16-LED Bar',
description: 'Arduino Mega drives 16 LEDs from pins 22-37. Knight Rider scanner effect.',
category: 'circuits',
difficulty: 'beginner',
boardType: 'arduino-mega',
code: `// Arduino Mega — 16-LED Knight Rider
void setup() { for(int i=22;i<=37;i++) pinMode(i,OUTPUT); }
void loop() {
for(int i=22;i<=37;i++) { digitalWrite(i,HIGH); delay(50); digitalWrite(i,LOW); }
for(int i=37;i>=22;i--) { digitalWrite(i,HIGH); delay(50); digitalWrite(i,LOW); }
}`,
components: [
MEGA,
...Array.from({ length: 8 }, (_, i) => ({
type: 'wokwi-led',
id: `led${i}`,
x: 460 + i * 30,
y: 300,
properties: { color: 'red' },
})),
// Series 220Ω resistors — one per LED. Without them ngspice
// can't solve a forward-biased short and the LEDs stay dark.
...Array.from({ length: 8 }, (_, i) => ({
type: 'wokwi-resistor',
id: `r${i}`,
x: 340,
y: 280 + i * 10,
properties: { value: '220' },
})),
],
wires: [
...Array.from({ length: 8 }, (_, i) =>
w(`wp${i}`, ['arduino-mega', `${22 + i}`], [`r${i}`, '1']),
),
...Array.from({ length: 8 }, (_, i) =>
w(`wl${i}`, [`r${i}`, '2'], [`led${i}`, 'A']),
),
...Array.from({ length: 8 }, (_, i) =>
w(`wg${i}`, [`led${i}`, 'C'], ['arduino-mega', 'GND'], '#000000'),
),
],
},
{
id: 'nano-sensor-station',
title: 'Arduino Nano Sensor Station',
description: 'Compact weather station: NTC + photoresistor on Nano. Reads temp and light.',
category: 'circuits',
difficulty: 'beginner',
boardType: 'arduino-nano',
code: `// Nano sensor station — NTC + LDR
#define NTC_PIN A0
#define LDR_PIN A1
void setup() { Serial.begin(9600); }
void loop() {
int tempRaw = analogRead(NTC_PIN);
int lightRaw = analogRead(LDR_PIN);
float tempV = tempRaw * 5.0 / 1023.0;
float lightPct = lightRaw * 100.0 / 1023.0;
Serial.print("Temp_V="); Serial.print(tempV,2);
Serial.print(" Light="); Serial.print(lightPct,0); Serial.println("%");
delay(1000);
}`,
components: [
{ type: 'wokwi-arduino-nano', id: 'arduino-nano', x: 100, y: 100, properties: {} },
{
type: 'wokwi-ntc-temperature-sensor',
id: 'ntc',
x: 350,
y: 100,
properties: { temperature: '22' },
},
{ type: 'wokwi-photoresistor-sensor', id: 'ldr', x: 350, y: 260, properties: { lux: '300' } },
],
wires: [
w('w1', ['arduino-nano', '5V'], ['ntc', 'VCC'], '#ff0000'),
w('w2', ['ntc', 'GND'], ['arduino-nano', 'GND'], '#000000'),
w('w3', ['ntc', 'OUT'], ['arduino-nano', 'A0'], '#ffaa00'),
w('w4', ['arduino-nano', '5V'], ['ldr', 'VCC'], '#ff0000'),
w('w5', ['ldr', 'GND'], ['arduino-nano', 'GND'], '#000000'),
w('w6', ['ldr', 'AO'], ['arduino-nano', 'A1'], '#ffaa00'),
],
},
{
id: 'esp32-pwm-led-rgb',
title: 'ESP32 LEDC PWM RGB',
description: 'ESP32 LEDC peripheral drives RGB LED with independent PWM channels.',
category: 'circuits',
difficulty: 'intermediate',
boardType: 'esp32',
code: `// ESP32 LEDC PWM — RGB LED color cycling
#define R_PIN 16
#define G_PIN 17
#define B_PIN 18
void setup() {
ledcAttach(R_PIN, 5000, 8);
ledcAttach(G_PIN, 5000, 8);
ledcAttach(B_PIN, 5000, 8);
}
void loop() {
for(int h=0; h<360; h+=5) {
float r,g,b;
// HSV to RGB (S=1, V=1)
int i = h/60; float f = h/60.0-i;
switch(i%6) {
case 0: r=1; g=f; b=0; break;
case 1: r=1-f; g=1; b=0; break;
case 2: r=0; g=1; b=f; break;
case 3: r=0; g=1-f; b=1; break;
case 4: r=f; g=0; b=1; break;
case 5: r=1; g=0; b=1-f; break;
}
ledcWrite(R_PIN, (int)(r*255));
ledcWrite(G_PIN, (int)(g*255));
ledcWrite(B_PIN, (int)(b*255));
delay(30);
}
}`,
components: [
ESP32,
{ type: 'wokwi-rgb-led', id: 'rgb', x: 400, y: 150, properties: {} },
{ type: 'wokwi-resistor', id: 'rr', x: 380, y: 80, properties: { value: '220' } },
{ type: 'wokwi-resistor', id: 'rg', x: 420, y: 80, properties: { value: '220' } },
{ type: 'wokwi-resistor', id: 'rb', x: 460, y: 80, properties: { value: '220' } },
],
wires: [
w('w1', ['esp32', '16'], ['rr', '1']),
w('w2', ['rr', '2'], ['rgb', 'R'], '#ff0000'),
w('w3', ['esp32', '17'], ['rg', '1']),
w('w4', ['rg', '2'], ['rgb', 'G'], '#00ff00'),
w('w5', ['esp32', '18'], ['rb', '1']),
w('w6', ['rb', '2'], ['rgb', 'B'], '#0000ff'),
w('w7', ['rgb', 'COM'], ['esp32', 'GND'], '#000000'),
],
},
];