Skip to content

Add practical gotchas found while scripting a real MCU schematic - #4

Open
shingo257 wants to merge 8 commits into
American-Embedded:mainfrom
shingo257:skill-improvements
Open

shingo257 wants to merge 8 commits into
American-Embedded:mainfrom
shingo257:skill-improvements

Conversation

@shingo257

Copy link
Copy Markdown

Found while using kicad-schematic/kicad-symbol to build a real STM32G474VETx (LQFP100) node-controller schematic for an unrelated project. Everything here is a thing that actually went wrong once and cost time to diagnose:

  • kicad-python's IPC API doesn't work against KiCad 10.0.5 in practice (import succeeds, get_open_documents() doesn't) — documented a fallback: script the .kicad_sch S-expression text directly, validate with kicad-cli sch erc + renders. Included the coordinate transform (abs = inst + local_x, inst - local_y at rotation 0) that makes hand/script-authored placement tractable instead of guesswork — verified empirically via an ERC report rather than assumed.
  • Labels must land on the exact wire/pin coordinate or ERC reports label_dangling/unconnected_wire_endpoint, even though the rendered image looks completely fine. Cost 22 dangling labels in one pass from a 0.5mm "just for readability" offset.
  • Decoupling caps wired in series (pin → cap → rail, instead of pin → rail with the cap branching off separately to ground) render identically to the correct wiring but leave the pin floating at DC. power_pin_not_driven/ground_pin_not_ground is what actually catches it — worth calling out since it's easy to get backwards when a script is drawing wires without a live visual editor giving instant feedback.
  • PWR_FLAG near a rail but not wired onto it still trips power_pin_not_driven — proximity isn't the same as connectivity.
  • A practical review tip: when an image tool can't preview a large rendered SVG, export PDF instead, or temporarily shrink the page to a custom size ((paper "User" w h)) that tightly wraps just the review area, so the same fixed image resolution shows more detail.
  • kicad-symbol: noted that (extends "Base") symbols — e.g. KiCad's own MCU_ST_* libraries — need flattening into a standalone symbol before they can go in a schematic's lib_symbols block, with a short description of the approach (parse both symbols, merge properties with the derived symbol's overrides winning, rename the base's sub-units).

🤖 Generated with Claude Code

shingo257 and others added 8 commits September 6, 2026 15:24
…atic

Working on a real multi-part MCU node board (STM32G474VETx, LQFP100)
surfaced a few things worth capturing:

- kicad-python's IPC API is broken against KiCad 10.0.5's own server in
  practice (import succeeds, get_open_documents() doesn't); documented a
  script-the-.kicad_sch-directly-and-verify-with-ERC fallback workflow,
  plus the coordinate transform that makes that tractable instead of
  guesswork.
- Labels need to land on the exact wire/pin coordinate or ERC reports
  label_dangling/unconnected_wire_endpoint even though the render looks
  fine -- easy mistake when a script nudges a label for "readability".
- Decoupling caps wired in series between a pin and its rail (instead of
  a parallel branch to ground) render identically to correct wiring but
  leave the pin floating at DC; ERC's power_pin_not_driven /
  ground_pin_not_ground is what actually catches it.
- A PWR_FLAG placed near a rail but not actually wired onto it still
  trips power_pin_not_driven.
- A practical tip for reviewing large schematics when an image tool
  chokes on a big SVG: temporarily shrink the page to a custom size that
  wraps just the review area, for more effective detail per pixel.
- kicad-symbol: symbols using (extends "Base") -- common in ST's own
  KiCad MCU libraries -- need flattening into a standalone symbol before
  they can go in a schematic's lib_symbols block; noted the approach.
… a Value override

Follow-up finding from the same OMNI-SENSE node schematic work: went to
add a second isolated-domain power net (OMNI_+3V3_ISO etc.) by copying
the existing "just rename a power symbol" advice -- overrode the
instance's Value property while leaving lib_id pointed at +3V3/GND (or,
worse, pointed lib_id straight at the new name with nothing defining
it). Every instance came back as its own single-node net instead of
merging, confirmed by exporting a netlist and reading it directly.
The actual fix is a real duplicated symbol *definition* under the new
name in lib_symbols. Also note the annotation-check gotcha discovered
along the way (kicad-cli sch export netlist warns and continues on an
unannotated schematic -- easy to miss since nothing fails loudly).
Third follow-up from the same OMNI-SENSE LTC2984 interface work: two
decoupling/bypass nets (LDO output, VREF bypass) sat on pins only
5.08mm apart on the same IC edge. Both used the same fixed stub
distance to clear the body, landing their vertical wire runs at the
identical x. Since one run's y-range overlapped the other's, they
touched at a coincident point and merged into one net -- caught via
netlist export showing a 2-pin capacitor's own two pins sharing a net
(shorted). Different stub lengths per net avoids it.
Document KiCad 10 + Windows agent pitfalls: kicad-cli full path,
annotation warnings on netlist export, pcbnew Remove/SWIG crashes,
pad+copper remapping after schematic net renames, and MCP footprint
parity false positives when instance Footprint fields are blank.

Co-authored-by: Cursor <cursoragent@cursor.com>
…umber

Fourth follow-up from the OMNI-SENSE work: a hand-authored PCAL6524
symbol had its INT pin typed "output" (push-pull) when NXP's datasheet
specifies open-drain. Wiring it to another chip's genuinely open-drain
alert pin on the same net produced ERC's pin_to_pin type-conflict
warning, which is what actually caught the mistake -- the wiring was
fine, the symbol's declared pin type was wrong.
…-vs-content sizing

Findings from OMNI-SENSE's I2C sensor cluster + isolation barrier layout
pass (2026-09-07), driven by a user-reported "net names overlapping pins"
bug, fixed via mechanical SVG text-bbox overlap detection rather than
visual inspection alone:

- A label's text anchors at the stub's far end and reads back toward the
  pin (verified from the exported SVG's own text-anchor position), so a
  long net name on a short stub overshoots into the IC's own pin-name
  text or a neighbour's label -- stub length needs to scale with name
  length, not use one fixed default for every label on a sheet.
- Multiple pins at the exact same local (x, y) in a symbol's pin table
  (vendor-ganged IN/GND/OUT pins) are already electrically joined by one
  wire touching that point -- drawing a separate wire+symbol per
  duplicate pin adds visual clutter, not connectivity.
- A block's own bounding box has to fit inside the sheet's declared
  paper size, or it lands off-page or under the auto-placed title block
  -- checked incrementally as content grows, not just visually at
  "fit whole page" zoom.
- A shared decoupling branch off a pin at the edge of a tight pin column
  should extend away from the column (into open space), not further
  along the same axis parallel to the other pins it needs to clear.
- A reusable technique for actually verifying "no overlapping text" on a
  dense sheet: parse the exported SVG's own <text> x/y/textLength/
  font-size/text-anchor into real bounding boxes and check pairwise
  intersection, instead of eyeballing a render.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
From OMNI-SENSE's relay-driver subcircuit (4x identical relay+TVS+
connector blocks stacked in a column, 2026-09-07): fixing a same-block
label collision by lengthening one pin's stub repeatedly pushed the
fix into colliding with the *next* repetition's own labels instead --
a whack-a-mole loop the stub-length lesson from the previous commit
doesn't by itself warn against. Widening the inter-block pitch first
(so no stub length, however long, can reach the next repetition) turned
out to be the actual fix, with per-pin stub tuning only needed for
collisions within a single repetition after that.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Document moving passives when corridors fail structural DRC, and the
correct kicad-cli --severity-all JSON gate used on Omni-Harvester Phase1.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant