1616 lines
65 KiB
TypeScript
1616 lines
65 KiB
TypeScript
/**
|
||
* 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'),
|
||
],
|
||
},
|
||
];
|