Hardcut — ESP32 ignition-cut rev limiter & launch control — design

A bolt-on ESP32-S3 box for a 1995 Geo Tracker 1.6 16v MPFI (G16B), 3L30 3-speed automatic, adding a two-step launch limiter and a configurable main rev limiter by intercepting the two low-current logic wires between the ECM and the igniter. It suppresses individual ignition events by shunting the ECM’s spark command (IGt) to ground, while keeping every run of skipped events short enough that the ECM never notices — which is what keeps fuel flowing, and therefore what produces the exhaust bangs. The tap is a parallel open-drain pull to ground: nothing in the harness is cut, and an unpowered or hung box is electrically identical to a stock car.

Related: esp32, kb-agent-api, pipeline, index, cluzter.

ESP32 platform knowledge lives in esp32

The timing-budget findings below — core pinning does not isolate an ISR from WiFi, flash write/erase stalls task code for milliseconds, and the ESP_INTR_FLAG_LEVEL3 | ESP_INTR_FLAG_IRAM / out_w1ts / no-printf ISR rules — are generalised there for any timing-critical ESP32 work, together with the S3-vs-C3 choice, flashing and power gotchas from lightaim and the RuView CSI node.

This note is a wire-data source for cluzter

The signal table below carries real JIS/Suzuki-coded wires measured or traced on this car — Bl/G (IGf → ECM B5), Br/W (igniter IG → coil primary −), B/W (igniter +B), plus Orange (IGt), Green/White (brake switch) and Yellow (VSS → ECM A7). cluzter is the wiring-diagram editor for the same vehicle and treats this as ground truth. Note the trap it is built around: B is black and Bl is blue, one character apart — see cluzter-wiring-gotchas.

Problem

The factory G16B ECM limits revs by fuel cut at 6,720 r/min, restoring at 6,680 — 40 r/min of hysteresis, no ignition involvement, and no launch control of any kind. There is no way to hold a chosen RPM against the torque converter for a brake-torque launch, no way to lower the ceiling for a tired engine, and no bangs, because fuel cut is the one mechanism that guarantees nothing combustible reaches the exhaust.

The naive approach backfires on this car. The OBD1 ECM monitors ignition and cuts fuel when spark is lost"If spark is bad, all ECU's Cut Fuel injection!" A sustained spark cut therefore yields a stumble, no fuel, no bang, a probable DTC 41, and a real risk of a silent limp-home (rich, heavily retarded, ~3000 r/min ceiling, glowing exhaust) that this ECM enters without lighting the CEL about half the time.

The way through is that the ECM’s detector is a consecutive-miss counter, reset by any real ignition event. Keep every run of cuts below its threshold and the ECM stays satisfied while the engine still loses most of its combustion events.

Goal

  • Two-step launch limiter for brake-torque launches, with bangs
  • Configurable main limiter, below the factory 6,720
  • Hard (clustered) and soft (evenly-spread) cut patterns, switchable
  • WiFi web config: RPM targets, mode, hysteresis, live RPM telemetry
  • No harness cuts; removable without trace; stock behaviour when unpowered

Non-goals

  • No fuel-side control in v1. We never touch injector drives. Spark-only, because fuel is what makes the bang. (A half-cut lever is noted under future levers, deliberately out of scope here.)
  • No coil primary switching. Opening a charging primary destroys igniters. Ruled out permanently.
  • No 100% spark cut. Not merely unnecessary — actively worse (see the bang mechanism below) and the only case that would need IGf forgery.
  • No WiFi while armed. Not a preference; see the timing section.
  • No ECM reflash, no PROM work, no standalone ECU. The Mitsubishi/Suzuki processor is proprietary and unrecoverable if blown.
  • No CAS interception. Cutting the crank signal kills spark and fuel — no bangs, and it risks the ECM’s start logic.
  • No OBD2 / 1996+ support. 1996+ ECMs expose no IGf pin and drop code 41 entirely. The 8-valve igniter is 3-wire with no IGf at all, so an 8v port would be a different design, not a wiring variant.
  • No galvanic isolation. Impossible by construction: a shunt FET’s source is ECM ground, so you cannot sink into a floating node.
  • No traction control, no flat-shift, no anti-lag, no boost control. Naturally aspirated automatic.

Key decisions

DecisionChoiceWhy
What to cutIGt (ECM A4 → igniter), spark onlyThe only low-current node that stops combustion without touching the coil primary or the fuel side
How to cutShunt to ground in parallel, 22 Ω + BSS806NTarget is not a logic threshold but below V_BE(on), so aim ≤0.8 V at the node. 47 Ω only achieves that against a weak driver; 22 Ω works across the plausible range
Keeping fuel aliveCap consecutive cuts at 5The ECM’s miss counter resets on any real event. 5 is inside the bang sweet spot and safe against the threshold whether it is the FSM’s 8 or kick-fix’s 6
IGf forgeryHardware fitted, firmware path default-offMade unnecessary by the run cap, but the FET and resistor cost nothing and re-spinning a board later would
Bang pattern (launch)Clustered: cut N, fire 1 (N = 5)Bang energy comes from consecutive cuts terminated by a fired event that ignites the accumulated charge. Even spreading is the wrong tool here
Smooth pattern (main/soft)Evenly-spread accumulator, ratio ramped across a bandMatches MaxxECU/Emtron/Haltech practice; deliberately minimises run length, which is what makes it smooth
Decision timingDecide at falling edge N, apply to event N+1Gives 4–5 ms of slack, so ISR jitter is irrelevant, and structurally cannot truncate a dwell
RPM sourceIGt falling edges, 2 per crank revolutionAlready tapped; the falling edge is the spark command, so this measures real events
Stationary interlockVSS pulse presence + a dedicated brake microswitchVSS is read-only from the existing wire. The brake signal comes from our own switch, not the stock circuit — see the install decision below
Install methodTap individual wires; no ECU passthroughA full 22+26-way passthrough would add ~96 contact points to reach 4 circuits, and still could not supply the brake signal (this ECM has no brake pin). An igniter-connector 4-way passthrough is the option worth building if unplug-to-stock reversibility is wanted, since both driven signals live there. Rejected for this project, not in general — a separate all-pins diagnostic harness is planned, where reading every wire is the point and the connector is temporary rather than permanent. If that gets built, this box can migrate onto it as shared infrastructure
Hold cap5 s, then forced cooldownThe FSM’s own stall-test caution: "Do not run engine at stall more than 5 seconds continuously"
MCUESP32-S3, radio off whenever armedS3 over C3 (C3 is single-core, no MCPWM). Core pinning does not isolate the ISR from WiFi, so the radio must be off
Retard modeDeferred to a later phaseNeeds µs edge placement (1 crank° = 28 µs at 6000 rpm); fights ISR jitter

The falling edge is the spark — never assert the shunt while IGt is high

Toyota Course 852, describing the identical architecture: “When IGT signal voltage drops to 0 volts, the transistor in the igniter turns off.” Pulling IGt low mid-dwell therefore does not suppress a spark — it fires the plug at a random advance angle. This is the one bug in this project that can destroy the engine.

SUPERSEDED — this is now enforced in hardware, not software

This document originally said “no hardware can prevent this; the ISR must read the IGt input and refuse to assert unless it is already low.” That is no longer the design. 2026-08-08-hardcut-plan adds a 74HC74 D flip-flop clocked on IGt’s falling edge: the ESP32 writes only the flip-flop’s D input, and Q — which drives the shunt FET — can change only coincident with the falling edge. The MCU may assert at any time, early, late or wrongly, and the gate still cannot move mid-dwell.

The bug becomes physically unreachable rather than merely tested-for, and firmware timing stops being safety-relevant. Build to the plan, not to this callout. See Task 8: Breadboard the front end, flip-flop and shunt.

Why 100% cut is the wrong setting for bangs

Each skipped event pumps a full ~398 cc charge into a manifold+downpipe volume of roughly 3 L. Cut every event and the volume fills, but there is no fired event left to ignite it — one report on resumption, then silence. Runs of 3–5 give 40–66% fill and are each terminated by a real spark whose flame front lights the charge, so the reports repeat. The lever for louder is clustering, not a higher ratio.

Why not intercept the tachometer wire instead

On the 8-valve cars the fail-safe signal genuinely is the coil primary, on a brown wire through the noise suppressor to ECM A1 — so tach and IGf are the same node. On our 16-valve they are separate: IGf is a dedicated igniter output on Bl/G to ECM B5, while the coil primary is Br/W. Tapping the tach wire would give RPM but no IGf, and loading that node risks tripping the fuel cut we are trying to avoid.

Signal source

Everything needed is at one 4-pin connector on the igniter, bolted to the ignition coil on the firewall — external and separately replaceable on a 1995 car. On 1996+ the igniter moved inside the distributor, which is why this design is year-locked.

ECM A4 ──── Or ──────┬──────────────────────► igniter IGt
                     │                         (Darlington base, ~1.4 V threshold, ~11 mA)
       [2k2]─┬─BAT54S─┬──► 74LVC1G17Q ──► GPIO   read
             │  470pF │
    [R_sh 22R]        │
       [PTC 100mA]    │     shunt low = next dwell suppressed = no spark
     Q1 BSS806N ──────┴──── GND (ECM signal ground, B14)
       100k gate pulldown = the fail-safe

ECM B5 ◄─── Bl/G ────┬──────────────────────  igniter IGf  (5 V pull-up INSIDE the ECM)
       [2k2]─┬─BAT54S─┬──► 74LVC1G17Q ──► GPIO   read
             │  100pF │   (no filter cap — the edge matters)
     Q2 BSS806N ──────┴──── GND
       fitted but idle — forgery only if the run cap proves insufficient

                       igniter +B  ← B/W   (power)
                       igniter IG  → Br/W  (coil primary −)  ── NEVER TOUCHED
SignalWhereElectrical natureMeasured / spec
IGtigniter pin IGt, OrangeECM-driven, current-mode into Darlington base0 → 3.5 V; ~11 mA to fire (150 Ω to +12 V on the bench)
IGfigniter pin IGf, Blue/GreenOpen-collector, active-low, ECM-side pull-up~5 V at the wire with igniter unplugged
Brakeour own microswitch on the pedal bracketDry contact to ground, pulled up to 3V3 by usNothing is tapped. Positioned to make well into the pedal stroke, so it reports car held, not pedal touched. Stock circuit tap remains the documented fallback
VSSECM A7, YellowReed switch + magnet in speedometer head, dry contact to ground; the ECM supplies the pull-up0–1 V ↔ 4–5 V with ECM connected; 0 Ω ↔ ∞ with it unplugged. 4 pulses per speedo-cable revolution, ≈1.14 Hz per mph

Ignition events are 2 per crank revolution (4 distributor shutters ÷ 2). Spark-to-spark is 10 ms at 3000 r/min, 5 ms at 6000, 4.29 ms at 7000. Dwell is ECM-controlled, not fixed.

Hardware

RefPartRole / note
Q1, Q2Infineon BSS806NSOT-23, 30 mΩ, V_GS(th) 0.55 V. Not BSS138 — its 3.5 Ω eats the 0.8 V budget; not 2N7002 — V_GS(th) too high for 3.3 V
R_sh22 Ω ¼ W, footprint accepts 10 ΩIGt shunt; final value set by the measurement gate
gate network100 Ω series, 100 kΩ pull-downThe pull-down is the fail-safe. Same approach as Speeduino
PTC100 mA polyfusePrototype-only ECM protection while R_sh is unproven
U4–U7Diodes 74LVC1G17QSchmitt, inputs rated 5.5 V independent of V_CC, 0.6 V hysteresis = 17% of the IGt swing
clamps2.2 kΩ series + BAT54S2.2 kΩ holds fault current to 16 mA on a 40 V transient. Placed at connector entry, not at the MCU
supplyLM74700-Q1 ideal diode → SMBJ33ALM5164-Q1 buck (6–100 V) → AP2112K-3.3Reverse battery, load dump, cold crank. Not MP1584 (28 V abs max). Not an LDO-only chain (4.5 W at 500 mA)
bulk470 µF low-ESR + 100 µF + 100 nFESP32 peaks ~500 mA on WiFi TX; brownout detector trips at 2.43 V
brake inmicroswitch + 10 kΩ pull-up to 3V3 + 100 nFDry contact to ground, so no divider, no clamp, no 12 V exposure. Software debounce 20–50 ms, sampled in the telemetry task, never the ISR. Choose a switch with a positive-action lever and mount it to make late in the pedal stroke
VSS in10 kΩ series + 100 nF + BAT54S, no added pull-upThe ECM already pulls this up and already wets the reed contact. A second pull-up is redundant and risks lifting the low level toward a code 24
U9ESP32-S3-WROOM-1Dual core, MCPWM available
U10TPL5010External watchdog, independent of firmware

Grounding. One signal-ground wire to ECM pin B14, run in the same loom as the IGt/IGf taps, so ECM ground movement is common-mode and our thresholds move with the ECM’s. Power ground returns separately to battery negative; the two grounds meet at exactly one point, the buck output capacitor. Enclosure bonded to chassis only. Twisted pair per signal, shield grounded at the box end only. Mount under the dash if the loom reaches — the ECM end of these wires is already in the cabin.

Calibration defaults

Every value is user-configurable over WiFi; these are the shipped defaults, each anchored to a factory figure or to documented aftermarket practice.

SettingDefaultAnchored to
Launch limit2,500 r/min, then set by measurementDerived, not specified — see the stall callout. Above stall the converter slips and the brakes lose, so a higher setting is fiction
Launch hysteresis80 r/minHysteresis matters proportionally: 150 at 6300 is 2.4%, but 120 at 2700 would be 4.4% — coarse at the one RPM the driver is watching
Launch clustercut 5, fire 13–5 consecutive cuts is the bang knee; 5 stays under the ECM’s miss threshold
Main limit6,300 r/minUnder the factory 6,720, and above the 16v power peak of 95 bhp @ 5,600 — nothing lost by capping here
Main hysteresis150 r/minMid-range of published practice (ProEFI 50, Link/ME 200, HPA 100–200). The factory’s 40 is what makes the stock cut feel like a brick wall
Soft-cut band250 r/minRatio ramps 0 → max across the band below the limit; MaxxECU recommends 200–400
Max consecutive cuts5Hard ceiling in all modes. Never raised by any web request. Also caps the spread pattern’s ratio at ~83%, which is ample authority
Hold cap5 sThe 3L30’s own limit: "Do not hold engine at WOT for more than 5 seconds"
Cooldown before re-arm60 sThe 3L30 time-lag test demands "one minute intervals between tests", and a launch is more severe than that test
Configurable ceiling6,600 r/minFirmware-clamped so no web request can set a limit above the factory cut

Why the launch limit should stay under ~3,000

EGR opens above 3,200 r/min with the vehicle stopped. A stationary hold above that dilutes the intake charge with exhaust gas precisely when we want a rich, ignitable mixture — so a higher launch setting fights itself, quite apart from being beyond the converter’s stall.

The 3L30's stall speed is not documented — measure it, don't assume it

The often-quoted 2,300–2,600 r/min figure belongs to the 4-speed A/T and must not be applied here. No stall speed, stall procedure or cool-down exists for the 3-speed 3L30 anywhere in the manuals. What the factory does give is the converter itself: 245 mm, 3-element, max stall ratio 2.40:1, capacity factor K = 260. From N_stall = K·√T, at 90–98 lb-ft that yields ≈2,470–2,570 r/min — a derivation, not a specification. So the shipped 2,500 default is a placeholder: commissioning measures the real stall speed on the car (5 s maximum, 60 s cool-down) and the launch limit is then set just above it.

Brake-torquing is pure fluid shear, and the owner's manual says so

Lock-up is guaranteed disengaged while the brake is pressed — "if the brake pedal is depressed... the lock-up solenoid circuit opens and no voltage is applied." Every joule of a brake-torque hold therefore goes into shearing fluid inside the converter, which is exactly why the 5 s limit exists. The Tracker owner’s manual is blunter still: "Damage to your transmission caused by shifting out of PARK (P) or NEUTRAL (N) with the engine racing isn't covered by your warranty." The time limits are the whole mitigation; treat them as hard.

Architecture

hardcut/
├── firmware/
│   ├── src/
│   │   ├── main.cpp          boot, wiring, task pinning
│   │   ├── ign.cpp           ISR: edge capture, period, gate decision   ← IRAM, LEVEL3
│   │   ├── pattern.cpp       clustered & evenly-spread patterns, run cap
│   │   ├── limiter.cpp       control law: modes, ratio vs overshoot, hysteresis
│   │   ├── arming.cpp        brake + VSS + RPM interlocks, 5 s cap
│   │   ├── config.cpp        NVS persistence, firmware-clamped bounds
│   │   └── web.cpp           AP, JSON API, inline HTML page          ← disabled while armed
│   └── platformio.ini
├── bench/
│   └── emulator.cpp          2nd ESP32: fakes ECM IGt + igniter IGf
└── hardware/
    └── schematic.md          front ends, output stage, 12 V supply, BOM

ign.cpp is the only timing-critical unit and owns the gate. Everything else advises it by setting a target and a mode; nothing else may write a GPIO. It writes GPIO.out_w1ts/out_w1tc directly — gpio_set_level() is not IRAM-safe — and contains no printf, no float, and no flash-resident constants.

pattern.cpp — cut patterns and the run cap

Two generators over one interface. Clustered emits N cuts then one forced pass. Spread distributes cuts as evenly as the ratio allows. Both are wrapped by a single hard rule: a run of 5 cuts forces the next event to pass, whatever the generator asked for. That rule is the fuel supply’s guarantee and lives in exactly one place.

limiter.cpp / arming.cpp

limiter.cpp converts period to RPM, selects the active limit, and computes the requested ratio from overshoot. arming.cpp owns every reason to refuse — brake plus no VSS pulses plus RPM in window, the 5 s cap and cooldown, and disarming on any loss of confidence.

Timing budget

Baseline GPIO ISR latency is ~4 µs; WiFi activity adds 50–100 µs, and core pinning does not prevent this because bus arbitration is not partitioned by core. Against a 4.29 ms inter-event gap at 7000 rpm even 100 µs is 2%, so jitter is not the threat.

Flash operations are the threat. Cache is disabled during write/erase, stalling task code for milliseconds — long enough to drop events and corrupt the period estimate. Therefore: ISR allocated ESP_INTR_FLAG_LEVEL3 | ESP_INTR_FLAG_IRAM, radio off whenever armed, no NVS/LittleFS write and no OTA while armed, logs buffered in a DRAM ring and flushed only when disarmed.

Failure handling

  • Gate asserted while IGt is highimpossible by construction. The 74HC74 only transfers D to Q on IGt’s falling edge, so the gate physically cannot move mid-dwell whatever the firmware does. The ISR still re-reads IGt and refuses as a belt-and-braces second line, but the hardware is the guarantee. See the superseded-callout above; this is the only failure that can destroy the engine.
  • Unpowered / booting / brownout / watchdog reset / hung firmware → 100 kΩ gate pull-downs hold both FETs off, which is a stock car. Not an error path, the default state.
  • Run cap → a 6th consecutive cut is unreachable, not merely unlikely. Enforced after the generator, so no mode, ratio or config value can defeat it.
  • IGt pulses stop → engine off or tap lost; disarm, gate open.
  • Implausible period (>2× or <0.5× the last, or below plausible idle) → discard the sample, do not cut.
  • 5 s hold exceeded → release and refuse to re-arm until a cooldown elapses, regardless of driver input.
  • VSS reed failed open → no edge for >2 s means speed zero, so a dead reed reads as stationary, not as “still moving”. At ≈1.14 Hz per mph a 2 s timeout corresponds to under about 0.5 mph, which is the intended threshold. Bounce is rejected by minimum-interval (≈60% of the period at top speed), never a fixed blanking window.
  • We never drive VSS, brake or any other ECM input — all three are read-only, high-impedance taps. The only nodes this box ever drives are IGt and (if ever enabled) IGf.
  • Brake alone never arms anything. The stop-light switch closes in the first millimetre of pedal travel, so it proves intent, not that the car is held. VSS stationarity is the load-bearing interlock; the brake is the driver’s request. Do not later “simplify” arming to brake-only — it would look equivalent and would not be.
  • Supply below ~10 V → the ECM itself dies here, so degrade to gate-open rather than pretending to work.
  • Must never crash the car’s ignition. Every failure mode resolves to “stock Tracker”.

The single easiest bug to ship here

Writing the gate GPIO from the web/config path, or from a timer not synchronised to IGt. It will work on the bench and on most events, then land inside a dwell window at some random RPM and fire the coil at an uncommanded angle. Only ign.cpp touches that pin, only while IGt is low.

Prior art

  • korn101/ArduinoLaunchControl intercepts the Toyota IGT line for exactly this purpose — the right interception point, and instructive for its defects: the cut is decided in loop() behind a 20 ms delay (four ignition events at 6000 rpm, asynchronous to ignition phase), switched by a relay, with RPM from 1 ms millis() deltas against a 5 ms event period. Decide-at-N / apply-at-N+1 with a FET fixes all three.
  • IGf forgery is established practice in the Megasquirt community for Toyota conversions — typically an NPN and a resistor generating IGf from IGt, structurally our idle Q2. Reassuring that the fallback is proven.
  • Speeduino and rusEFI both use series-R + diode-clamp + hex Schmitt input protection and 100 kΩ gate pull-downs; the front end here is deliberately the same topology.
  • Relays are consistently reported as too slow for per-event ignition cutting. We use a MOSFET.

Bench rig

A second ESP32 emulates the ECM and the igniter: it generates IGt at a swept RPM and returns IGf after a configurable delay, optionally omitting IGf to imitate a fault. Every mode, interlock and failure path is proven here before the box goes near the car.

Testing / verification

  1. Car, identity check — 30 seconds, before anything else. Count the cavities on the ECM couplers: this design assumes the OBD1 16-valve 22-pin “A” + 26-pin “B” ECU. Also read the VIN’s 8th digit and confirm it is the 16-valve code. Every pin number in this document rests on a Vitara manual, corroborated pin-for-pin by a Tracker source but not from a Tracker factory section — these two checks validate or invalidate the whole basis at once. A different cavity count means stop and re-research.
  2. Emulator, pass-through — IGt out matches IGt in for every event across 500–7000 r/min; zero blocked events when disarmed.
  3. Emulator, the assertion trap — command the firmware to assert the shunt while IGt is high and verify it refuses. Hardware cannot enforce this, so it gets its own test.
  4. Emulator, gate integrity — assert across a long sweep that the gate pin never changes while IGt is high. Must fail loudly if the ISR is restructured.
  5. Emulator, run cap — sweep every mode, ratio and cluster setting; assert no run of blocked events ever exceeds 5. This is the test that protects the fuel supply.
  6. Emulator, RPM accuracy — within 1 % of commanded across the sweep; no reading survives an injected implausible period.
  7. Emulator, patterns and interlocks — clustered gives exact N-cut/1-pass groups; spread hits the requested ratio; no cut without brake + stationary; hold releases at 5 s; cooldown blocks re-arming.
  8. Car, measurement gate — the go/no-go, before anything is built. Key on, engine off, nothing unplugged: measure IGt high level (V1), add a known 220 Ω IGt-to-ground, measure again (V2), compute R_out = (V1 − V2) / (V2 / 220). Choose R_sh ≤ R_out / 6. If R_out < 60 Ω the parallel shunt is abandoned in favour of the series interrupt — at that impedance the shunt current is limited only by R_sh and would destroy the ECM driver. Also capture the real IGt→IGf delay and IGf pulse width while here. Best done as a continuity check from the igniter connector’s IGt terminal to ECM A4, and IGf to B5 — that single measurement proves the pinout on this car rather than inheriting it from a Vitara manual, and confirms both ends at once.
  9. Car, main limiter — at temperature, in neutral, brief excursion to a limit well under 6,720. Confirm it holds, then read DTCs live at the 6-pin DLC (jumper 2↔4) and confirm no code 41.
  10. Car, stall measurement — before enabling the launch limiter, measure the actual stall speed: brake fully applied, “D”, full throttle, read rpm when it stabilises, release immediately. 5 s maximum, 60 s at idle before repeating. Set the launch limit just above the measured figure.
  11. Car, two-step — brake-torque to the launch limit; confirm bangs, release, and that the 5 s cap and 60 s cooldown both fire. Check ATF colour and smell afterwards.

Risks

RiskMitigation
Every pin number is Vitara-sourcedNo Tracker/Sidekick factory electrical section for the 16-valve exists in the KB. A4/B5/A7 are corroborated by a Tracker-specific ECU pin list that matches the Vitara table pin-for-pin, but the cavity count and VIN check in test 0 are what actually confirm it. Cheap, so do them first
Adding a pull-up to VSS lifts its low level and sets code 24 → limp-homeNo added pull-up; read high-impedance and rely on the ECM’s own. Verify the low level with a meter once tapped
ECM output too stiff for a shunt (R_out < 60 Ω)The one outcome that invalidates the approach. Resolved by the two-minute measurement in test 7 before any board is built; fallback is a series interrupt, which the igniter’s internal pull-down makes safe for the coil
Shunt fails to pull below V_BE and the cut silently does nothingWhy R_sh is 22 Ω rather than 47 Ω, with a 10 Ω footprint in reserve; verified on the emulator and then on the car before relying on it
Shunt current stresses the ECM driverThe 8v ECU’s igniter driver is an M5262L, a 2 A peripheral driver, so 15–35 mA is orders of magnitude inside rating (16v part not identified, assumed comparable). IGt also rests at 0 V with ignition ON, so we only contend during the ~3 ms dwell command. Prototype carries a 100 mA polyfuse
Run cap does not satisfy the ECM (counter needs more than one good event to reset)Cap of 5 is conservative against a threshold documented as 8 and reported as 6. If fuel still cuts, enable the fitted Q2 forgery path — hardware is already there
Brake-torquing cooks the 3L305 s hard cap and 60 s cooldown, both from the 3L30’s own procedures. Lock-up is open with the brake down, so this is all converter shear — there is no mechanical path for the heat to avoid. ATF check after every session; normal operating range is 88–93 °C and there is no fluid-temperature sensor on this transmission, so inspection is the only feedback
Launch limit set from the wrong transmission’s specFixed: the 2,300–2,600 figure is 4-speed-only. Commissioning measures actual stall on the car; the 2,500 default is explicitly a placeholder
Muffler packing destroyedThe most likely casualty by far — a straight-through drum is fibreglass around a perforated tube, and pressure pulses shred and eject it permanently. Treat it as a consumable
O2 sensor fouling / thermal shockDegrades closed-loop fuelling without necessarily setting a code on OBD1. Inspect and expect to replace
Cast-iron manifold crackingDocumented for repeated late-combustion thermal cycling. Inspect runner junctions periodically; bounded by the 5 s cap
Exhaust valve bounceMaterially lower here than the forums suggest: the classic failure is a bounced valve letting a hydraulic lifter pump up and hold it open, and the G16B is shim-over-bucket with solid lifters. A bounced valve simply recloses. No documented case of a small NA four losing a valve to a two-step
Silent limp-home with no CELRun cap is the primary defence; read DTCs live at the DLC after every session rather than trusting the lamp
Millisecond ISR stall from a flash write drops eventsRadio off and no NVS/OTA while armed; logs buffered in DRAM. Enforced structurally, not by discipline
Engine-bay EMI corrupting a 3.5 V logic tap0.6 V Schmitt hysteresis, clamps at connector entry, twisted/shielded pairs, signal ground referenced to ECM B14 so ground movement is common-mode
Decel fuel cut removes the fuel we needBangs require an open throttle. Closed-throttle above 3000 r/min triggers the factory decel cut and there is nothing to ignite — a limitation, not a fault

Future levers (not v1)

  • IGf forgery enabled — unlocks runs longer than 5 and a true 100% cut. Only worth it if the run cap disappoints; note the forged pulse may need a width window, since real IGf holds a roughly constant high duration while the low portion varies with RPM.
  • Spark retard mode — delay the IGt pulse rather than blocking it. Keeps real spark and real IGf, zero DTC risk, smooth street limiter. Needs ~28 µs placement accuracy; revisit once ISR jitter is measured on the bench.
  • Half-cut via one injector group — B11 (injectors 1&4) and B24 (2&3) are separate drivers, so half the fuel could be dropped to tune bang intensity. Adds inductive-load switching risk.
  • Igniter-connector passthrough — a 4-way printed adapter carrying IGt, IGf, +B and IG, giving unplug-to-stock reversibility. Shell can be printed (ASA or nylon, never PLA — under-bonnet temperatures pass its glass transition and a crept latch is a connector that backs out); terminals cannot, and would need harvesting from a donor harness.
  • Orphaned rear-diff VR sensor as a road-speed source — the ABS speed sensor is already unplugged and cut, so it is electrically free to reuse. Not worth it while the reed switch works (a VR front end is an entirely different circuit), but it is the fallback if the speedo-head reed corrodes, which the KB calls its most common failure.
  • Jot the tap points into pipeline as harness entries once verified on the car.
  • Telegram fault reporting via the existing bot, if the box ever needs to report off-car.