def _renderBoards(self, outputDirectory): """ Convert all boards to images and gerber exports. Enrich self.boards with paths of generated files """ pcbdraw = shutil.which("pcbdraw") if not pcbdraw: raise RuntimeError("PcbDraw needs to be installed in order to render boards") dirPrefix = "boards" boardDir = os.path.join(outputDirectory, dirPrefix) Path(boardDir).mkdir(parents=True, exist_ok=True) for boardDesc in self.boards: boardName = os.path.basename(boardDesc["source"]).replace(".kicad_pcb", "") boardDesc["front"] = os.path.join(dirPrefix, boardName + "-front.png") boardDesc["back"] = os.path.join(dirPrefix, boardName + "-back.png") boardDesc["gerbers"] = os.path.join(dirPrefix, boardName + "-gerbers.zip") boardDesc["file"] = os.path.join(dirPrefix, boardName + ".kicad_pcb") subprocess.check_call([pcbdraw, "--vcuts", "--silent", boardDesc["source"], os.path.join(outputDirectory, boardDesc["front"])]) subprocess.check_call([pcbdraw, "--vcuts", "--silent", "--back", boardDesc["source"], os.path.join(outputDirectory, boardDesc["back"])]) tmp = tempfile.mkdtemp() export.gerberImpl(boardDesc["source"], tmp) gerbers = [os.path.join(tmp, x) for x in os.listdir(tmp)] subprocess.check_call(["zip", "-j", os.path.join(outputDirectory, boardDesc["gerbers"])] + gerbers) shutil.rmtree(tmp) shutil.copy(boardDesc["source"], os.path.join(outputDirectory, boardDesc["file"]))
def exportJlcpcb(board, outputdir, assembly, schematic, ignore, field, corrections, correctionpatterns, missingerror, nametemplate, drc): """ Prepare fabrication files for JLCPCB including their assembly service """ loadedBoard = pcbnew.LoadBoard(board) if drc: ensurePassingDrc(loadedBoard) refsToIgnore = parseReferences(ignore) removeComponents(loadedBoard, refsToIgnore) Path(outputdir).mkdir(parents=True, exist_ok=True) gerberdir = os.path.join(outputdir, "gerber") shutil.rmtree(gerberdir, ignore_errors=True) gerberImpl(board, gerberdir) archiveName = nametemplate.format("gerbers") shutil.make_archive(os.path.join(outputdir, archiveName), "zip", outputdir, "gerber") if not assembly: return if schematic is None: raise RuntimeError( "When outputing assembly data, schematic is required") correctionFields = [x.strip() for x in corrections.split(",")] components = extractComponents(schematic) ordercodeFields = [x.strip() for x in field.split(",")] bom = collectBom(components, ordercodeFields, refsToIgnore) posData = collectPosData(loadedBoard, correctionFields, bom=components, posFilter=noFilter, correctionFile=correctionpatterns) boardReferences = set([x[0] for x in posData]) bom = { key: [v for v in val if v in boardReferences] for key, val in bom.items() } bom = {key: val for key, val in bom.items() if len(val) > 0} missingFields = False for type, references in bom.items(): _, _, lcsc = type if not lcsc: missingFields = True for r in references: print(f"WARNING: Component {r} is missing ordercode") if missingFields and missingerror: sys.exit("There are components with missing ordercode, aborting") posDataToFile(posData, os.path.join(outputdir, nametemplate.format("pos") + ".csv")) bomToCsv(bom, os.path.join(outputdir, nametemplate.format("bom") + ".csv"))
def exportPcbway(board, outputdir, assembly, schematic, ignore, manufacturer, partnumber, description, notes, soldertype, footprint, corrections, missingerror, nboards): """ Prepare fabrication files for PCBWay including their assembly service """ loadedBoard = pcbnew.LoadBoard(board) refsToIgnore = parseReferences(ignore) removeComponents(loadedBoard, refsToIgnore) Path(outputdir).mkdir(parents=True, exist_ok=True) gerberdir = os.path.join(outputdir, "gerber") shutil.rmtree(gerberdir, ignore_errors=True) gerberImpl(board, gerberdir, settings=exportSettingsPcbway) shutil.make_archive(os.path.join(outputdir, "gerbers"), "zip", outputdir, "gerber") if not assembly: return if schematic is None: raise RuntimeError( "When outputing assembly data, schematic is required") components = extractComponents(schematic) correctionFields = [x.strip() for x in corrections.split(",")] manufacturerFields = [x.strip() for x in manufacturer.split(",")] partNumberFields = [x.strip() for x in partnumber.split(",")] descriptionFields = [x.strip() for x in description.split(",")] notesFields = [x.strip() for x in notes.split(",")] typeFields = [x.strip() for x in soldertype.split(",")] footprintFields = [x.strip() for x in footprint.split(",")] addVirtualToRefsToIgnore(refsToIgnore, loadedBoard) bom = collectBom(components, manufacturerFields, partNumberFields, descriptionFields, notesFields, typeFields, footprintFields, refsToIgnore) missingFields = False for type, references in bom.items(): _, _, manu, partno, _, _ = type if not manu or not partno: missingFields = True for r in references: print( f"WARNING: Component {r} is missing manufacturer and/or part number" ) if missingFields and missingerror: sys.exit("There are components with missing ordercode, aborting") posData = collectPosData(loadedBoard, correctionFields, bom=components) posDataToFile(posData, os.path.join(outputdir, "pos.csv")) types = collectSolderTypes(loadedBoard) bomToCsv(bom, os.path.join(outputdir, "bom.csv"), nboards, types)
def create(inputboard, outputdir, jigsize, jigthickness, pcbthickness, registerborder, tolerance, ignore, cutout): board = pcbnew.LoadBoard(inputboard) refs = parseReferences(ignore) removeComponents(board, refs) Path(outputdir).mkdir(parents=True, exist_ok=True) jigsize = (fromMm(jigsize[0]), fromMm(jigsize[1])) addJigFrame(board, jigsize) cutoutComponents(board, getComponents(board, parseReferences(cutout))) stencilFile = os.path.join(outputdir, "stencil.kicad_pcb") board.Save(stencilFile) plotPlan = [ # name, id, comment ("PasteBottom", pcbnew.B_Paste, "Paste Bottom"), ("PasteTop", pcbnew.F_Paste, "Paste top"), ] # get a copy of exportSettingsJlcpcb dictionary and # exclude the Edge.Cuts layer for creation of stencil gerber files exportSettings = exportSettingsJlcpcb.copy() exportSettings["ExcludeEdgeLayer"] = True gerberDir = os.path.join(outputdir, "gerber") gerberImpl(stencilFile, gerberDir, plotPlan, False, exportSettings) gerbers = [os.path.join(gerberDir, x) for x in os.listdir(gerberDir)] subprocess.check_call( ["zip", "-j", os.path.join(outputdir, "gerbers.zip")] + gerbers) jigthickness = fromMm(jigthickness) pcbthickness = fromMm(pcbthickness) outerBorder, innerBorder = fromMm(registerborder[0]), fromMm( registerborder[1]) tolerance = fromMm(tolerance) topRegister = makeTopRegister(board, jigsize, jigthickness, pcbthickness, outerBorder, innerBorder, tolerance) bottomRegister = makeBottomRegister(board, jigsize, jigthickness, pcbthickness, outerBorder, innerBorder, tolerance) topRegisterFile = os.path.join(outputdir, "topRegister.scad") solid.scad_render_to_file(topRegister, topRegisterFile) renderScad(topRegisterFile, os.path.join(outputdir, "topRegister.stl")) bottomRegisterFile = os.path.join(outputdir, "bottomRegister.scad") solid.scad_render_to_file(bottomRegister, bottomRegisterFile) renderScad(bottomRegisterFile, os.path.join(outputdir, "bottomRegister.stl"))
def create(inputboard, outputdir, jigsize, jigthickness, pcbthickness, registerborder, tolerance, ignore, cutout): """ Create stencil and register elements for manual paste dispensing jig. See more details at: https://github.com/yaqwsx/KiKit/blob/master/doc/stencil.md """ board = pcbnew.LoadBoard(inputboard) refs = parseReferences(ignore) removeComponents(board, refs) Path(outputdir).mkdir(parents=True, exist_ok=True) jigsize = (fromMm(jigsize[0]), fromMm(jigsize[1])) addJigFrame(board, jigsize) cutoutComponents(board, getComponents(board, parseReferences(cutout))) stencilFile = os.path.join(outputdir, "stencil.kicad_pcb") board.Save(stencilFile) plotPlan = [ # name, id, comment ("PasteBottom", pcbnew.B_Paste, "Paste Bottom"), ("PasteTop", pcbnew.F_Paste, "Paste top"), ] gerberDir = os.path.join(outputdir, "gerber") gerberImpl(stencilFile, gerberDir, plotPlan, False) gerbers = [os.path.join(gerberDir, x) for x in os.listdir(gerberDir)] subprocess.check_call( ["zip", "-j", os.path.join(outputdir, "gerbers.zip")] + gerbers) jigthickness = fromMm(jigthickness) pcbthickness = fromMm(pcbthickness) outerBorder, innerBorder = fromMm(registerborder[0]), fromMm( registerborder[1]) tolerance = fromMm(tolerance) topRegister = makeTopRegister(board, jigsize, jigthickness, pcbthickness, outerBorder, innerBorder, tolerance) bottomRegister = makeBottomRegister(board, jigsize, jigthickness, pcbthickness, outerBorder, innerBorder, tolerance) topRegisterFile = os.path.join(outputdir, "topRegister.scad") solid.scad_render_to_file(topRegister, topRegisterFile) renderScad(topRegisterFile, os.path.join(outputdir, "topRegister.stl")) bottomRegisterFile = os.path.join(outputdir, "bottomRegister.scad") solid.scad_render_to_file(bottomRegister, bottomRegisterFile) renderScad(bottomRegisterFile, os.path.join(outputdir, "bottomRegister.stl"))
def exportOSHPark(board, outputdir, nametemplate, drc): """ Prepare fabrication files for OSH Park """ loadedBoard = pcbnew.LoadBoard(board) Path(outputdir).mkdir(parents=True, exist_ok=True) if drc: ensurePassingDrc(loadedBoard) gerberdir = os.path.join(outputdir, "gerber") shutil.rmtree(gerberdir, ignore_errors=True) gerberImpl(board, gerberdir, plot_plan=plotPlanNoVCuts, settings=exportSettingsOSHPark) archiveName = nametemplate.format("gerbers") shutil.make_archive(os.path.join(outputdir, archiveName), "zip", outputdir, "gerber")
def exportJlcpcb(board, outputdir, assembly, schematic, forcesmd, ignore, field, corrections, missingerror): """ Prepare fabrication files for JLCPCB including their assembly service """ loadedBoard = pcbnew.LoadBoard(board) refsToIgnore = parseReferences(ignore) removeComponents(loadedBoard, refsToIgnore) Path(outputdir).mkdir(parents=True, exist_ok=True) gerberdir = os.path.join(outputdir, "gerber") shutil.rmtree(gerberdir, ignore_errors=True) gerberImpl(board, gerberdir) shutil.make_archive(os.path.join(outputdir, "gerbers"), "zip", outputdir, "gerber") if not assembly: return if schematic is None: raise RuntimeError( "When outputing assembly data, schematic is required") correctionFields = [x.strip() for x in corrections.split(",")] components = extractComponents(schematic) ordercodeFields = [x.strip() for x in field.split(",")] bom = collectBom(components, ordercodeFields, refsToIgnore) missingFields = False for type, references in bom.items(): _, _, lcsc = type if not lcsc: missingFields = True for r in references: print(f"WARNING: Component {r} is missing ordercode") if missingFields and missingerror: sys.exit("There are components with missing ordercode, aborting") posData = collectPosData(loadedBoard, correctionFields, posFilter=genPosFilter(forcesmd), bom=components) posDataToFile(posData, os.path.join(outputdir, "pos.csv")) bomToCsv(bom, os.path.join(outputdir, "bom.csv"))
def gerber(boardfile, outputdir): from kikit.export import gerberImpl gerberImpl(boardfile, outputdir)
def gerber(boardfile, outputdir): from kikit.export import gerberImpl from kikit.common import fakeKiCADGui app = fakeKiCADGui() gerberImpl(boardfile, outputdir)