Finished the board including the connector and mousebites
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
---
|
||||
name: kicad-manufacturing-export
|
||||
description: Use when regenerating or exporting the BOM CSV, CPL/position CSV, or Gerbers+drill zip for a KiCad PCB project via kicad-cli (e.g. "regenerate the gerbers", "update the BOM and CPL", "re-export for JLCPCB"). Covers the exact kicad-cli invocations and column formats this project's ordering files expect, and the CPL rotation-correction trap (regenerating the position file the naive way silently wipes hand-verified assembly rotation fixes). KiCad 8/9/10, JLCPCB-style deliverables.
|
||||
---
|
||||
|
||||
# Regenerating BOM / CPL / Gerbers via kicad-cli
|
||||
|
||||
For the `re-bba-rb` board specifically, deliverables live in
|
||||
`hardware/re-bba-rb/`: `re-bba-rb-bom.csv`, `re-bba-rb-cpl.csv`,
|
||||
`gerbers/rebbarb.zip`. Adjust paths/output names for other boards, but the
|
||||
gotchas below (especially the CPL rotation trap) apply generally.
|
||||
|
||||
## 1. Gerbers + drill + zip
|
||||
|
||||
```bash
|
||||
cd hardware/re-bba-rb
|
||||
kicad-cli pcb export gerbers --board-plot-params -o gerbers/ re-bba-rb.kicad_pcb
|
||||
kicad-cli pcb export drill --format excellon --excellon-separate-th \
|
||||
--excellon-units mm -o gerbers/ re-bba-rb.kicad_pcb
|
||||
```
|
||||
|
||||
`--board-plot-params` reuses whatever layer/plot settings are already stored
|
||||
in the board file — don't hand-pick layers, this reproduces exactly what was
|
||||
there before. `--excellon-separate-th` splits plated/non-plated holes into
|
||||
`*-PTH.drl` / `*-NPTH.drl`, matching the existing file-naming convention.
|
||||
|
||||
Then re-zip (excluding the previous zip itself, so it's not nested inside
|
||||
its own replacement):
|
||||
|
||||
```python
|
||||
import zipfile, os
|
||||
folder = 'gerbers'
|
||||
files = sorted(f for f in os.listdir(folder) if f != 'rebbarb.zip')
|
||||
with zipfile.ZipFile(os.path.join(folder, 'rebbarb.zip'), 'w', zipfile.ZIP_DEFLATED) as z:
|
||||
for f in files:
|
||||
z.write(os.path.join(folder, f), arcname=f)
|
||||
```
|
||||
|
||||
kicad-cli's gerber export also produces a `*-job.gbrjob` metadata file
|
||||
alongside the layer files — include it in the zip, it's harmless and some
|
||||
fabs use it for auto-configuration.
|
||||
|
||||
## 2. BOM
|
||||
|
||||
```bash
|
||||
kicad-cli sch export bom \
|
||||
--fields "ITEM_NUMBER,Reference,Value,Footprint,MPN,LCSC,QUANTITY,DNP,Manufacturer" \
|
||||
--labels "Item,Designator,Value,Footprint,MPN,LCSC,Qty,DNP,Manufacturer" \
|
||||
--group-by "Value,Footprint,MPN,LCSC,Manufacturer" \
|
||||
--sort-field "Reference" \
|
||||
--ref-range-delimiter "" \
|
||||
-o re-bba-rb-bom.csv \
|
||||
re-bba-rb.kicad_sch
|
||||
```
|
||||
|
||||
`--ref-range-delimiter ""` disables range compression (`C18-C20` becomes
|
||||
`C18,C19,C20`) — this project's existing BOM convention is flat comma lists,
|
||||
not ranges; drop this flag if the target format wants ranges instead.
|
||||
`--group-by` on those 5 fields means any two components sharing value +
|
||||
footprint + MPN + LCSC + manufacturer collapse into one row (with a combined
|
||||
`Qty`) — this is how e.g. adding a new part that happens to match an
|
||||
*already-used* part (same value/footprint/MPN) merges into an existing BOM
|
||||
line instead of creating a new one, which is usually what you want (no new
|
||||
line item added to the order).
|
||||
|
||||
Reference-only / non-purchasable footprints (gold-finger connectors, mouse-bite
|
||||
NPTH-hole footprints, etc.) are excluded automatically via `in_bom no` on the
|
||||
schematic symbol (or `exclude_from_bom` in the footprint's `attr`) — don't
|
||||
try to filter them out in the export command itself.
|
||||
|
||||
**Verify after export**: diff the new BOM against the old one and sanity-check
|
||||
that only expected rows changed — an unexpectedly *shorter* BOM (fewer
|
||||
component rows/refs than before) is the signature of the
|
||||
[kicad-bom-edit](../kicad-bom-edit/SKILL.md) skill's "malformed property
|
||||
silently drops a whole sheet" bug, not a real BOM change.
|
||||
|
||||
## 3. CPL / position file — the rotation trap
|
||||
|
||||
```bash
|
||||
kicad-cli pcb export pos --format csv --units mm --side both --exclude-dnp \
|
||||
-o /tmp/pos_raw.csv re-bba-rb.kicad_pcb
|
||||
```
|
||||
|
||||
kicad-cli's own CSV columns (`Ref,Val,Package,PosX,PosY,Rot,Side`) don't match
|
||||
JLCPCB's expected format (`Designator,Mid X,Mid Y,Layer,Rotation`, with
|
||||
`Layer` capitalized `Top`/`Bottom`, not lowercase `top`/`bottom`). Transform:
|
||||
|
||||
```python
|
||||
import csv
|
||||
with open('/tmp/pos_raw.csv', newline='') as f:
|
||||
rows = list(csv.DictReader(f))
|
||||
with open('re-bba-rb-cpl.csv', 'w', newline='') as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerow(['Designator', 'Mid X', 'Mid Y', 'Layer', 'Rotation'])
|
||||
for r in rows:
|
||||
layer = 'Top' if r['Side'].strip().lower() == 'top' else 'Bottom'
|
||||
writer.writerow([r['Ref'], f"{float(r['PosX']):.6f}",
|
||||
f"{float(r['PosY']):.6f}", layer,
|
||||
f"{float(r['Rot']):.6f}"])
|
||||
```
|
||||
|
||||
**Then — before treating this as done — reapply every correction in
|
||||
[`hardware/re-bba-rb/CPL_ROTATIONS.md`](../../../hardware/re-bba-rb/CPL_ROTATIONS.md).**
|
||||
KiCad's raw per-footprint rotation frequently does not match what the
|
||||
assembler expects (arbitrary per-footprint authoring reference vs. the
|
||||
assembler's actual placement convention), and this has already been
|
||||
hand-verified part-by-part against JLCPCB's placement-preview render for
|
||||
this board. Regenerating the position file "the normal way" silently
|
||||
overwrites those fixes back to (wrong) raw values — there is no automated
|
||||
check that catches this, so it's easy to quietly ship a regression. Read
|
||||
that file's sign-convention note before applying anything (short version:
|
||||
"N degrees clockwise" feedback means *subtract* N in the CPL's Y-up frame,
|
||||
not add it).
|
||||
|
||||
Do **not** reach for a generic community rotation-correction table (e.g.
|
||||
`cpl_rotations_db.csv` from JLCKicadTools) as a shortcut — one was tried on
|
||||
this board and found wrong for at least one package family (claimed
|
||||
`LQFP-: 270°`; this board's actual correct value is 0°, unmodified). That
|
||||
table is calibrated against a specific plugin's own raw-rotation baseline,
|
||||
which is not the same as `kicad-cli`'s raw CSV baseline (different Y-axis
|
||||
handling) — the numbers don't transfer.
|
||||
|
||||
## Quick full-refresh recipe
|
||||
|
||||
1. Gerbers/drill/zip: regenerate + re-zip (section 1) — safe to always redo,
|
||||
no hidden state to lose.
|
||||
2. BOM: regenerate (section 2) — safe to always redo. Diff-check the row
|
||||
count.
|
||||
3. CPL: regenerate raw (section 3), **then reapply CPL_ROTATIONS.md** before
|
||||
calling it current.
|
||||
4. Run ERC (`kicad-cli sch erc --severity-all`) and DRC
|
||||
(`kicad-cli pcb drc --severity-all`) after any schematic/PCB change that
|
||||
prompted the refresh — not the export step itself, but worth confirming
|
||||
nothing regressed if this was bundled with other edits.
|
||||
Reference in New Issue
Block a user