5.4 KiB
name, description
| name | description |
|---|---|
| kicad-bom-edit | Use when adding or editing BOM/part fields (MPN, LCSC, Manufacturer, tolerance, voltage/current ratings, DNP) on KiCad .kicad_sch symbols by hand or script, or when a kicad-cli BOM export is missing parts. Covers safe property insertion, the "malformed property silently drops a whole sheet" pitfall, and the netlist-vs-BOM count verification that catches it. KiCad 7/8/9/10 S-expression schematics. |
Editing KiCad schematics for BOM
Adding manufacturer part numbers (MPN), LCSC codes, ratings, etc. to a KiCad
.kicad_sch so the BOM can be ordered/assembled (e.g. JLCPCB). Prefer the
KiCad GUI (Symbol Fields Table / per-symbol properties) — it can't corrupt the
file. Only hand/script-edit when the GUI isn't available, and then follow this
exactly.
How symbols store fields
Each placed symbol is (symbol (lib_id ...) (at ...) ... <properties> <pins> (instances ...)).
A field is a property, a direct child of the symbol:
(property "MPN" "FNR4018S3R3MT"
(at 139.7 87.63 0)
(hide yes)
(show_name no)
(do_not_autoplace no)
(effects (font (size 1.27 1.27)))
)
Properties Reference, Value, Footprint, Datasheet, Description are
mandatory; MPN/LCSC/Manufacturer/V/Type/Current/etc. are custom BOM
fields. Field names must be unique within a symbol. kicad-cli sch export bom --fields '...' selects which show up as columns.
⚠️ THE PITFALL: a malformed property silently drops the WHOLE sheet
New BOM fields must be siblings of Value (direct children of the symbol) —
NOT nested inside another property. If you accidentally place them inside the
Value property, kicad-cli sch export bom will silently omit every component
on that sheet — no warning, exit code 0 — while kicad-cli sch export netlist
still parses fine and shows nothing wrong. A whole page of parts (regulators,
connectors…) can vanish from the BOM you send to the fab.
Root cause seen in practice: naive regex insertion. Property indentation
varies by file (some use 2 tabs for (property, some 1). A regex like
.*?\n\t\t\t\) grabs the first 3-tab close — which is the inner effects/font
close, not the property's own close — so the insert lands inside Value.
Safe insertion (script)
- Match the entire target property block by balanced parens, keyed on its
unique content (e.g.
Value= "2.2uH" at a known(at ...)), from the(property "Value"line to its own closing paren at the property's indent level. Don't rely on a fixed tab count guessed from another file — detect the file's actual property indentation first. - Insert new
(property ...)blocks after that close, at the same indent level asValue(siblings), with children one level deeper. - Keep every block paren-balanced (each
(property/(effects/(fonthas its close).
Robust pattern (Python) — replace the whole Value block and append siblings:
import re
src=open(f).read()
# whole L1 Value property: 2-tab property line, 3+tab children, 2-tab close
pat=re.compile(r'\t\t\(property "Value" "2\.2uH"\n(?:\t\t\t.*\n)*?\t\t\)\n')
m=pat.search(src)
def prop(n,v):
return (f'\t\t(property "{n}" "{v}"\n\t\t\t(at 139.7 87.63 0)\n\t\t\t(hide yes)\n'
f'\t\t\t(show_name no)\n\t\t\t(do_not_autoplace no)\n\t\t\t(effects\n\t\t\t\t(font\n'
f'\t\t\t\t\t(size 1.27 1.27)\n\t\t\t\t)\n\t\t\t)\n\t\t)\n')
block=m.group(0).replace('"2.2uH"','"3.3uH"') # keep Value block intact
add=prop("MPN","FNR4018S3R3MT")+prop("LCSC","C167805")+prop("Manufacturer","cjiang")
src=src[:m.start()]+block+add+src[m.end():]
open(f,'w').write(src)
(Whitespace inside S-expressions is not significant to KiCad — matching indent is only for legibility and to hit the right closing paren. KiCad rewrites formatting on its next save.)
✅ ALWAYS verify: netlist component count must equal BOM row count
This is the check that catches the silent-drop bug. After any schematic edit:
kicad-cli sch export netlist --format kicadsexpr -o /tmp/n.net project.kicad_sch
kicad-cli sch export bom --fields 'Reference,Value,MPN,LCSC' -o /tmp/b.csv project.kicad_sch
# count components in each; they MUST match
Parse the netlist (components (comp (ref ...))) for the ref set, and the BOM
CSV first column for its ref set, and print the difference. If the BOM set is
smaller, some sheet was dropped — you have a malformed property. Confirm the
specific row (grep '"L1"' /tmp/b.csv) shows its new fields populated.
Dual-project-instance sheets
A sub-sheet that was once its own standalone project (e.g. Power.kicad_sch
reused in re-bba-rb) has (instances (project "power" ...) (project "re-bba-rb" ...)) on each symbol. This is normal, but it makes such sheets
extra-sensitive to malformed properties in BOM export — always run the
count check after editing these.
Part selection for JLCPCB / LCSC
- Fill
MPN,Manufacturer, and theLCSCC-number (e.g.C167805) — the LCSC code is what JLC assembly needs. Don't invent C-numbers; verify each on lcsc.com / jlcpcb.com/parts (existence, stock, Basic vs Extended — Extended = small one-time fee). - For power inductors, record and check Isat (saturation ≥ peak current) and Irms; a value/footprint alone isn't enough.
- Match the field-naming already used in the project (this repo uses
V,Type,Current,MPN,LCSC,Manufacturer).