fix(spice): allow hyphens in voltage-source name regex (root cause of dark-LED bug)

The user-reported 'LED with proper series resistor shows 1.84 V at
the anode but never visually lights up' had its root cause here,
not in ngspice / not in the LED brightness handler / not in any
component id naming choice. ngspice parses 'V_led-builtin_sense'
just fine; the diode conducts and the node voltage is exactly what
you'd compute by hand.

What breaks is the JS regex that scans the emitted netlist to
collect voltage-source names so CircuitSimulationService can ask
the scheduler to read their branch-current vectors:

  const m = card.match(/^([Vv][_\w]*)\s/);

[_\w]* doesn't accept '-'. For a card 'V_led-builtin_sense …' the
capture is 'V_led' (truncated at the hyphen). The voltageSources
array gets the wrong name; CircuitSimulationService pushes
'i(v_led)' into extraVectorsOfInterest; ngspice has no such vector
so the readVec promise rejects silently; branchCurrents['v_led-builtin_sense']
is never populated; the LED handler in BasicParts.ts sees raw =
undefined, the SPICE-memo path is skipped, and the digital fallback
runs but only sets the LED on when the PinResolver classifies the
anode as a direct GPIO connection (which it does NOT when an
intermediate resistor is in series). Dark LED.

Fix is adding '-' to the character class. One character. All five
existing examples I previously 'fixed' by just adding a series
resistor will now light up correctly without renaming any of their
component ids. Same for any saved user project with hyphenated ids
and for the auto-generated picker ids that used to contain hyphens.

The earlier underscore-id workarounds (default canvas + picker
template) stay in place as defense in depth — they don't break
anything and they keep the SPICE side clear of avoidable special
characters.
This commit is contained in:
David Montero Crespo 2026-05-18 10:44:51 -03:00
parent db5e3a8623
commit 5f378ed411
1 changed files with 12 additions and 1 deletions

View File

@ -201,9 +201,20 @@ export function buildNetlist(input: BuildNetlistInput): BuildNetlistResult {
// by an underscore or digit. ngspice's case-insensitive match means
// both `Vname` and `vname` count. We emit only uppercase prefixes
// from componentToSpice + NetlistBuilder, so this regex is safe.
//
// The character class MUST include `-` (hyphen). Component ids in
// examples and user-drawn circuits commonly contain hyphens
// (`led-builtin`, `led-red`, auto-generated `led-1717…-abc`), and
// SPICE itself happily parses identifiers with hyphens. If the regex
// doesn't accept them it truncates the captured name at the first
// hyphen ⇒ wrong voltageSources entry ⇒ CircuitSimulationService
// asks ngspice for the WRONG branch-current vector ⇒ branchCurrents
// lookup returns undefined ⇒ LED brightness stays at zero even though
// the circuit conducts correctly. Single-character fix, but it
// unblocks every hyphenated id across every existing project.
const voltageSources: string[] = [];
for (const card of cards) {
const m = card.match(/^([Vv][_\w]*)\s/);
const m = card.match(/^([Vv][_\w-]*)\s/);
if (m) voltageSources.push(m[1]);
}