Skip to content

Instantly share code, notes, and snippets.

@salkinium
Last active July 29, 2020 18:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save salkinium/0c588d4652c1f33850caa234b04cbe6f to your computer and use it in GitHub Desktop.
Save salkinium/0c588d4652c1f33850caa234b04cbe6f to your computer and use it in GitHub Desktop.
Python script to generate Gerber ZIP files from KiCAD files in the right format for JLCPCB
#!/Applications/Kicad/kicad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python
import sys
sys.path.insert(0,"/Applications/Kicad/kicad.app/Contents/Frameworks/python/site-packages/")
import os
import shutil
import zipfile
import tempfile
import pcbnew
output, dependency, = sys.argv[1:]
print("Gerberizing '{}'".format(output))
board = pcbnew.LoadBoard(dependency)
with_silkscreen = True # Silkscreen makes the boards slightly thicker
with_paste = True
with_4layers = board.GetDesignSettings().GetCopperLayerCount() == 4
# Configure plotter
pctl = pcbnew.PLOT_CONTROLLER(board)
popt = pctl.GetPlotOptions()
# Set some important plot options
popt.SetPlotFrameRef(False)
popt.SetLineWidth(pcbnew.FromMM(0.05))
popt.SetAutoScale(False)
popt.SetScale(1)
popt.SetMirror(False)
popt.SetUseGerberAttributes(False)
popt.SetUseGerberProtelExtensions(True)
popt.SetExcludeEdgeLayer(True)
popt.SetUseAuxOrigin(False)
popt.SetDrillMarksType(pcbnew.PCB_PLOT_PARAMS.NO_DRILL_SHAPE)
popt.SetSkipPlotNPTH_Pads(True)
# Render Plot Files
tempdir = tempfile.mkdtemp()
popt.SetOutputDirectory(tempdir)
plot_plan = [
( "F_Cu", pcbnew.F_Cu, "Top layer" ),
( "B_Cu", pcbnew.B_Cu, "Bottom layer" ),
( "F_Mask", pcbnew.F_Mask, "Mask top" ),
( "B_Mask", pcbnew.B_Mask, "Mask bottom" ),
( "Edge_Cuts", pcbnew.Edge_Cuts, "Edges" ),
]
if with_4layers:
plot_plan += [
( "In1_Cu", pcbnew.In1_Cu, "Top internal layer" ),
( "In2_Cu", pcbnew.In2_Cu, "Bottom internal layer" ),
]
if with_silkscreen:
plot_plan += [
( "F_Silk", pcbnew.F_SilkS, "Silk top" ),
( "B_Silk", pcbnew.B_SilkS, "Silk top" ),
]
if with_paste:
plot_plan += [
( "F_Paste", pcbnew.F_Paste, "Paste top" ),
( "B_Paste", pcbnew.B_Paste, "Paste Bottom" ),
]
for layer_info in plot_plan:
pctl.SetLayer(layer_info[1])
pctl.OpenPlotfile(layer_info[0], pcbnew.PLOT_FORMAT_GERBER, layer_info[2])
pctl.PlotLayer()
# Render Drill Files
drlwriter = pcbnew.EXCELLON_WRITER(board)
drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_GERBER)
drlwriter.SetOptions(aMirror=False, aMinimalHeader=False,
aOffset=pcbnew.wxPoint(0, 0), aMerge_PTH_NPTH=False)
drlwriter.SetFormat(True, pcbnew.EXCELLON_WRITER.DECIMAL_FORMAT, 3, 3)
drlwriter.CreateDrillandMapFilesSet( pctl.GetPlotDirName(), True, False );
pctl.ClosePlot()
# Archive files
files = os.listdir(tempdir)
with zipfile.ZipFile(os.path.join(tempdir, "zip"), 'w', zipfile.ZIP_DEFLATED) as myzip:
for file in files:
myzip.write(os.path.join(tempdir, file), file)
os.rename(os.path.join(tempdir, "zip"), output)
# Remove tempdir
shutil.rmtree(tempdir)
@salkinium
Copy link
Author

Raw usage:

# This path is specific to MacOS, couldn't find a path independent way of calling this outside KiCAD
KICAD_PYTHON=/Applications/Kicad/kicad.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python

${KICAD_PYTHON} gerberize.py path/to/zipfile.zip path/to/pcb.kicad_pcb

Example usage within Makefile:

pcb/gerber/%.zip: pcb/panel/%.kicad_pcb pcb/gerber/generate.py
    @${KICAD_PYTHON} pcb/gerber/generate.py $@ $<

.PHONY: generate_pcb_gerbers
generate_pcb_gerbers:	pcb/gerber/mast_ks_rechts.zip pcb/gerber/mast_ks_rechts_zs3v.zip path/to/more.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment