From d79f2923d9a7af1f935459caa632aef8ad42e323 Mon Sep 17 00:00:00 2001 From: davidmonterocrespo24 Date: Fri, 15 May 2026 06:32:26 +0200 Subject: [PATCH] =?UTF-8?q?fix(sim):=20trace=20through=20BJT=20C=E2=86=94B?= =?UTF-8?q?=20in=20getArduinoPinHelper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The canonical "Arduino pin → resistor → BJT base, BJT collector → load" pattern for multiplexed 7-segment clocks was breaking in the simulator: getArduinoPinHelper('COM.1') couldn't resolve through the transistor, so the multiplex-aware 7-segment driver thought no digit-select pin was wired and fell back to "all digits enabled". Result: every display in the multiplex array rendered the same rapidly-changing pattern → user-visible flicker. Fix: add the NPN/PNP BJTs to the PASSIVE_PIN_PAIRS map with [collector, base] — the trace function continues from B when it arrives at C (and vice versa). That makes the Arduino pin driving the base reported as the controller of the collector — exactly the relationship the user's multiplex code expects. Conventions covered: - NPN (2n2222, bc547, 2n3055): Arduino HIGH → transistor on → COM pulled LOW → common-cathode digit enabled. Our 7-segment driver treats "digit pin HIGH = enabled" which matches. - PNP (2n3906, bc557): inverse logic. We expose the same pin mapping; users writing PNP-driver code will see the polarity behave inverted, which is what real hardware does too. This is a one-line shortcut, not a true active-device model. We're not simulating BJT saturation, β, base current, or PNP polarity — just reporting "this Arduino pin is the boss of this collector". That's enough for the multiplexing use case and the only place getArduinoPinHelper is consulted today. --- frontend/src/components/DynamicComponent.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/frontend/src/components/DynamicComponent.tsx b/frontend/src/components/DynamicComponent.tsx index 3566c857..05ba3163 100644 --- a/frontend/src/components/DynamicComponent.tsx +++ b/frontend/src/components/DynamicComponent.tsx @@ -262,6 +262,24 @@ export const DynamicComponent: React.FC = ({ // NTC and photoresistor breakouts are 3-pin active modules (VCC/GND // + analog output); not traceable as 2-terminal passives. Their // analog output is already an ADC-readable pin on its own. + // + // BJTs are 3-pin actives, but the canonical "Arduino digital pin + // controls a load via transistor" pattern is fundamental enough + // that we treat them as a [collector, base] shortcut. Tracing + // FROM the collector side continues through the base — i.e. the + // Arduino pin driving the base is reported as the controller of + // the collector. That makes 7-segment multiplex circuits with + // BJT digit drivers actually work in the simulator, since + // getArduinoPinHelper('COM.1') can resolve through the transistor. + // For NPN, Arduino HIGH at base → transistor on → collector pulled + // to emitter (typically GND) — and "HIGH = digit enabled" in our + // 7-segment driver matches this when COM is common-cathode wired + // through the transistor to GND. + 'bjt-2n2222': ['C', 'B'], + 'bjt-bc547': ['C', 'B'], + 'bjt-2n3055': ['C', 'B'], + 'bjt-2n3906': ['C', 'B'], + 'bjt-bc557': ['C', 'B'], }; // Preset variants of the generic passives share their parent's tag // and pin layout — so resistor-220, cap-1u, ind-10m, etc. trace the