diff --git a/frontend/src/components/DynamicComponent.tsx b/frontend/src/components/DynamicComponent.tsx index 58ecb4ac..19d0952f 100644 --- a/frontend/src/components/DynamicComponent.tsx +++ b/frontend/src/components/DynamicComponent.tsx @@ -552,8 +552,15 @@ export function createComponentFromMetadata( y: number; properties: Record; } { + // Underscore separators (not '-') so the resulting id is safe to embed + // in SPICE component / source names. ngspice's WASM build truncates + // vector keys at '-', which broke branch-current lookups for any LED / + // ammeter wired up by the user (visible symptom: correct node voltage, + // dark LED). Also strip '-' from metadata.id (e.g. 'led-bar-graph') so + // the prefix doesn't reintroduce a hyphen. + const safePrefix = metadata.id.replace(/-/g, '_'); return { - id: `${metadata.id}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, + id: `${safePrefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, metadataId: metadata.id, x, y, diff --git a/frontend/src/store/useSimulatorStore.ts b/frontend/src/store/useSimulatorStore.ts index 995eb131..8999f063 100644 --- a/frontend/src/store/useSimulatorStore.ts +++ b/frontend/src/store/useSimulatorStore.ts @@ -1894,16 +1894,22 @@ export const useSimulatorStore = create((set, get) => { // short forward-biased between 5V and GND — real hardware blows the // diode, and the ngspice solver returns an indeterminate / NaN branch // current so the visual LED never lights up on the canvas either. + // NOTE: component ids must NOT contain hyphens. ngspice (WASM build) + // truncates branch-current vector names at '-', so a sense source + // named V_led-builtin_sense yields the wrong key in branchCurrents + // and the LED's update() loop never sees the diode current — the + // node voltage is correct (the user sees ~1.84V on the wire) but the + // visual brightness stays at zero. Underscore is safe. components: [ { - id: 'led-builtin', + id: 'led_builtin', metadataId: 'led', x: 380, y: 100, properties: { color: 'red' }, }, { - id: 'r-builtin', + id: 'r_builtin', metadataId: 'resistor', x: 240, y: 130, @@ -1914,24 +1920,24 @@ export const useSimulatorStore = create((set, get) => { wires: [ // Pin 13 → resistor pin 1 (current-limiting side). { - id: 'wire-builtin-pin13', + id: 'wire_builtin_pin13', start: { componentId: 'arduino-uno', pinName: '13', x: 0, y: 0 }, - end: { componentId: 'r-builtin', pinName: '1', x: 0, y: 0 }, + end: { componentId: 'r_builtin', pinName: '1', x: 0, y: 0 }, waypoints: [], color: '#22c55e', }, // Resistor pin 2 → LED anode. { - id: 'wire-builtin-anode', - start: { componentId: 'r-builtin', pinName: '2', x: 0, y: 0 }, - end: { componentId: 'led-builtin', pinName: 'A', x: 0, y: 0 }, + id: 'wire_builtin_anode', + start: { componentId: 'r_builtin', pinName: '2', x: 0, y: 0 }, + end: { componentId: 'led_builtin', pinName: 'A', x: 0, y: 0 }, waypoints: [], color: '#22c55e', }, // LED cathode → GND. { - id: 'wire-builtin-cathode', - start: { componentId: 'led-builtin', pinName: 'C', x: 0, y: 0 }, + id: 'wire_builtin_cathode', + start: { componentId: 'led_builtin', pinName: 'C', x: 0, y: 0 }, end: { componentId: 'arduino-uno', pinName: 'GND.1', x: 0, y: 0 }, waypoints: [], color: '#000000',