← Open EMC  ·  first project · open-source, local-first

EMC-Assist — find conducted-EMI risk before the lab.

Open-source, local-first tooling for conducted-EMI pre-compliance workflows: model PCB parasitics, generate LISN and cable-aware LTspice testbenches, run them in your local LTspice, compare EMI filter variants, parse .raw/.log results, and document risks before the lab. A deterministic engineering core — with an optional, opt-in LLM-assisted review layer on top. Results are engineering diagnostics, never certification.

100% local — schematic never leaves the machine Apache-2.0 open source PCB parasitic modelling LISN / cable-aware testbenches local LTspice run variant comparison & ranking min·typ·max corner sweep pre-compliance reports
⚠
Independent open-source project. LTspice is user-supplied and runs locally — never bundled, hosted, or modified. Results are pre-compliance diagnostics, not certification.
Part of the Open EMC initiative

The first project under Open EMC

Open EMC is an open-source initiative for transparent, local-first EMC tooling. EMC-Assist is its first concrete tool — a conducted-EMI workflow for LTspice-based simulations. The deterministic core runs entirely on your machine, with an opt-in LLM layer on top.

← Explore the Open EMC initiative
The problem

The ideal simulation is not the real board

A clean LTspice schematic looks reassuring — and omits almost everything that actually shapes conducted emissions. EMC-Assist exists to make those omitted effects visible early, as engineering hypotheses to test, while changes are still cheap.

≈

Real boards carry parasitics

Trace inductance, via ESL, capacitor mounting effects, plane coupling and filter Q create resonances the ideal schematic never shows.

⌁

Cables & return paths matter

The LISN, the input cable and the return path set what an EMI receiver would actually measure — not the bare DUT.

◷

Lab iterations are expensive

Chamber time and re-spins compound. Surfacing likely risks before the booking turns blind guesses into targeted checks.

Workflow

A run, end to end

A deterministic spine writes an auditable artifact at every stage — nothing is a black box. After simulation, an LLM panel fans out over the result, then converges into one diagnosis.

01 · Import.asc / .cir 02 · Topologynet roles 03 · Parasiticsmin·typ·max / net 04 · TestbenchLISN+cable+inj 05 · Variants×3 min/typ/max 06 · SimulateLTspice + detectors
↓ optional · when enabled, the analysis fans out to the LLM review panel — off by default ↓
simulation output
.raw · metrics · quasi-peak-like detectors
fan‑out →
dcdc
filtering
power_integrity
decoupling
parasitics
stackup
high_speed
mixed_signal
ic_vendor
layout_risk
signal_map
11 specialists run in parallel · each one focused LLM call · redacted payloads only
→ cluster →
orchestrator
clusters findings
synthesiser
one diagnosis
diagnosis → report
conf 70% · cited

A pre-composition LISN-mode agent also shapes stage 04 before simulation. The deterministic core runs with or without the LLM layer — it is an assistant, never the source of truth.

Key features

What's inside

A deterministic engineering core, with an optional LLM layer bolted on top — never the source of truth.

◇ Per-net parasitic injection shipped

Every net gets a parasitic: shunt-C universally, series R+L+C where the topology allows a clean cut. Min·typ·max bands, project overrides, and an opt-in LLM negligibility screen.

≈ Corner sweep shipped

Parasitics are uncertain, so we sweep them. Each run produces ranked min/typ/max variants — an honest spread, not a single "certain" number.

⎍ Quasi-peak-like diagnostic metrics shipped

Peak, quasi-peak-like (meter-time-constant model) and average diagnostic metrics, compared against a configured reference curve — an uncalibrated pre-compliance diagnostic, not a certified-receiver reading.

⌬ 11 specialist agents opt-in · experimental

One focused LLM call per area (DC/DC, filtering, layout, decoupling, parasitics…), plus a pre-composition LISN-mode agent, an orchestrator and a diagnostic synthesiser.

⌕ Local RAG opt-in · experimental

Curated EMC seed rules, local embeddings and a pure-numpy vector index — no FAISS/Chroma, no cloud index. Every rule carries a source or is flagged as an engineering estimate.

⛨ Copyright-safe redaction shipped

Outbound LLM payloads carry only rule_id + source_id + our summary + a ≤200-char excerpt. Full vendor text and your netlist never leave the machine.

▤ Auditable reports shipped

Markdown / HTML (PDF optional) with an assumptions table, parasitics table, before/after, a risk list, cited sources and a pre-compliance disclaimer.

▦ Desktop UI shipped (M3)

A pywebview shell over the same service core: Projects → Report, with stage gating, live logs, the detector spectrum and a stale-data guard.

⚿ Local-first & private shipped

LTspice runs locally and is never bundled. Cloud LLM is opt-in and key-gated; with it off, no network calls happen under any action.

⤓ Schematic import & topology shipped

Import an .asc/.cir, parse R/L/C/V/I/X/M/D + .model/.param/.tran, and derive net roles (power / switch / signal / return) for the analysis.

⌁ AI: suggest negligible opt-in · experimental

An opt-in LLM negligibility screen pre-deselects nets that won't move the conducted band — you keep the final say. Key-gated; deterministic otherwise.

⟳ AI: re-evaluate values (RAG) opt-in · experimental

One batched LLM+RAG pass refines every net's R/L/C into citation-backed min·typ·max. Preview → review → apply; the deterministic prior is the fallback.

∿ Time-domain waveform analyzer shipped

Two time-aligned panels: the LISN-measured V(meas) over a comparison trace (load current by default; four more LLM/heuristic-picked for EMI relevance).

⌖ Quasi-peak at frequency & sweep shipped

Quasi-peak-like diagnostic at a single frequency with margin to the configured reference curve, or a full sweep across the conducted band (150 kHz–30 MHz) — read straight off the run's .raw.

▤ Standardized recommendation JSON shipped

Every finding carries problem · evidence · proposed change · value range · assumptions · limitations · sim/measurement requirement · confidence · severity · sources.

✓ Accept / reject feedback loop shipped

Decide on each recommendation; decisions persist to decisions/*.json and flow into the report's decision log.

⚙ Simulation-settings review shipped

A deterministic, free check of your .tran window/timestep against the conducted band and switching edges — review proposed settings before they apply.

◷ Honest-data stale guard shipped

Edit any upstream input and the whole downstream chain is flagged stale; Results / Findings / Report refuse to present old numbers as current.

⌗ One service core, two front-ends shipped

A typed service/ layer is the product; the CLI and the desktop app are thin adapters over it, with a structured logging seam and offline schema validation.

▥ LTspice .asc visualisation export shipped

The composed testbench is also emitted as an .asc you can open in LTspice to eyeball the LISN + cable + injection wiring.

Parasitics & testbench

Every net modelled — then wired into a LISN testbench

PCB parasitics dominate conducted EMI and they're uncertain — so the tool estimates a min·typ·max band for every net from role-tuned geometry, cites a rule (or marks it an engineering estimate), injects them, and assembles a LISN testbench around your circuit. An LLM can screen out negligible nets and refine the values against the knowledge base — both opt-in, both reviewable.

Estimated structures — case_003 (real, min·typ·max)

StructureTypemintypmaxconfsrc
trace R 25×0.5 1ozR mΩ20.225.331.6highR001
trace L iso 25×0.5L nH12.625.237.8medR002
trace C Z0 25–50C pF2.343.354.35highR004/5
plane-pair C 100mm²C pF1.902.382.97medR012
via L h1.6 d0.3L nH0.911.301.82medR010
loop self-resonanceMHz438548685highR030

Models cover trace R/L/C, vias, plane pairs, cables and capacitor ESR/ESL/SRF. Injection: a shunt-C on every net, plus a series R+L+C where the net is a clean point-to-point cut; each L gets a Q-damping resistor so tiny pF/nH tanks don't blow up transient time. --parasitics-report-only keeps estimates in the report but out of the sim; project overrides pin any value.

⌁ AI: suggest negligible

The opt-in negligibility screen reads the per-net plan and pre-deselects nets that won't change the conducted band. For case_003 the 17 LTC7800 controller-pin nets are skipped, leaving 14 power/switch/signal nets.

⟳ AI: re-evaluate values (RAG)

A single batched LLM+RAG call turns each net's rule-of-thumb band into a citation-backed min·typ·max. You review the proposals (with their cited sources) and apply only the typ overrides — no second call, full audit kept.

Injection summary — testbench.cir

V_RAIL → LISN+ → cable → [TRACE_RLC] → DUT (31 nets) → LISN- · DM+CM probes

Series RLC
6 nets
Shunt-C
7 nets
Dropped · user
17 nets
Dropped · AI
0 nets
Input-rail inj.
1 TRACE
LISN
dual DM+CM

Signals probed Vout=V(OUT), Vin=V(IN) · supply VIN ↦ LISN · return 0 ↦ LISN · wiring/parasitics/signal audits all green

Diagnostics · real data

The conducted-emissions spectrum

A real per-frequency quasi-peak-like detector sweep from the bundled case_003 example — an LTC7800 buck (12 → 3.3 V) — against a configured reference curve. The detector flags a low-frequency quasi-peak-like exceedance above that reference curve in this simulation: a pre-compliance hypothesis to confirm on the bench.

020 4060 80100 dBµV 150k1 MHz 10 MHz30 MHz QP +12.9 dB over @ ~177 kHz
QP ≈ AVG · V(meas) QP limit (configured reference) AVG limit

Real artifact: results/spectrum.json · 96-point sweep · 150 kHz–30 MHz · trace V(meas). Margins are pre-compliance estimates against a configured reference curve — not a calibrated lab measurement.

Optional LLM-assisted reviewopt-in · experimental

An optional review layer — that cites its sources

Entirely optional and off by default. The deterministic core produces the result on its own; when you opt in and supply a key, this experimental layer reviews it. After simulation, 11 area specialists each produce structured recommendations; an orchestrator clusters them and a synthesiser writes one top-level diagnosis. A pre-composition LISN-mode agent shapes the testbench. Each is a single focused call — no autonomous loops, and the engineer keeps the final say.

dcdcfiltering power_integritydecoupling parasiticsstackup high_speedmixed_signal ic_vendorlayout_risk signal_map + orchestrator + synthesiser + LISN-mode (pre-compose)

Diagnosis — case_003, real

“Switch-node (hot-loop) dv/dt likely dominates conducted EMI, with input-filter resonance a secondary contributor.” The simulation shows differential-mode amplitude far above common-mode (20.85 V vs 10.40 V) — consistent with DM-driven emission from a high-dv/dt node.

confidence 70%LLM-synthesised cites SRC-045, SRC-082hypothesis · verify on bench

What we send to the cloud (when enabled)

Always sentNever sent
rule_id · source_idyour schematic / netlist
our own summaryfull vendor document text
≤200-char excerpt*net names (redacted)

*only from permissively-licensed sources. Every outbound payload is logged to results/llm/*.jsonl. Cloud LLM is off by default.

A slice of the real findings for case_003 — 11 areas, ~37 recommendations:

HIGHdcdcDifferential-mode emissions are dominant in the simulation (dm_peak > cm_peak).conf 70%
HIGHpower_integrityLikely LC resonance near 156 kHz amplifying conducted noise.conf 60%
HIGHlayout_riskUnknown hot-loop area and loop inductance around the switch node and input decoupling.conf 30%
Local-first privacy model

What stays on your machine

By default, nothing leaves your computer. The optional cloud-LLM layer is key-gated and off until you turn it on — and even then it only ever sees a redacted, structured summary, never your design files.

⌂  Stays local — always
schematic
netlist
.raw / .log results
generated testbench
project files

With cloud LLM off, no network calls happen under any action.

↗  Optional LLM payload — only when enabled
redacted structured summary
cited snippets (≤200-char, permissive sources)
metrics
never the full schematic / netlist by default

Every outbound payload is logged to results/llm/*.jsonl — a privacy audit trail you can inspect.

Open-source knowledge model

No hidden knowledge dump

EMC-Assist does not ship a hidden knowledge dump. The core is open source, and users can index sources they are legally allowed to use.

◍

The core is open source

You can read exactly how each parasitic value is estimated, and where the result is an engineering assumption rather than a measurement.

⚿

Bring your own sources

Index the references you're legally allowed to use. No bundled scraped RAG dump; no paid standards shipped inside the tool.

▤

Knowledge stays user-controlled

Every rule carries a source or is flagged as an engineering estimate — guidance is never presented without showing where it came from.

Architecture

One service core, two front-ends

A typed service/ layer is the product; the CLI and the desktop app are thin adapters over it. The deterministic spine writes an auditable artifact at every stage; the agent, RAG and LLM layers sit on top — opt-in, and never the source of truth. Everything runs locally: LTspice is a local subprocess, and only redacted, structured payloads ever leave the machine, only when cloud LLM is explicitly enabled.

FRONT-ENDS · THIN ADAPTERS CLI · emc-assistantargparse over service/ Desktop app · pywebviewApi bridge → service/ service/ — application coreuse-cases (project · context · parasitics · testbench · simulate · report · pipeline) · resolvers · CommandOptions DETERMINISTIC SPINE · AUDITABLE ARTIFACT PER STAGE netlist.cir parse · topology parasiticsper-net R·L·C bands testbenchLISN+cable+inject ltspicerunner · .raw/.log resultsdetectors · metrics · rank reportsmd · html · pdf OPT-IN LLM LAYER · ASSISTANT, NOT SOURCE OF TRUTH agents/11 specialists + orchestrator + synthesiser knowledge/ — RAGcurated rules · numpy vector index llm/ — provider seambudget cap · copyright redaction EXTERNAL · LOCAL FIRST LTspice — local subprocessuser-supplied · batch -b -Run · never bundled / hosted Cloud LLM — opt-in, key-gatedredacted structured egress · off by default · budget-capped runs redacted only

⌗ service/ is the product

One typed application core — a plain function per use case returning a result dataclass. Both front-ends are thin adapters, so behaviour can't drift between the CLI and the app.

▤ Auditable spine

Every stage writes a JSON/SPICE artifact under generated/ · results/ · reports/ — nothing is a black box, and the whole chain is reproducible from the inputs.

⛨ Local-first egress control

The deterministic core needs no network. Cloud LLM is opt-in and key-gated; every outbound payload is redacted (rule_id+summary, ≤200-char excerpt) and logged to results/llm/*.jsonl.

◷ Offline schema validation

A local referencing.Registry resolves every cross-$ref offline, so all artifacts are schema-validated without touching the network.

⌁ Structured logging seam

Components log under emc_assistant.<area> to a console handler, an optional per-run JSONL file, and a UI hook — replacing ad-hoc prints.

▦ Where it's going (M11)

A localhost service + thin client: the pipeline runs out-of-process so a UI crash can never lose a run, with pull-based logging and a content-aware freshness model. The service/ layer stays the core.

The desktop app

Screens, on real case_003 data

The pywebview shell reads the very same artifacts shown above. Below: the full app — left rail with pipeline gating, topbar and the active screen — then each screen on its own. (Renderings reproduce the live screens with real case_003 values.)

EMC Assistant — case_003_DCDC_eval — Results
Project / case_003_DCDC_eval / Results
topology DC/DC buckVin/Vout 12 / 3.3 Vpipeline report
🔒 cloud LLM OFF ⌘S · Save
Diagnostic · results/diagnostic.json · LLM · conf 70%

Switch-node (hot-loop) dv/dt likely dominates conducted EMI; differential-mode amplitude far exceeds common-mode.

DM dominantsimulated only
Band peak
47.1 dBµV
DM peak
20.85 V
CM peak
10.40 V
Corner span
~1.0 dB

↓ the detector spectrum, waveform analyzer and corner-variant ranking follow in the live screen

06 · Results — case_003_DCDC_eval
Diagnostic · results/diagnostic.json · LLM

Switch-node dv/dt likely dominates conducted EMI…

conf 70%DM dominant
Band peak
47.1 dBµV
DM peak
20.85 V
CM peak
10.40 V
Corner span
~1.0 dB

Corner ranking: 11 variants · worst par-trace-R…max 48.10 dBµV · baseline 47.08

03 · Parasitic selection
31 nets14 included17 skipped0 overrides
NetRoleTypeR mΩL nHC pF
■N003switchseries-RLC2.74.621.07
■OUTpowershunt-C7.623.44.02
■N007signalseries-RLC20.219.32.68
▢MP_01signalshunt-C20.219.32.68

Audit → 6 series · 7 shunt · 17 dropped (user) · 1 input-rail TRACE_RLC

04 · Testbench review — case_003_DCDC_eval

V_RAIL → LISN+ → cable → [TRACE_RLC] → DUT (31 nets) → LISN- · DM+CM probes

composed
Wiring audit
Supply VIN ↦ LISN ✓
Return 0 ↦ LISN ✓
Cable · default
LISN · dual DM+CM
Input-rail · 1 TRACE_RLC
Parasitics audit
Series RLC · 6 nets
Shunt-C · 7 nets
Dropped user · 17
Dropped AI · 0
Signal audit
Vout · V(OUT)
Vin · V(IN)

Actions: View testbench.cir · Continue to run → (auto-starts the pipeline)

07 · Findings & recommendations
Open 37Accepted 0Rejected 0All 37
HIGHfilteringInput LC may be undamped; DM emissions dominate.
HIGHdecouplingBand peak suggests insufficient HF bypass near the IC.

Accept / reject each → persisted to the report's decision log.

Honest-data guard
⚠These results are out of date. An input changed since this run — re-run the pipeline to refresh.  Re-run pipeline →

Edit any upstream input and the whole downstream chain is marked stale on the rail; Results, Findings and Report dim their numbers and show this banner. Stale data is never presented as current.

Versions & roadmap

Where it is, where it's going

Cloud model

OpenAI gpt-5-mini — opt-in, key-gated, budget-capped. Deterministic fallback when off.

Embeddings

Local sentence-transformers (POC) behind a pluggable interface; pure-numpy vector index.

Simulator

Your local LTspice (e.g. 26.0.2) — discovered, never bundled, never hosted.

M0 – M2.x
Deterministic core + LLM layer done

Schematic → testbench → variants → LTspice → metrics → ranking → report; per-net parasitics, 11 agents, RAG, redaction, CISPR-like diagnostic metrics and configured reference curves.

M3
Desktop UI done

pywebview shell over the service core — Projects → Report wired to real artifacts, with the stale-data guard.

M10
CM-coupling model planned

CSTRAY → earth, so the common-mode metrics and plot carry a real deterministic signal.

M11
UI rebuild planned

From-the-studs remake: localhost service + thin client, out-of-process pipeline, content-aware freshness, large-.raw streaming, pre-run cost/privacy gate.

M12
Live Lab Assistant planned

Overlay a live EMI-receiver spectrum on the simulated prediction; real-time attribution to a specific parasitic.

M13
Engineer Training planned

Your estimated→corrected overrides become opt-in, federated, redacted training signal — the tool improves with use.

To add & improve

The honest backlog

What's known to be missing or rough, kept in the open. Everything below is planned or a tracked caveat — not yet shipped.

⎍ Selectable detector + narrow-harmonic accuracy planned

The canonical receiver-like sweep (Mode 3, 128 pts) under-reads narrow harmonics that fall between swept points. Make detector mode / start-skip / point density user-selectable, and root-cause the skip anomaly.

⌬ Schematic-understanding agent M4

The tool netlists but doesn't yet understand the schematic — net roles are heuristic. Label power stage, high/low-side switches, SW node, hot loop and rails as user-confirmable, sourced hypotheses.

≈ EMI-filter design / optimization agent M4

Diagnose DM/CM noise from the detector result, size a π-filter / CM choke (banded, with Y-cap leakage + damping guards), and close the loop: inject → re-simulate → adjust to meet the limit.

⚙ Device-aware sim-setup agent M4

Infer the switching-edge rate from the FET part / topology + KB, so fast-edge devices get a device-aware timestep verdict without the user supplying a rise time.

⊕ Variant-review / proposal agent M4

Review whether the min/typ/max corner sweep covers the uncertainty and propose additional sensitivity / what-if variants as an accept/skip list — additive only, never replacing the deterministic baseline.

⌁ Conversational parasitics-strategy chat M5

Direct strategy in natural language ("add a series L to every net with a 10 pF shunt"); the LLM proposes RAG-grounded per-net edits as a reviewable diff — never a silent mutation.

⚿ Common-mode coupling model M10

Opt-in, dual-LISN-only stray capacitance to earth from high-dv/dt nets, so the CM metrics and CM detector plot carry real deterministic signal (today they exist but are inert).

⛨ Security & privacy hardening review M9

A cross-cutting assurance pass before wider distribution: redaction-path audit + outbound-payload guard, key-never-logged, bridge path-traversal review, parser fuzzing, CSP, and a pip-audit scan.

▦ UI rebuild — out-of-process M11

Localhost service + thin client: crash-isolated runs, pull-based log streaming, content-aware freshness, large-.raw streaming, a faithful per-net testbench render, and a pre-run cost/privacy gate.

∿ Transient-event detection & auto-window planned

Detect max |di/dt| / turn-on inrush and auto-size the .tran window so a slow turn-on event isn't truncated — distinct from the steady-state conducted-EMI run.

⤓ .raw fastaccess + multi-LISN CM planned

Support LTspice fastaccess-format .raw and a real two-LISN V(CM) (today single-LISN V(CM) is a placeholder).

▣ Pro & layout tracks M6 / M7

Project history beyond one project, richer stack-up / cable profiles, daily/monthly budget caps (M6); layout import, parasitic extraction and radiated-risk estimation (M7).

Demo workflow

A worked example, end to end

The bundled case_003 example walks the whole pipeline on a DC/DC buck converter — so you can see the shape of a run before pointing it at your own project.

01 · circuit

DC/DC converter + input cable

A buck converter (12 → 3.3 V) with an input cable and a LISN at the supply — the conducted-EMI measurement setup, in simulation.

02 · model

Parasitic sweep

Per-net min·typ·max parasitics are estimated and injected, then swept so the result is an honest spread rather than a single "certain" number.

03 · compare

Filter variants

EMI filter variants are compared and ranked against the configured reference curve to show which direction reduces risk.

⚠
In this example the diagnostic flags a low-frequency exceedance above the configured reference curve in this simulation. That is a pre-compliance hypothesis, not a verdict — it tells you where to look on the bench, and requires lab verification.
Scope

What EMC-Assist is not

Being clear about the boundaries is part of being honest. EMC-Assist is a pre-compliance engineering aid — it is deliberately none of the following.

✕  Not a certified EMC receiver

The metrics are quasi-peak-like diagnostics, not a calibrated CISPR-16 receiver reading.

✕  Not a replacement for lab testing

Every result is an engineering hypothesis that requires laboratory verification.

✕  Not a standards-compliance tool

It does not certify compliance with any standard and ships no paid standards.

✕  Not an official LTspice plugin

Independent project. LTspice is user-supplied and runs locally; it is never bundled, hosted, or modified.

✕  Not a schematic / layout editor

It reads your netlist and composes a testbench — it does not draw or edit your board.

✕  Not a cloud SaaS

Local-first by default. There is no account, no subscription, and no required cloud service.

Getting started

Run the demo locally

The shape of a first run. See the documentation for exact, verified commands — the steps below are an outline, not copy-paste commands.

Outline · example placeholders
  1. Clone the repository
  2. Install the Python package
  3. Point EMC-Assist at your local LTspice install
  4. Run a bundled demo project
  5. Open the generated pre-compliance report
You'll need
LTspiceuser-supplied · local
Pythoncore package
Cloud LLMoptional · off by default
Networknot required for a run

The deterministic core runs with the LLM layer entirely off — it is an assistant, never the source of truth.

⚠
Pre-compliance only. Every output is an engineering hypothesis requiring laboratory verification — never a guarantee that a design will pass formal EMC. Simulation does not replace accredited EMC laboratory measurement. The tool speaks in “reduces risk”, “may improve”, “requires verification”. Independent open-source project — LTspice is user-supplied and runs locally; results are engineering diagnostics, not certification.