5.7 KiB
KiCad → Stencil G-code pipeline
Automates the conversion of a KiCad v9 F.Paste and B.Paste Gerber to G-code for CNC milling a solder paste stencil, using FlatCAM beta 8.995 headless. Tested on Ubuntu 24.04 with Python 3.12 and a Frezu 3040 / FluidNC controller.
This project shares a single FlatCAM install (~/flatcam-beta) with other kicad2* pipelines (e.g. kicad2outlines). Install FlatCAM once; each project just points to it.
Prerequisites
- Ubuntu 24.04
- Python 3.10–3.12
- KiCad v9
- A flat end mill (corn bit), 0.5 mm recommended
Installation
1. System dependencies
sudo apt install python3-venv python3-pip libgeos-dev libspatialindex-dev libxcb-cursor0
2. Install FlatCAM beta 8.995 (shared, once)
If ~/flatcam-beta already exists, skip to step 3 — there's nothing to do here.
git clone --branch mstanciu_Beta_8.995 --depth 1 https://github.com/dwrobel/flatcam.git ~/flatcam-beta
cd ~/flatcam-beta
python3 -m venv .flatcam-env
source .flatcam-env/bin/activate
pip install PyQt6 PyQt6-Qt6 PyQt6-sip
# Skip ortools (path optimizer), rasterio, and gdal (image import) — not needed for stencils/outlines
grep -vE "ortools|rasterio|gdal" requirements.txt | pip install -r /dev/stdin
deactivate
3. Verify
~/flatcam-beta/.flatcam-env/bin/python ~/flatcam-beta/flatcam.py --version
You should see the FlatCAM version string printed without errors.
4. Point this project at the shared install
run_stencil.sh reads the FLATCAM_HOME environment variable, defaulting to ~/flatcam-beta if unset. Override it only if your install lives elsewhere:
export FLATCAM_HOME=~/flatcam-beta # default, usually no need to set this
5. Export the stencil gerbers
Export the gerber layers F.Paste and B.Paste
kicad-cli pcb export gerbers -o gerbers -l F.Paste,B.Paste ../kicad2panel/panel/Flow_Controller_Panel.kicad_pcb
Usage
Generate the stencil G-code for the layer F.Paste:
./run_stencil.sh gerbers/Flow_Controller_Panel-F_Paste.gtp \
gcode/Flow_Controller_Panel-F_Paste-stencil.nc
It should output:
→ Running FlatCAM headless...
Gerber : gerbers/Flow_Controller_Panel-F_Paste.gtp
Output : gcode/Flow_Controller_Panel-F_Paste-stencil.nc
✓ Done: gcode/Flow_Controller_Panel-F_Paste-stencil.nc (277 lines)
Generate the stencil G-code for the layer B.Paste:
./run_stencil.sh gerbers/Flow_Controller_Panel-B_Paste.gbp \
gcode/Flow_Controller_Panel-B_Paste-stencil.nc
It should output:
→ Running FlatCAM headless...
Gerber : gerbers/Flow_Controller_Panel-B_Paste.gbp
Output : gcode/Flow_Controller_Panel-B_Paste-stencil.nc
✓ Done: gcode/Flow_Controller_Panel-B_Paste-stencil.nc (1895 lines)
Parameters
All cutting parameters are at the top of paste_stencil.tcl:
| Variable | Default | Description |
|---|---|---|
TOOL_DIA |
0.5 |
End mill diameter in mm |
CUT_Z |
-0.2 |
Cutting depth in mm (negative). Set slightly past material thickness |
TRAVEL_Z |
2.0 |
Safe travel height in mm |
FEEDRATE |
120 |
XY feed rate in mm/min |
SPINDLE |
24000 |
Spindle speed in RPM |
OVERLAP |
60 |
Tool overlap in % — higher = cleaner clearing, more paths |
MARGIN |
0.0 |
Inset from aperture edge in mm. 0 = cut to exact pad size |
Depth by material
| Material | Thickness | CUT_Z |
SPINDLE |
FEEDRATE |
|---|---|---|---|---|
| Brass shim (CW614N) | 0.15 mm | -0.18 | 24000 RPM | 120 mm/min |
| Polyimide (Kapton) | 0.10 mm | -0.13 | 24000 RPM | 300 mm/min |
| Stainless steel shim | 0.15 mm | -0.18 | 16000 RPM | 60 mm/min |
Preprocessor
The script uses the GRBL_11 preprocessor (-pp GRBL_11 in paste_stencil.tcl), which produces grbl 1.1 compatible G-code. FluidNC implements the grbl protocol so this works directly with no modifications.
Alternative: GRBL_11_no_M6 suppresses tool change commands — not needed for a single-tool stencil job but harmless either way.
Workholding notes
- Stencil material is thin and will flex — use double-sided tape on a flat spoilboard
- Zero Z directly on the stencil surface, not the spoilboard
- For brass shim, clamp the edges with small clips if the tape isn't holding — chatter from an unanchored sheet ruins aperture quality
Troubleshooting
FlatCAM hangs after writing G-code
The run_stencil.sh wrapper detects the TclCommandQuit log line and kills the process after 3 seconds. This is expected behavior — FlatCAM's Qt GUI cleanup hangs in headless mode.
ImportError: cannot import name 'Inf' from numpy
You have the old PyPI FlatCAM 8.5 installed somewhere on your PATH/venv. Make sure FLATCAM_HOME points at ~/flatcam-beta (the beta 8.995 clone from the install steps above), not a pip-installed FlatCAM.
ImportError: cannot import name 'cascaded_union' from shapely.ops
Same cause — old FlatCAM 8.5 is incompatible with Shapely 2.0. Check FLATCAM_HOME as above.
G-code cuts everything except the pads
You used ncc (non-copper clear) instead of paint. The correct command is paint — it pockets the pad polygons. ncc clears everything around them, which is the inverse.
gdal fails to install
Skip it — gdal is only needed for the image import plugin. Use:
grep -vE "ortools|rasterio|gdal" requirements.txt | pip install -r /dev/stdin
Multiple projects, which one owns the FlatCAM install?
None of them — ~/flatcam-beta is shared and project-agnostic. Install it once via any one project's instructions above; every other kicad2* project just needs FLATCAM_HOME set (or left at its default) to find it. Don't git clone a second copy per project.