feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
/**
|
|
|
|
|
* Measurement probes (voltmeters, ammeters, scope probes).
|
|
|
|
|
*
|
|
|
|
|
* Probes are Velxio components with `metadataId` starting with `instr-`.
|
|
|
|
|
* They do NOT contribute SPICE cards themselves (so `componentToSpice`
|
|
|
|
|
* returns null for them). Instead, they read the already-solved result
|
|
|
|
|
* via net names derived from the same Union-Find used in NetlistBuilder.
|
|
|
|
|
*
|
|
|
|
|
* The ammeter is special: it *does* inject a "V_name_sense 0" voltage
|
|
|
|
|
* source (0 V) in series with one of its pins so ngspice reports a
|
|
|
|
|
* branch current for it. Phase 8.5 MVP: emit the sense source by extending
|
|
|
|
|
* componentToSpice with an ammeter mapper.
|
|
|
|
|
*/
|
2026-04-21 12:17:30 +07:00
|
|
|
import type { ComponentForSpice, ElectricalSolveResult, TimeWaveforms } from './types';
|
feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
import type { Wire } from '../../types/wire';
|
|
|
|
|
import { UnionFind } from './unionFind';
|
2026-04-21 12:17:30 +07:00
|
|
|
import { rms, mean, peak, subtract, isAC } from './waveformStats';
|
feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
|
|
|
|
|
export type ProbeKind = 'voltmeter' | 'ammeter' | 'multimeter';
|
|
|
|
|
|
2026-04-21 12:17:30 +07:00
|
|
|
/**
|
|
|
|
|
* Time-domain statistics computed from a `.tran` waveform.
|
|
|
|
|
* Present only when the probed net has AC content.
|
|
|
|
|
*/
|
|
|
|
|
export interface ProbeAcStats {
|
|
|
|
|
/** Root-mean-square (what a real RMS meter reads for AC). */
|
|
|
|
|
rms: number;
|
|
|
|
|
/** DC component (mean). */
|
|
|
|
|
dc: number;
|
|
|
|
|
/** Peak absolute value. */
|
|
|
|
|
peak: number;
|
|
|
|
|
/** Pre-formatted "RMS X.XX V" / "RMS X.XX mA" line. */
|
|
|
|
|
rmsDisplay: string;
|
|
|
|
|
/** Pre-formatted "pk X.XX V" line. */
|
|
|
|
|
peakDisplay: string;
|
|
|
|
|
/** Pre-formatted "DC X.XX V" line. */
|
|
|
|
|
dcDisplay: string;
|
|
|
|
|
}
|
|
|
|
|
|
feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
export interface ProbeReading {
|
|
|
|
|
kind: ProbeKind;
|
|
|
|
|
/** Primary numeric value (volts for voltmeter, amps for ammeter). */
|
|
|
|
|
value: number;
|
2026-04-21 12:17:30 +07:00
|
|
|
/** Pretty string for UI display (legacy single-line). */
|
feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
display: string;
|
|
|
|
|
/** Unit label shown next to the value. */
|
|
|
|
|
unit: 'V' | 'mV' | 'µV' | 'A' | 'mA' | 'µA' | 'nA' | 'Ω' | 'kΩ' | 'MΩ' | '—';
|
|
|
|
|
/** Whether the reading is stale / invalid. */
|
|
|
|
|
stale: boolean;
|
2026-04-21 12:17:30 +07:00
|
|
|
/** Time-domain statistics when the probed net has AC content. */
|
|
|
|
|
ac?: ProbeAcStats;
|
feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** True if a component is an instrument (doesn't stamp SPICE cards itself). */
|
|
|
|
|
export function isInstrument(metadataId: string): boolean {
|
|
|
|
|
return metadataId.startsWith('instr-');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function formatV(v: number): { value: number; unit: ProbeReading['unit']; display: string } {
|
|
|
|
|
const abs = Math.abs(v);
|
|
|
|
|
if (abs < 1e-6) return { value: v * 1e6, unit: 'µV', display: `${(v * 1e6).toFixed(2)} µV` };
|
|
|
|
|
if (abs < 1) return { value: v * 1e3, unit: 'mV', display: `${(v * 1e3).toFixed(2)} mV` };
|
|
|
|
|
return { value: v, unit: 'V', display: `${v.toFixed(3)} V` };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function formatI(i: number): { value: number; unit: ProbeReading['unit']; display: string } {
|
|
|
|
|
const abs = Math.abs(i);
|
|
|
|
|
if (abs < 1e-9) return { value: 0, unit: 'nA', display: `0 nA` };
|
|
|
|
|
if (abs < 1e-6) return { value: i * 1e9, unit: 'nA', display: `${(i * 1e9).toFixed(1)} nA` };
|
|
|
|
|
if (abs < 1e-3) return { value: i * 1e6, unit: 'µA', display: `${(i * 1e6).toFixed(2)} µA` };
|
|
|
|
|
if (abs < 1) return { value: i * 1e3, unit: 'mA', display: `${(i * 1e3).toFixed(2)} mA` };
|
|
|
|
|
return { value: i, unit: 'A', display: `${i.toFixed(3)} A` };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Build a pin → net lookup identical to what NetlistBuilder uses. Used by
|
|
|
|
|
* probe readings so we can map `voltmeter:Vin` / `voltmeter:Vout` etc. to
|
|
|
|
|
* actual net names in the solve result.
|
|
|
|
|
*/
|
|
|
|
|
export function buildPinNetLookup(
|
|
|
|
|
wires: Wire[],
|
|
|
|
|
groundPins: Array<{ componentId: string; pinName: string }>,
|
|
|
|
|
vccPins: Array<{ componentId: string; pinName: string }>,
|
|
|
|
|
): (componentId: string, pinName: string) => string | null {
|
|
|
|
|
const uf = new UnionFind();
|
|
|
|
|
for (const w of wires) {
|
|
|
|
|
const a = `${w.start.componentId}:${w.start.pinName}`;
|
|
|
|
|
const b = `${w.end.componentId}:${w.end.pinName}`;
|
|
|
|
|
uf.union(a, b);
|
|
|
|
|
}
|
|
|
|
|
for (const g of groundPins) uf.setCanonical(`${g.componentId}:${g.pinName}`, '0');
|
|
|
|
|
for (const v of vccPins) uf.setCanonical(`${v.componentId}:${v.pinName}`, 'vcc_rail');
|
|
|
|
|
// Build deterministic net names matching NetlistBuilder's scheme (n0, n1, …)
|
|
|
|
|
const reps = [...uf.nets()].sort();
|
|
|
|
|
const netNames = new Map<string, string>();
|
|
|
|
|
let counter = 0;
|
|
|
|
|
for (const rep of reps) {
|
|
|
|
|
if (rep === '0' || rep === 'vcc_rail') netNames.set(rep, rep);
|
|
|
|
|
else netNames.set(rep, `n${counter++}`);
|
|
|
|
|
}
|
|
|
|
|
return (componentId, pinName) => {
|
|
|
|
|
const key = `${componentId}:${pinName}`;
|
|
|
|
|
if (!uf.has(key)) return null;
|
|
|
|
|
return netNames.get(uf.find(key)) ?? null;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-21 12:17:30 +07:00
|
|
|
function buildAcStatsV(samples: readonly number[]): ProbeAcStats {
|
|
|
|
|
const r = rms(samples);
|
|
|
|
|
const dc = mean(samples);
|
|
|
|
|
const pk = peak(samples);
|
|
|
|
|
const rmsFmt = formatV(r);
|
|
|
|
|
const dcFmt = formatV(dc);
|
|
|
|
|
const pkFmt = formatV(pk);
|
|
|
|
|
return {
|
|
|
|
|
rms: r,
|
|
|
|
|
dc,
|
|
|
|
|
peak: pk,
|
|
|
|
|
rmsDisplay: `RMS ${rmsFmt.display}`,
|
|
|
|
|
peakDisplay: `pk ${pkFmt.display}`,
|
|
|
|
|
dcDisplay: `DC ${dcFmt.display}`,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function buildAcStatsI(samples: readonly number[]): ProbeAcStats {
|
|
|
|
|
const r = rms(samples);
|
|
|
|
|
const dc = mean(samples);
|
|
|
|
|
const pk = peak(samples);
|
|
|
|
|
const rmsFmt = formatI(r);
|
|
|
|
|
const dcFmt = formatI(dc);
|
|
|
|
|
const pkFmt = formatI(pk);
|
|
|
|
|
return {
|
|
|
|
|
rms: r,
|
|
|
|
|
dc,
|
|
|
|
|
peak: pk,
|
|
|
|
|
rmsDisplay: `RMS ${rmsFmt.display}`,
|
|
|
|
|
peakDisplay: `pk ${pkFmt.display}`,
|
|
|
|
|
dcDisplay: `DC ${dcFmt.display}`,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
export function readVoltmeter(
|
|
|
|
|
comp: ComponentForSpice,
|
|
|
|
|
netLookup: (componentId: string, pinName: string) => string | null,
|
|
|
|
|
solve: ElectricalSolveResult,
|
2026-04-21 12:17:30 +07:00
|
|
|
timeWaveforms?: TimeWaveforms,
|
feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
): ProbeReading {
|
|
|
|
|
const plusNet = netLookup(comp.id, 'V+');
|
|
|
|
|
const minusNet = netLookup(comp.id, 'V-');
|
|
|
|
|
if (!plusNet || !minusNet) {
|
|
|
|
|
return { kind: 'voltmeter', value: 0, unit: '—', display: '— probe not connected', stale: true };
|
|
|
|
|
}
|
|
|
|
|
const vp = solve.nodeVoltages[plusNet] ?? 0;
|
|
|
|
|
const vm = solve.nodeVoltages[minusNet] ?? 0;
|
|
|
|
|
const diff = vp - vm;
|
|
|
|
|
const fmt = formatV(diff);
|
2026-04-21 12:17:30 +07:00
|
|
|
|
|
|
|
|
let ac: ProbeAcStats | undefined;
|
|
|
|
|
if (timeWaveforms) {
|
|
|
|
|
const plusSamples = timeWaveforms.nodes.get(plusNet);
|
|
|
|
|
const minusSamples = plusNet === '0' ? undefined : timeWaveforms.nodes.get(minusNet);
|
|
|
|
|
const plusArr = plusSamples ?? (plusNet === '0' ? [] : undefined);
|
|
|
|
|
const minusArr = minusSamples ?? (minusNet === '0' ? [] : undefined);
|
|
|
|
|
if (plusArr !== undefined && minusArr !== undefined) {
|
|
|
|
|
// subtract() tolerates a zero-length array and returns []; guard with a length check.
|
|
|
|
|
const diffSamples =
|
|
|
|
|
plusArr.length === 0
|
|
|
|
|
? minusArr.map((v) => -v)
|
|
|
|
|
: minusArr.length === 0
|
|
|
|
|
? [...plusArr]
|
|
|
|
|
: subtract(plusArr, minusArr);
|
|
|
|
|
if (diffSamples.length > 0 && isAC(diffSamples)) {
|
|
|
|
|
ac = buildAcStatsV(diffSamples);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
kind: 'voltmeter',
|
|
|
|
|
value: fmt.value,
|
|
|
|
|
unit: fmt.unit,
|
|
|
|
|
display: ac ? ac.rmsDisplay : fmt.display,
|
|
|
|
|
stale: !solve.converged,
|
|
|
|
|
ac,
|
|
|
|
|
};
|
feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function readAmmeter(
|
|
|
|
|
comp: ComponentForSpice,
|
|
|
|
|
solve: ElectricalSolveResult,
|
2026-04-21 12:17:30 +07:00
|
|
|
timeWaveforms?: TimeWaveforms,
|
feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
): ProbeReading {
|
|
|
|
|
const key = `v_${comp.id}_sense`;
|
|
|
|
|
const i = solve.branchCurrents[key];
|
|
|
|
|
if (i == null) {
|
|
|
|
|
return { kind: 'ammeter', value: 0, unit: '—', display: '— no sense reading', stale: true };
|
|
|
|
|
}
|
|
|
|
|
// Convention: ngspice reports positive current flowing from + terminal into
|
|
|
|
|
// the source (which is our "entry" terminal). Ammeters typically want the
|
|
|
|
|
// current through, with a sign convention of + out of the "+" probe.
|
|
|
|
|
const signed = -i;
|
|
|
|
|
const fmt = formatI(signed);
|
2026-04-21 12:17:30 +07:00
|
|
|
|
|
|
|
|
let ac: ProbeAcStats | undefined;
|
|
|
|
|
if (timeWaveforms) {
|
|
|
|
|
const raw = timeWaveforms.branches.get(key);
|
|
|
|
|
if (raw && raw.length > 0) {
|
|
|
|
|
const signedSamples = raw.map((v) => -v);
|
|
|
|
|
if (isAC(signedSamples)) {
|
|
|
|
|
ac = buildAcStatsI(signedSamples);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
kind: 'ammeter',
|
|
|
|
|
value: fmt.value,
|
|
|
|
|
unit: fmt.unit,
|
|
|
|
|
display: ac ? ac.rmsDisplay : fmt.display,
|
|
|
|
|
stale: !solve.converged,
|
|
|
|
|
ac,
|
|
|
|
|
};
|
feat: electrical simulation via ngspice-WASM (eecircuit-engine)
Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy-
loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate
with real analog behaviour: correct voltages on wires, real I–V curves on
LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM
driving RC filters, transistors, op-amps, diodes, MOSFETs, etc.
Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle
stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates
electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false.
Frontend additions:
- simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with
UnionFind over wires, componentToSpice mapping (24 metadataIds incl.
real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148,
1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with
debounced coalescing, AVRSpiceBridge for quasi-static co-simulation.
- store/useElectricalStore: Zustand slice, feature-flag aware.
- components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay.
- components/components-instruments/: Voltmeter, Ammeter probes.
- 62 tests (spice-*, netlist-builder, component-to-spice, instruments).
Sandbox (test/test_circuit/): 47-test validation sandbox that proved
the approach (hand-rolled MNA baseline + ngspice pipeline) before
porting to the app. Kept as reference.
Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering
architecture, solvers, components, AVR bridge, gotchas, performance,
integration plan, API reference, appendix) + electrical-simulation-
user-guide.md (end-user facing).
Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
|
|
|
}
|