def plot_drill(self): board_name = os.path.splitext( os.path.basename(self.board.GetFileName()))[0] logger.info('Plotting drill file') drill_writer = pcbnew.EXCELLON_WRITER(self.board) drill_writer.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) mirror = False minimalHeader = False offset = pcbnew.wxPoint(0, 0) merge_npth = True drill_writer.SetOptions(mirror, minimalHeader, offset, merge_npth) metric_format = True drill_writer.SetFormat(metric_format) generate_drill = True generate_map = True drill_writer.CreateDrillandMapFilesSet(self.build_directory, generate_drill, generate_map) drill_file_name = os.path.join(self.build_directory, '%s.drl' % (board_name, )) map_file_name = os.path.join(self.build_directory, '%s-drl_map.pdf' % (board_name, )) return drill_file_name, map_file_name
def plotDrill( board, gerberDirPath, boardProjectName, excellonFormat, useAuxOrigin, drillMinimalHeader, drillMergeNpth, drillExtensionRenameTo, ): ew = pcbnew.EXCELLON_WRITER(board) ew.SetFormat(True, excellonFormat, 3, 3) offset = pcbnew.wxPoint(0,0) if useAuxOrigin: offset = board.GetAuxOrigin() ew.SetOptions(False, drillMinimalHeader, offset, drillMergeNpth) ew.CreateDrillandMapFilesSet(gerberDirPath,True,False) if drillExtensionRenameTo is not None: if drillMergeNpth: renameFileIfExists('%s/%s.drl' % (gerberDirPath, boardProjectName), '%s/%s.%s' % (gerberDirPath, boardProjectName, drillExtensionRenameTo)) else: renameFileIfExists('%s/%s-PTH.drl' % (gerberDirPath, boardProjectName), '%s/%s-PTH.%s' % (gerberDirPath, boardProjectName, drillExtensionRenameTo)) renameFileIfExists('%s/%s-NPTH.drl' % (gerberDirPath, boardProjectName), '%s/%s-NPTH.%s' % (gerberDirPath, boardProjectName, drillExtensionRenameTo))
def get_drill_file(drill_output_dir): create_dir_if_not_exist(drill_output_dir) drlwriter = pcbnew.EXCELLON_WRITER(board) drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) mirror = False minimalHeader = False offset = pcbnew.wxPoint(0, 0) # False to generate 2 separate drill files (one for plated holes, one for non plated holes) # True to generate only one drill file mergeNPTH = False drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) metricFmt = True drlwriter.SetFormat(metricFmt) genDrl = True genMap = True print('create drill and map files in %s' % drill_output_dir) drlwriter.CreateDrillandMapFilesSet(drill_output_dir, genDrl, genMap) # One can create a text file to report drill statistics rptfn = os.path.join(drill_output_dir, 'drill_report.rpt') print('report: %s' % rptfn) drlwriter.GenDrillReportFile(rptfn)
def genDrill(self, board, path, filename): drlwriter = pcbnew.EXCELLON_WRITER(board) drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) mirror = False minimalHeader = False mergeNPTH = True offset = pcbnew.wxPoint(0, 0) drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) drlwriter.SetRouteModeForOvalHoles(False) # G85 for oval shapes metricFmt = False drlwriter.SetFormat(metricFmt, drlwriter.KEEP_ZEROS) genDrl = True genMap = True drlwriter.CreateDrillandMapFilesSet(path, genDrl, genMap) # convert to DOS format when run on Linux if platform.system() == 'Linux': f = open(path + '/' + filename + '.drl', 'r') content = f.read() content = self.toDOS(content) f = open(path + '/' + filename + '.drl', 'w') f.write(content) f.close() # One can create a text file to report drill statistics drlwriter.GenDrillReportFile(path + '/' + filename + '_drill_stat.txt') logging.info('Drill file done')
def generate_pcb_drill(args): logging.info('Generating PCB drill file') check_args(args) output_dir = os.path.join(args.output_dir, 'gerber') if not os.path.exists(output_dir): os.makedirs(output_dir) logging.info(' Reading %s', args.input_pcb) board = pcbnew.LoadBoard(args.input_pcb) excellon_writer = pcbnew.EXCELLON_WRITER(board) excellon_writer.SetMapFileFormat(pcbnew.PLOT_FORMAT_GERBER) mirror = False minimal_header = False merge_pth_npth = True offset = pcbnew.wxPoint(0, 0) excellon_writer.SetOptions(mirror, minimal_header, offset, merge_pth_npth) metric_format = True excellon_writer.SetFormat(metric_format) generate_drill = True generate_map = False logging.info(' Writing to %s' % output_dir) excellon_writer.CreateDrillandMapFilesSet(output_dir, generate_drill, generate_map)
def plot_drill(self, pcb): "plot drill files" pctl = pcbnew.PLOT_CONTROLLER(pcb) drill_path = os.path.dirname( pcb.GetFileName()) + PCB_MAN_PACK_DIR + "Drill/" if not os.path.exists(drill_path): os.makedirs(drill_path) report_path = os.path.dirname(pcb.GetFileName()) + REPORTS_DIR if not os.path.exists(report_path): os.makedirs(report_path) pctl = pcbnew.PLOT_CONTROLLER(pcb) popt = pctl.GetPlotOptions() popt.SetOutputDirectory(drill_path) # Set some important plot options: popt.SetPlotFrameRef(False) popt.SetLineWidth(pcbnew.FromMM(0.1)) popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(False) popt.SetExcludeEdgeLayer(False) popt.SetPlotValue(False) popt.SetPlotReference(False) popt.SetUseGerberAttributes(True) popt.SetUseGerberProtelExtensions(False) popt.SetUseAuxOrigin(True) # Fabricators need drill files. # sometimes a drill map file is asked (for verification purpose) drlwriter = pcbnew.EXCELLON_WRITER(pcb) drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) mirror = False minimalHeader = False offset = pcb.GetAuxOrigin() # False to generate 2 separate drill files (one for plated holes, one for non plated holes) # True to generate only one drill file mergeNPTH = True drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) metricFmt = True drlwriter.SetFormat(metricFmt) genDrl = True genMap = True drlwriter.CreateDrillandMapFilesSet(drill_path, genDrl, genMap) # One can create a text file to report drill statistics rptfn = report_path + 'drill_report.rpt' drlwriter.GenDrillReportFile(rptfn) pctl.ClosePlot()
def export_drills(self): ''' Generate EXCELLON drill file ''' print('> ' + self.f_name.replace('.kicad_pcb', '.drl')) drill_writer = pcbnew.EXCELLON_WRITER(self.board) drill_writer.SetOptions(aMirror=False, aMinimalHeader=False, aMerge_PTH_NPTH=False, aOffset=pcbnew.wxPoint(0, 0)) drill_writer.SetFormat(True) # Metric format drill_writer.CreateDrillandMapFilesSet(aPlotDirectory=self.plot_dir, aGenDrill=True, aGenMap=False)
def generate_drillmap(name, output_dir): board = pcbnew.LoadBoard(name) writer = pcbnew.EXCELLON_WRITER(board) writer.SetFormat(False) writer.SetOptions(aMirror=False, aMinimalHeader=False, aOffset=writer.GetOffset(), aMerge_PTH_NPTH=True) writer.CreateDrillandMapFilesSet(output_dir, aGenDrill=True, aGenMap=False, aReporter=None)
def generate_drill_files(args): """ Generates the drill files for a KiCAD design, including a drill report. The options/arguments consumed by this function are all provided by the argument parser. Returns 0 if everything was successful, or 1 otherwise. """ pcb_file = sanitize(args.pcb_file) output_dir = sanitize(args.output_dir) file_base = os.path.splitext(os.path.basename(pcb_file))[0] drill_report_file = "%s-drill_report.txt" % file_base drill_report_file = os.path.join(args.tempdir, drill_report_file) board = pcbnew.LoadBoard(pcb_file) origin_point = board.GetAuxOrigin() writer = pcbnew.EXCELLON_WRITER(board) writer.SetMapFileFormat(pcbnew.PLOT_FORMAT_GERBER) writer.SetFormat(args.metric, pcbnew.EXCELLON_WRITER.DECIMAL_FORMAT) writer.SetOptions(False, False, origin_point, False) writer.GenDrillReportFile(drill_report_file) writer.CreateDrillandMapFilesSet(args.tempdir, True, True) if args.check != "": drills_ok = check_drills(sanitize(args.check), drill_report_file, args.metric) if drills_ok is False: return 1 if args.no_slots: drill_report_data = open(drill_report_file, 'r').readlines() for line in drill_report_data: if re.findall("with [1-9][0-9]* slot", line) != []: sys.stderr.write("Error: One or more slots reported in ") sys.stderr.write("design.\n%s" % line) return 1 if not os.path.isdir(output_dir): try: os.mkdir(output_dir) except OSError: err_msg = "Error: Couldn't make output directory [%s]" % output_dir sys.stderr.write(err_msg + "\n") return 1 for filename in os.listdir(args.tempdir): filename = os.path.join(args.tempdir, filename) shutil.copy(filename, output_dir) return 0
def _configure_excellon_drill_writer(self, board, offset, options): drill_writer = pcbnew.EXCELLON_WRITER(board) to = options.type_options mirror_y = to.mirror_y_axis minimal_header = to.minimal_header merge_npth = to.pth_and_npth_single_file zeros_format = pcbnew.EXCELLON_WRITER.DECIMAL_FORMAT drill_writer.SetOptions(mirror_y, minimal_header, offset, merge_npth) drill_writer.SetFormat(to.metric_units, zeros_format) return drill_writer
def drill( self, dest, global_suffix='', merge_npth=False, extension=None, mirror=False, aux_origin=True, minimal_header=False, metric=True, ): dctl = pcbnew.EXCELLON_WRITER(self._board) if aux_origin: offset = self._board.GetAuxOrigin() else: offset = pcbnew.wxPoint(0, 0) dctl.SetOptions(mirror, minimal_header, offset, merge_npth) dctl.SetFormat(metric) dctl.CreateDrillandMapFilesSet(dest, aGenDrill=True, aGenMap=False) oldname = os.path.join(dest, self._name) if len(global_suffix): newname = os.path.join(dest, self._name + '-' + global_suffix) else: newname = oldname oldext = '.drl' if extension is not None: newext = extension else: newext = oldext if newname != oldname or newext != oldext: if merge_npth: os.rename(oldname + oldext, newname + newext) else: for s in ['-PTH', '-NPTH']: os.rename(oldname + s + oldext, newname + s + newext)
(pcbnew.Edge_Cuts, "Edge_Cuts")] for l in layers: # Set current layer pc.SetLayer(l[0]) # Plot layer to file pc.OpenPlotfile(l[1], pcbnew.PLOT_FORMAT_GERBER, l[1]) print("Plotting to " + pc.GetPlotFileName()) pc.PlotLayer() pc.ClosePlot() # Generate drill files drlwriter = pcbnew.EXCELLON_WRITER(board) drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_POST) mirror = False minimalHeader = False offset = board.GetAuxOrigin() mergeNPTH = False drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) metricFmt = True drlwriter.SetFormat(metricFmt) genDrl = True genMap = False drlwriter.CreateDrillandMapFilesSet(os.path.dirname(sys.argv[1]), genDrl, genMap)
def kicad_file_to_gerber_archive_file(input_path, output_path): board = pcbnew.LoadBoard(input_path) pctl = pcbnew.PLOT_CONTROLLER(board) popt = pctl.GetPlotOptions() popt.SetPlotFrameRef(False) popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(False) popt.SetUseGerberAttributes(False) popt.SetExcludeEdgeLayer(True) popt.SetScale(1) popt.SetUseAuxOrigin(True) popt.SetNegative(False) popt.SetPlotReference(True) popt.SetPlotValue(True) popt.SetPlotInvisibleText(False) popt.SetSubtractMaskFromSilk(True) popt.SetMirror(False) popt.SetDrillMarksType(pcbnew.PCB_PLOT_PARAMS.NO_DRILL_SHAPE) # TODO(kleinpa): Will JLCPCB accept file without this set? popt.SetUseGerberProtelExtensions(True) plot_plan = [("F_Cu", pcbnew.F_Cu, "Top layer"), ("B_Cu", pcbnew.B_Cu, "Bottom layer"), ("B_Mask", pcbnew.B_Mask, "Mask Bottom"), ("F_Mask", pcbnew.F_Mask, "Mask top"), ("B_Paste", pcbnew.B_Paste, "Paste Bottom"), ("F_Paste", pcbnew.F_Paste, "Paste Top"), ("F_SilkS", pcbnew.F_SilkS, "Silk Top"), ("B_SilkS", pcbnew.B_SilkS, "Silk Bottom"), ("Edge_Cuts", pcbnew.Edge_Cuts, "Edges")] for layer in range(1, board.GetCopperLayerCount() - 1): plot_plan += (f"inner{layer}", layer, "inner") with tempfile.TemporaryDirectory() as temp_path: popt.SetOutputDirectory(temp_path) # Plot layers for suffix, layer, description in plot_plan: pctl.SetLayer(layer) pctl.OpenPlotfile(suffix, pcbnew.PLOT_FORMAT_GERBER, description) pctl.PlotLayer() pctl.ClosePlot() # Generate drill file drlwriter = pcbnew.EXCELLON_WRITER(board) drlwriter.SetMapFileFormat(aMapFmt=pcbnew.PLOT_FORMAT_GERBER) drlwriter.SetOptions(aMirror=False, aMinimalHeader=False, aOffset=pcbnew.wxPoint(0, 0), aMerge_PTH_NPTH=True) formatMetric = True drlwriter.SetFormat(formatMetric) drlwriter.CreateDrillandMapFilesSet(aPlotDirectory=temp_path, aGenDrill=True, aGenMap=False) # Copy files from output directory to in-memory zip file fp = io.BytesIO() with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as z: for root, dirs, files in os.walk(temp_path): for file in files: z.write( os.path.join(root, file), # TODO(kleinpa): Required for JLCPCB, any alternative? file.replace("gm1", "gko")) fp.seek(0) return fp
def gen_gerbers(filename, plot_folder): board = PN.LoadBoard(filename) pc = PN.PLOT_CONTROLLER(board) po = pc.GetPlotOptions() po.SetOutputDirectory(plot_folder) # Set some important plot options: po.SetPlotFrameRef(False) po.SetLineWidth(PN.FromMM(0.15)) po.SetAutoScale(False) po.SetScale(1) po.SetMirror(False) po.SetUseGerberAttributes(False) po.SetUseGerberProtelExtensions(True) po.SetExcludeEdgeLayer(True) po.SetScale(1) po.SetUseAuxOrigin(False) po.SetSubtractMaskFromSilk( True ) #Without this if part outline silkscreen on top of pad, we are screwed. po.SetPlotReference(True) po.SetPlotValue(False) layers = [ ("F.Cu", PN.F_Cu, "Top layer"), ("B.Cu", PN.B_Cu, "Bottom layer"), ("B.Paste", PN.B_Paste, "Paste Bottom"), ("F.Paste", PN.F_Paste, "Paste top"), ("F.SilkS", PN.F_SilkS, "Silk top"), ("B.SilkS", PN.B_SilkS, "Silk top"), ("B.Mask", PN.B_Mask, "Mask bottom"), ("F.Mask", PN.F_Mask, "Mask top"), ("Edge.Cuts", PN.Edge_Cuts, "Edges"), ] for layer_prefix, layer_id, layer_info in layers: pc.SetLayer(layer_id) pc.OpenPlotfile(layer_prefix, PN.PLOT_FORMAT_GERBER, layer_info) print('Plot %s' % os.path.basename(pc.GetPlotFileName())) if pc.PlotLayer() == False: print("Plot error while generating %s" % layer_info) sys.exit(1) pc.ClosePlot() # Generate the drill file drl = PN.EXCELLON_WRITER(board) drl.SetMapFileFormat(PN.PLOT_FORMAT_GERBER) mirror = False minimal_header = False offset = PN.wxPoint(0, 0) mergeNPTH = True drl.SetOptions(mirror, minimal_header, offset, mergeNPTH) metric_fmt = False zeros_fmt = PN.EXCELLON_WRITER.SUPPRESS_LEADING left_digits = 2 right_digits = 4 drl.SetFormat(metric_fmt, zeros_fmt, left_digits, right_digits) generate_drl = True generate_map = True print("Create drill and map files") drl.CreateDrillandMapFilesSet(pc.GetPlotDirName(), generate_drl, generate_map)
pctl.OpenPlotfile(layer_info[0], pcbnew.PLOT_FORMAT_GERBER, layer_info[2]) pctl.PlotLayer() pctl.ClosePlot() ############################## # export drill METRIC = True ZERO_FORMAT = pcbnew.GENDRILL_WRITER_BASE.DECIMAL_FORMAT INTEGER_DIGITS = 3 MANTISSA_DIGITS = 3 MIRROR_Y_AXIS = False HEADER = True OFFSET = pcbnew.wxPoint(0, 0) MERGE_PTH_NPTH = True DRILL_FILE = True MAP_FILE = False REPORTER = None drill_writer = pcbnew.EXCELLON_WRITER(board) drill_writer.SetFormat(METRIC, ZERO_FORMAT, INTEGER_DIGITS, MANTISSA_DIGITS) drill_writer.SetOptions(MIRROR_Y_AXIS, HEADER, OFFSET, MERGE_PTH_NPTH) drill_writer.CreateDrillandMapFilesSet(gerber_dir, DRILL_FILE, MAP_FILE, REPORTER) #################### # Create gerber zip shutil.make_archive("{}/gerbers".format(output_dir), 'zip', root_dir=gerber_dir)
def plotGerbers(): board = pcbnew.GetBoard() pctl = pcbnew.PLOT_CONTROLLER(board) popt = pctl.GetPlotOptions() popt.SetOutputDirectory("gerbers/") # Set some important plot options: popt.SetPlotFrameRef(False) popt.SetLineWidth(pcbnew.FromMM(0.1)) popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(False) popt.SetUseGerberAttributes(False) popt.SetExcludeEdgeLayer(True) popt.SetPlotPadsOnSilkLayer(False) popt.SetScale(1) popt.SetUseGerberProtelExtensions(True) # This by gerbers only (also the name is truly horrid!) popt.SetSubtractMaskFromSilk(False) # Once the defaults are set it become pretty easy... # I have a Turing-complete programming language here: I'll use it... # param 0 is a string added to the file base name to identify the drawing # param 1 is the layer ID plot_plan = [ ("CuTop", pcbnew.F_Cu, "Top layer"), ("CuBottom", pcbnew.B_Cu, "Bottom layer"), ("PasteBottom", pcbnew.B_Paste, "Paste Bottom"), ("PasteTop", pcbnew.F_Paste, "Paste top"), ("SilkTop", pcbnew.F_SilkS, "Silk top"), ("SilkBottom", pcbnew.B_SilkS, "Silk top"), ("MaskBottom", pcbnew.B_Mask, "Mask bottom"), ("MaskTop", pcbnew.F_Mask, "Mask top"), ("EdgeCuts", pcbnew.Edge_Cuts, "Edges"), ] 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() # At the end you have to close the last plot, otherwise you don't know when # the object will be recycled! pctl.ClosePlot() # Fabricators need drill files. # sometimes a drill map file is asked (for verification purpose) drlwriter = pcbnew.EXCELLON_WRITER(board) drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) mirror = False minimalHeader = False offset = pcbnew.wxPoint(0, 0) # False to generate 2 separate drill files (one for plated holes, one for non plated holes) # True to generate only one drill file mergeNPTH = True drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) metricFmt = True drlwriter.SetFormat(metricFmt) # Generate drill file genDrl = True genMap = False drlwriter.CreateDrillandMapFilesSet(pctl.GetPlotDirName(), genDrl, genMap) return pctl.GetPlotDirName()
def OutputFab(board=None, output_dir=defaults['output_dir'], overwrite=False, protel_ext=False, output_log=sys.stdout): ret = {} ret['warn'] = [] if board == None: board = pcbnew.GetBoard() if not board: raise Exception('Error: Invalid board') os.makedirs(output_dir) out_file_prefix = os.path.splitext(os.path.basename( board.GetFileName()))[0] # TODO run DRC pctl = pcbnew.PLOT_CONTROLLER(board) popt = pctl.GetPlotOptions() popt.SetOutputDirectory(output_dir) # Set some important plot options: popt.SetPlotFrameRef(False) #do not change it popt.SetLineWidth(pcbnew.FromMM(0.1)) popt.SetAutoScale(False) #do not change it popt.SetScale(1) #do not change it popt.SetMirror(False) popt.SetUseGerberAttributes( False) # disable verbose header in gerber files popt.SetUseGerberProtelExtensions(protel_ext) popt.SetExcludeEdgeLayer(True) popt.SetUseAuxOrigin(True) popt.SetSubtractMaskFromSilk(True) popt.SetDrillMarksType(pcbnew.PCB_PLOT_PARAMS.NO_DRILL_SHAPE) plot_plan = [ # fname_suffix layer_id comment ("CuTop", pcbnew.F_Cu, "Top layer"), ("CuBottom", pcbnew.B_Cu, "Bottom layer"), ("PasteTop", pcbnew.F_Paste, "Paste top"), ("PasteBottom", pcbnew.B_Paste, "Paste Bottom"), ("SilkTop", pcbnew.F_SilkS, "Silk top"), ("SilkBottom", pcbnew.B_SilkS, "Silk bottom"), ("MaskTop", pcbnew.F_Mask, "Mask top"), ("MaskBottom", pcbnew.B_Mask, "Mask bottom"), ("EdgeCuts", pcbnew.Edge_Cuts, "Edges"), ] # add inner layers if present for inner_layer in range(1, board.GetCopperLayerCount() - 1): layer_name = "Int%d" % inner_layer plot_plan.append((layer_name, inner_layer, "Layer %s" % layer_name)) # now do the plot for layer_info in plot_plan: pctl.SetLayer(layer_info[1]) pctl.OpenPlotfile(layer_info[0], pcbnew.PLOT_FORMAT_GERBER, layer_info[2]) output_log.write('Ploting %s\n' % pctl.GetPlotFileName()) if pctl.PlotLayer() == False: raise Exception("Plot error") # Plot the FAB notes and drill legend popt.SetUseAuxOrigin(False) # Color plotting does not work from the python interface # Might need to export each layer separatelly and combine them with external tools pctl.SetColorMode(True) pctl.OpenPlotfile("FabDrawing", pcbnew.PLOT_FORMAT_PDF, "Fab Drawing") output_log.write('Ploting %s\n' % pctl.GetPlotFileName()) #popt.SetColor(pcbnew.GREEN) # kicad 4.0 #popt.SetColor(pcbnew.COLOR4D(0.050, 0.050, 0.050, 0.1)) # kicad 5.0 pctl.SetLayer(pcbnew.Edge_Cuts) pctl.PlotLayer() pctl.SetLayer(pcbnew.Cmts_User) pctl.PlotLayer() pctl.SetLayer(pcbnew.Eco1_User) pctl.PlotLayer() # Generate drill files mirror = False minimalHeader = False offset = board.GetAuxOrigin() mergeNPTH = True drlwriter = pcbnew.EXCELLON_WRITER(board) drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) metricFmt = True drlwriter.SetFormat(metricFmt) genDrl = True genMap = True output_log.write('Create drill and map files\n') drlwriter.CreateDrillandMapFilesSet(pctl.GetPlotDirName(), genDrl, genMap) report_filename = pctl.GetPlotDirName( ) + out_file_prefix + '_DrillReport.rpt' output_log.write('Create drill report in %s\n' % report_filename) drlwriter.GenDrillReportFile(report_filename) pctl.ClosePlot() output_log.write('Create zip file') os.chdir(pctl.GetPlotDirName()) cmd = 'zip -j {0}.zip {0}*.g?? {0}*.g? {0}-FabDrawing.pdf {0}.drl '.format( out_file_prefix) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) stdout, stderr = p.communicate() output_log.write(stdout) output_log.write(stderr) # TODO IPC-D-356 (it's not exposed in the python interface) ret['warn'].append( 'Please create manually the IPC-D-356 file from the File->Fabrication Outputs menu' ) return ret
def convert(pcb, dir): board = pcb plotDir = os.path.abspath(dir) # prepare the gerber job file gen_job_file = False pctl = pcbnew.PLOT_CONTROLLER(board) popt = pctl.GetPlotOptions() popt.SetOutputDirectory(plotDir) # Set some important plot options (see pcb_plot_params.h): popt.SetPlotFrameRef(False) # do not change it popt.SetLineWidth(pcbnew.FromMM(0.35)) popt.SetAutoScale(False) # do not change it popt.SetScale(1) # do not change it popt.SetMirror(False) popt.SetUseGerberAttributes(True) popt.SetIncludeGerberNetlistInfo(True) popt.SetCreateGerberJobFile(gen_job_file) popt.SetUseGerberProtelExtensions(False) popt.SetExcludeEdgeLayer(False) popt.SetScale(1) popt.SetUseAuxOrigin(True) # This by gerbers only popt.SetSubtractMaskFromSilk(False) # Disable plot pad holes popt.SetDrillMarksType(pcbnew.PCB_PLOT_PARAMS.NO_DRILL_SHAPE) # Skip plot pad NPTH when possible: when drill size and shape == pad size and shape # usually sel to True for copper layers popt.SetSkipPlotNPTH_Pads(False) # prepare the gerber job file jobfile_writer = pcbnew.GERBER_JOBFILE_WRITER(board) # Once the defaults are set it become pretty easy... # I have a Turing-complete programming language here: I'll use it... # param 0 is a string added to the file base name to identify the drawing # param 1 is the layer ID # param 2 is a comment plot_plan = [ ("F_Cu", pcbnew.F_Cu, "Top layer"), ("B_Cu", pcbnew.B_Cu, "Bottom layer"), ("B_Paste", pcbnew.B_Paste, "Paste Bottom"), ("F_Paste", pcbnew.F_Paste, "Paste top"), ("F_SilkS", pcbnew.F_SilkS, "Silk top"), ("B_SilkS", pcbnew.B_SilkS, "Silk top"), ("B_Mask", pcbnew.B_Mask, "Mask bottom"), ("F_Mask", pcbnew.F_Mask, "Mask top"), ("Edge_Cuts", pcbnew.Edge_Cuts, "Edges"), ] for layer_info in plot_plan: if layer_info[1] <= pcbnew.B_Cu: popt.SetSkipPlotNPTH_Pads(True) else: popt.SetSkipPlotNPTH_Pads(False) pctl.SetLayer(layer_info[1]) pctl.OpenPlotfile(layer_info[0], pcbnew.PLOT_FORMAT_GERBER, layer_info[2]) print 'plot %s' % pctl.GetPlotFileName() if gen_job_file == True: jobfile_writer.AddGbrFile(layer_info[1], os.path.basename(pctl.GetPlotFileName())) if pctl.PlotLayer() == False: print "plot error" # generate internal copper layers, if any lyrcnt = board.GetCopperLayerCount() for innerlyr in range(1, lyrcnt - 1): popt.SetSkipPlotNPTH_Pads(True) pctl.SetLayer(innerlyr) lyrname = 'In%s_Cu' % innerlyr pctl.OpenPlotfile(lyrname, pcbnew.PLOT_FORMAT_GERBER, "inner") print 'plot %s' % pctl.GetPlotFileName() if pctl.PlotLayer() == False: print "plot error" # At the end you have to close the last plot, otherwise you don't know when # the object will be recycled! pctl.ClosePlot() # Fabricators need drill files. # sometimes a drill map file is asked (for verification purpose) drlwriter = pcbnew.EXCELLON_WRITER(board) drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) mirror = False minimalHeader = False offset = pcbnew.wxPoint(0, 0) # False to generate 2 separate drill files (one for plated holes, one for non plated holes) # True to generate only one drill file mergeNPTH = True drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) metricFmt = True drlwriter.SetFormat(metricFmt) genDrl = True genMap = True print 'create drill and map files in %s' % pctl.GetPlotDirName() drlwriter.CreateDrillandMapFilesSet(pctl.GetPlotDirName(), genDrl, genMap)
def main(args): # kicad helpfully avoids simply writing to named files # and mangles everything based on the name of the input # file. :( # hope this never changes... basename, _junk = os.path.splitext(os.path.basename(args.pcb)) board = pcb.LoadBoard(args.pcb) pctrl = pcb.PLOT_CONTROLLER(board) popt = pctrl.GetPlotOptions() # Default options popt.SetPlotFrameRef(False) popt.SetLineWidth(pcb.FromMM(0.35)) popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(False) popt.SetUseGerberAttributes(True) popt.SetUseGerberProtelExtensions(False) popt.SetExcludeEdgeLayer(False) popt.SetScale(1) popt.SetUseAuxOrigin(True) popt.SetSubtractMaskFromSilk(False) # layers are number from front F_Cu==0, B_Cu==31 # inner layers are 1..30 # count includes B_Cu ncu = board.GetCopperLayerCount() log.info("Design has %d Cu layers", ncu) if ncu == 1: log.warn("Not tested w/ single layer board") assert ncu >= 1, "No Cu layers?" with TempDir() as dname, ZipFile(args.gbrzip, mode='w') as zip: popt.SetOutputDirectory(dname) generated = [] for ext, layer, desc in oshnames: if layer >= ncu - 1 and layer < pcb.B_Cu: log.info("No %s", desc) continue # skip unused inner pctrl.SetLayer(layer) pctrl.OpenPlotfile(ext, pcb.PLOT_FORMAT_GERBER, desc) if not pctrl.PlotLayer(): log.error("Failed to write layer %s", desc) generated.append((os.path.join(dname, "%s-%s.gbr" % (basename, ext)), '%s.%s' % (basename, ext))) pctrl.ClosePlot() # files actually generated at this point for inf, outf in generated: zip.write(inf, outf) drill = pcb.EXCELLON_WRITER(board) drill.SetMapFileFormat(pcb.PLOT_FORMAT_GERBER) mirror = False minimalHeader = False offset = pcb.wxPoint(0, 0) merge = True drill.SetOptions(mirror, minimalHeader, offset, merge) metricFmt = True drill.SetFormat(metricFmt) # can't use drlwriter.CreateDrillFile() # as this wants swig wrapped FILE* # and I can't see how to create one (can't just use ctypes) genDrl = True genMap = True drill.CreateDrillandMapFilesSet(dname, genDrl, genMap) zip.write(os.path.join(dname, "%s.drl" % basename), "%s.XLN" % basename) zip.write(os.path.join(dname, "%s-drl_map.gbr" % basename), "%s.fab.gbr" % basename)
def plot(brd, args): pctl = pcbnew.PLOT_CONTROLLER(brd) popt = pctl.GetPlotOptions() popt.SetOutputDirectory(args.output_dir) # 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(True) popt.SetExcludeEdgeLayer(True) popt.SetUseGerberProtelExtensions( True) # instead of .gbr use protel extensions if args.values: popt.SetPlotReference(False) popt.SetPlotValue(True) else: popt.SetPlotReference(True) popt.SetPlotValue(False) # popt.SetUseAuxOrigin(True) # This by gerbers only (also the name is truly horrid!) - what is this? popt.SetSubtractMaskFromSilk(False) pctl.SetColorMode(True) plot_plan = [ # filename layer description outline svg gerb ("MaskBottom", pcbnew.B_Mask, "Mask bottom", True, False, True), ("MaskTop", pcbnew.F_Mask, "Mask top", True, True, True), ("CuBottom", pcbnew.B_Cu, "Bottom layer", True, True, True), ("CuTop", pcbnew.F_Cu, "Top layer", True, True, True), ("SilkTop", pcbnew.F_SilkS, "Silk top", False, True, True), ("SilkBottom", pcbnew.B_SilkS, "Silk bottom", False, False, True), ("EdgeCuts", pcbnew.Edge_Cuts, "Edges", False, True, True), ("User", pcbnew.Cmts_User, "User", False, True, False), ] if config.get('board', 'layers') == '4': plot_plan += [("CuLayer2", pcbnew.In1_Cu, "Layer 2", True, True, True), ("CuLayer3", pcbnew.In2_Cu, "Layer 3", True, True, True)] # https://github.com/KiCad/kicad-source-mirror/blob/0af5695e51733445c0f246eb688c98201601cd76/pcbnew/plot_board_layers.cpp#L226 for layer_info in plot_plan: print(layer_info) pctl.SetLayer(layer_info[1]) popt.SetUseGerberAttributes( False) # gerbv lists lots of errors if this is True if layer_info[5]: pctl.OpenPlotfile(layer_info[0], pcbnew.PLOT_FORMAT_GERBER, layer_info[2]) pctl.PlotLayer() # drill # https://github.com/KiCad/kicad-source-mirror/blob/afe92c7bfc9d02d551b2cfa675e73d18b956f010/pcbnew/dialogs/dialog_gendrill.cpp#L403 drill = pcbnew.EXCELLON_WRITER(brd) # older kicad doesn't know about MergeOption drill.SetMergeOption(True) drill.SetFormat(True, drill.DECIMAL_FORMAT, 0, 0) drill.CreateDrillandMapFilesSet(args.output_dir, True, False) # make an SVG overview pctl.OpenPlotfile("overview", pcbnew.PLOT_FORMAT_SVG, "Overview") pctl.SetColorMode(True) for layer_info in plot_plan: pctl.SetLayer(layer_info[1]) if layer_info[4]: pctl.PlotLayer() pctl.ClosePlot() out_name = get_board_name() print("convert svg to png") os.system( "inkscape -f %s/%s-overview.svg -z --export-dpi=%d --export-area-drawing --export-png=%s/%s-overview.png" % (args.output_dir, out_name, args.dpi, args.output_dir, out_name)) os.remove("%s/%s-overview.svg" % (args.output_dir, out_name)) # remove the svg as it's quite big
def main(): if len(sys.argv) <= 1 or len(sys.argv) >= 3: print("Usage: " + sys.argv[0] + " <project name>") exit(1) cwd = os.getcwd() projectname = sys.argv[1] board = pcbnew.LoadBoard(cwd + "/" + projectname + ".kicad_pcb") pc = pcbnew.PLOT_CONTROLLER(board) po = pc.GetPlotOptions() # Set General Options: po.SetOutputDirectory(cwd) po.SetPlotFrameRef(False) po.SetPlotValue(True) po.SetPlotReference(True) po.SetPlotInvisibleText(False) po.SetPlotViaOnMaskLayer(True) po.SetExcludeEdgeLayer(False) #po.SetPlotPadsOnSilkLayer(PLOT_PADS_ON_SILK_LAYER) #po.SetUseAuxOrigin(PLOT_USE_AUX_ORIGIN) po.SetMirror(False) #po.SetNegative(PLOT_NEGATIVE) #po.SetDrillMarksType(PLOT_DRILL_MARKS_TYPE) #po.SetScale(PLOT_SCALE) po.SetAutoScale(True) #po.SetPlotMode(PLOT_MODE) #po.SetLineWidth(pcbnew.FromMM(PLOT_LINE_WIDTH)) # Set Gerber Options #po.SetUseGerberAttributes(GERBER_USE_GERBER_ATTRIBUTES) #po.SetUseGerberProtelExtensions(GERBER_USE_GERBER_PROTEL_EXTENSIONS) #po.SetCreateGerberJobFile(GERBER_CREATE_GERBER_JOB_FILE) #po.SetSubtractMaskFromSilk(GERBER_SUBTRACT_MASK_FROM_SILK) #po.SetIncludeGerberNetlistInfo(GERBER_INCLUDE_GERBER_NETLIST_INFO) # plot layers dict_layerInfo = ({ "F_Cu": pcbnew.F_Cu, "F_Mask": pcbnew.F_Mask, "F_Paste": pcbnew.F_Paste, "F_SilkS": pcbnew.F_SilkS, "B_Cu": pcbnew.B_Cu, "B_Mask": pcbnew.B_Mask, "B_Paste": pcbnew.B_Paste, "B_SilkS": pcbnew.B_SilkS, "Edge_Cuts": pcbnew.Edge_Cuts, "Eco1_User": pcbnew.Eco1_User, "Eco2_User": pcbnew.Eco2_User }) for key in dict_layerInfo : val = dict_layerInfo[key] pc.SetLayer(val) sheetDesc = key if val not in [ pcbnew.Edge_Cuts, pcbnew.Eco1_User, pcbnew.Eco2_User ]: sheetDesc = sheetDesc.replace("F_", "Front ").replace("B_", "Back ") + " Layer" pc.OpenPlotfile(key, pcbnew.PLOT_FORMAT_GERBER, sheetDesc) pc.PlotLayer() pc.ClosePlot() # generate drill file # options: METRIC = True ZERO_FORMAT = pcbnew.GENDRILL_WRITER_BASE.DECIMAL_FORMAT INTEGER_DIGITS = 3 MANTISSA_DIGITS = 3 MIRROR_Y_AXIS = False HEADER = True OFFSET = pcbnew.wxPoint(0,0) MERGE_PTH_NPTH = False DRILL_FILE = True MAP_FILE = False REPORTER = None drill_writer = pcbnew.EXCELLON_WRITER(board) drill_writer.SetFormat(METRIC, ZERO_FORMAT, INTEGER_DIGITS, MANTISSA_DIGITS) drill_writer.SetOptions(MIRROR_Y_AXIS, HEADER, OFFSET, MERGE_PTH_NPTH) drill_writer.CreateDrillandMapFilesSet(cwd, DRILL_FILE, MAP_FILE, REPORTER)
def Run(self): Print_Board_Dimensions().Run() board = pcbnew.GetBoard() design_settings = board.GetDesignSettings() ff = board.GetFileName().replace("\\", "/") while ("//" in r"%r" % ff): ff = ff.replace("//", "/") fdir = ff.rsplit("/", 1)[0:-1][0] + "/" fname = (ff.rsplit(".", 1)[0]).rsplit("/", 1)[-1] fabdir = fdir + "fabrication/" dokudir = fdir + "documentation/" mapfiledir = dokudir + "drillmaps/" if not (os.path.isdir(fabdir)): os.mkdir(fabdir) if not (os.path.isdir(dokudir)): os.mkdir(dokudir) if not (os.path.isdir(mapfiledir)): os.mkdir(mapfiledir) pctl = pcbnew.PLOT_CONTROLLER(board) popt = pctl.GetPlotOptions() # Set some important plot options: popt.SetPlotFrameRef(False) popt.SetSketchPadLineWidth(pcbnew.FromMM(0.05)) popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(False) popt.SetUseGerberAttributes(True) popt.SetGerberPrecision(6) popt.SetExcludeEdgeLayer(True) popt.SetSubtractMaskFromSilk(True) popt.SetUseAuxOrigin(True) popt.SetUseGerberX2format(True) popt.SetDrillMarksType(pcbnew.PCB_PLOT_PARAMS.NO_DRILL_SHAPE) popt.SetOutputDirectory(fabdir) # Once the defaults are set it become pretty easy... # I have a Turing-complete programming language here: I'll use it... # param 0 is a string added to the file base name to identify the drawing # param 1 is the layer ID # param 2 is a comment rename_necessary = False plot_plan = [ ("TopLayer", pcbnew.F_Cu, "Top layer"), ("BottomLayer", pcbnew.B_Cu, "Bottom layer"), ("PasteBottom", pcbnew.B_Paste, "Paste Bottom"), ("PasteTop", pcbnew.F_Paste, "Paste top"), ("SilkTop", pcbnew.F_SilkS, "Silk top"), ("SilkBottom", pcbnew.B_SilkS, "Silk top"), ("MaskBottom", pcbnew.B_Mask, "Mask bottom"), ("MaskTop", pcbnew.F_Mask, "Mask top"), ("Mechanical", pcbnew.Edge_Cuts, "Mechanical"), ] popt.SetUseGerberProtelExtensions(True) for layer_info in plot_plan: if layer_info[1] <= pcbnew.B_Cu: popt.SetSkipPlotNPTH_Pads(True) else: popt.SetSkipPlotNPTH_Pads(False) pctl.SetLayer(layer_info[1]) pctl.OpenPlotfile("", pcbnew.PLOT_FORMAT_GERBER, layer_info[2]) filpn = pctl.GetPlotFileName().rsplit('.', 1)[0:-1][0] extn = pctl.GetPlotFileName().rsplit('.', 1)[-1] pctl.PlotLayer() if extn == 'gm1': rename_necessary = True sysstrng = (filpn + ".gm1") newname = (filpn + ".gml") #generate internal copper layers, if any lyrcnt = board.GetCopperLayerCount() for innerlyr in range(1, lyrcnt - 1): pctl.SetLayer(innerlyr) lyrname = 'inner%s' % innerlyr pctl.OpenPlotfile(lyrname, pcbnew.PLOT_FORMAT_GERBER, "inner") pctl.PlotLayer() # At the end you have to close the last plot, otherwise you don't know when # the object will be recycled! pctl.ClosePlot() if rename_necessary: if os.path.isfile(newname): os.remove(newname) os.rename(sysstrng, newname) rename_necessary = False # Fabricators need drill files. # sometimes a drill map file is asked (for verification purpose) drlwriter = pcbnew.EXCELLON_WRITER(board) drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) mirror = False minimalHeader = False offset = design_settings.m_AuxOrigin # False to generate 2 separate drill files (one for plated holes, one for non plated holes) # True to generate only one drill file mergeNPTH = False drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) metricFmt = True drlwriter.SetFormat(metricFmt, pcbnew.GENDRILL_WRITER_BASE.SUPPRESS_LEADING, 3, 3) drlwriter.SetRouteModeForOvalHoles(True) drlwriter.CreateDrillandMapFilesSet(pctl.GetPlotDirName(), True, False) drlwriter.CreateDrillandMapFilesSet(mapfiledir, False, True) # Rename drill files to .txt if os.path.isfile(fabdir + fname + "-PTH.drl"): if os.path.isfile(fabdir + fname + "-PTH.txt"): os.remove(fabdir + fname + "-PTH.txt") os.rename(fabdir + fname + "-PTH.drl", fabdir + fname + "-PTH.txt") if os.path.isfile(fabdir + fname + "-NPTH.drl"): if os.path.isfile(fabdir + fname + "-NPTH.txt"): os.remove(fabdir + fname + "-NPTH.txt") os.rename(fabdir + fname + "-NPTH.drl", fabdir + fname + "-NPTH.txt") os.system("zip -j " + fabdir + fname + ".zip " + fabdir + "*") ####################################################################################################### popt.SetA4Output(True) popt.SetSketchPadLineWidth(pcbnew.FromMM(0.1)) # popt.SetAutoScale(True) # Switching the output directory popt.SetOutputDirectory(dokudir) ######################################################################################################## # Our fabricators want two additional gerbers: # An assembly with no silk trim and all and only the references # (you'll see that even holes have designators, obviously) # popt.SetSubtractMaskFromSilk(False) popt.SetPlotReference(True) popt.SetPlotValue(False) popt.SetPlotInvisibleText(False) popt.SetPlotReference(True) popt.SetPlotValue(True) popt.SetPlotInvisibleText(False) # Remember that the frame is always in color 0 (BLACK) and should be requested # before opening the plot popt.SetPlotFrameRef(False) popt.SetFineScaleAdjustX(1.000) popt.SetFineScaleAdjustY(1.000) pctl.OpenPlotfile("Layout", pcbnew.PLOT_FORMAT_PDF, "General layout") popt.SetTextMode(pcbnew.PLOT_TEXT_MODE_STROKE) pctl.SetLayer(pcbnew.Edge_Cuts) pctl.PlotLayer() popt.SetPlotMode(pcbnew.SKETCH) pctl.SetLayer(pcbnew.F_Mask) pctl.PlotLayer() popt.SetPlotMode(pcbnew.FILLED) pctl.SetLayer(pcbnew.F_SilkS) pctl.PlotLayer() pctl.ClosePlot() ################################################################################################################ pctl.OpenPlotfile("Assembly", pcbnew.PLOT_FORMAT_SVG, "Master Assembly") pctl.SetColorMode(True) # We want *everything* popt.SetPlotReference(True) popt.SetPlotValue(True) popt.SetPlotInvisibleText(False) # Remember than the DXF driver assigns colours to layers. This means that # we will be able to turn references on and off simply using their layers # Also most of the layer are now plotted in 'line' mode, because DXF handles # fill mode almost like sketch mode (this is to keep compatibility with # most CAD programs; most of the advanced primitive attributes required are # handled only by recent autocads...); also the entry level cads (qcad # and derivatives) simply don't handle polyline widths... pctl.SetLayer(pcbnew.B_SilkS) pctl.PlotLayer() pctl.SetLayer(pcbnew.F_SilkS) pctl.PlotLayer() popt.SetDrillMarksType(pcbnew.PCB_PLOT_PARAMS.SMALL_DRILL_SHAPE) pctl.SetLayer(pcbnew.B_Mask) pctl.PlotLayer() pctl.SetLayer(pcbnew.F_Mask) pctl.PlotLayer() pctl.SetLayer(pcbnew.B_Paste) pctl.PlotLayer() pctl.SetLayer(pcbnew.F_Paste) pctl.PlotLayer() pctl.SetLayer(pcbnew.Edge_Cuts) pctl.PlotLayer() # Export the copper layers too... exporting one of them in filled mode with # drill marks will put the marks in the WHITE later (since it tries to blank # the pads...); these will be obviously great reference points for snap # and stuff in the cad. A pctl function to only plot them would be # better anyway... #pctl.SetLayer(pcbnew.B_Cu) #pctl.PlotLayer() #popt.SetDrillMarksType(pcbnew.PCB_PLOT_PARAMS.NO_DRILL_SHAPE) #pctl.SetLayer(pcbnew.F_Cu) #pctl.PlotLayer() # At the end you have to close the last plot, otherwise you don't know when # the object will be recycled! pctl.ClosePlot()
def main(): # load command-line arguments parser = argparse.ArgumentParser() parser.add_argument('--pcb') parser.add_argument('--plot') args = parser.parse_args() # load board board = pcbnew.LoadBoard(args.pcb) # get plot options pctl = pcbnew.PLOT_CONTROLLER(board) popt = pctl.GetPlotOptions() # set up output directory plotDir = args.plot + '/' popt.SetOutputDirectory(plotDir) # Set plot options according to: # http://docs.oshpark.com/design-tools/kicad/generating-kicad-gerbers/ # Options popt.SetPlotFrameRef(False) popt.SetPlotPadsOnSilkLayer(False) popt.SetPlotValue(True) popt.SetPlotReference(True) popt.SetPlotInvisibleText(False) popt.SetPlotViaOnMaskLayer(True) popt.SetExcludeEdgeLayer(True) popt.SetMirror(False) popt.SetNegative(False) popt.SetUseAuxOrigin(False) popt.SetDrillMarksType(pcbnew.PCB_PLOT_PARAMS.NO_DRILL_SHAPE) popt.SetAutoScale(False) popt.SetScale(1) # TODO: Plot mode = filled popt.SetLineWidth(pcbnew.FromMM(0.1)) # Gerber options popt.SetUseGerberProtelExtensions(True) popt.SetUseGerberAttributes(False) popt.SetSubtractMaskFromSilk(False) popt.SetGerberPrecision(6) # Layers to be plotted plot_plan = [ ("CuTop", pcbnew.F_Cu, "Top layer"), ("CuBottom", pcbnew.B_Cu, "Bottom layer"), ("EdgeCuts", pcbnew.Edge_Cuts, "Edges")] # Plot the layers for layer_info in plot_plan: pctl.SetLayer(layer_info[1]) pctl.OpenPlotfile(layer_info[0], pcbnew.PLOT_FORMAT_GERBER, layer_info[2]) fullname = pctl.GetPlotFileName() basename = os.path.basename(fullname) print 'Plotting %s' % basename if not pctl.PlotLayer(): raise Exception('Plotting error.') # Done with plotting gerbers pctl.ClosePlot() drlwriter = pcbnew.EXCELLON_WRITER(board) # Set Excellon format according to: # http://docs.oshpark.com/design-tools/kicad/generating-kicad-gerbers/ # Drill units, zeros format metricFmt = False zerosFmt = pcbnew.EXCELLON_WRITER.DECIMAL_FORMAT drlwriter.SetFormat(metricFmt, zerosFmt) # Drill map format drlwriter.SetMapFileFormat(pcbnew.PLOT_FORMAT_POST) # Drill file options mirror = False minimalHeader = False mergeNPTH = True offset = pcbnew.wxPoint(0, 0) drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH) genDrl = True genMap = False pctl.GetPlotDirName() print 'Creating drill file.' drlwriter.CreateDrillandMapFilesSet(plotDir, genDrl, genMap)
def plot(args): board = pcbnew.LoadBoard(args.brd + '.kicad_pcb') # Load board and initialize plot controller pc = pcbnew.PLOT_CONTROLLER(board) po = pc.GetPlotOptions() po.SetPlotFrameRef(False) po.SetExcludeEdgeLayer(True) po.SetOutputDirectory(args.dir) po.SetUseGerberProtelExtensions(args.protel) # Load board and initialize excellon writter er = pcbnew.EXCELLON_WRITER(board) mirror = False minimalHeader = False offset = pcbnew.wxPoint(0, 0) merge_npth = not args.splitth er.SetOptions(mirror, minimalHeader, offset, merge_npth) metric_format = True er.SetFormat(metric_format) generate_drill = True generate_map = False if (args.drl or args.all): if (args.splitth): print('Plotting to ' + os.path.join(args.dir, os.path.basename(args.brd)) + '-PTH.drl') print('Plotting to ' + os.path.join(args.dir, os.path.basename(args.brd)) + '-NPTH.drl') else: print('Plotting to ' + os.path.join(args.dir, os.path.basename(args.brd)) + '.drl') er.CreateDrillandMapFilesSet(args.dir, generate_drill, generate_map) if (args.fcu or args.all): suffix = 'F.Cu' if (args.protel): suffix = '' # Set current layer pc.SetLayer(pcbnew.F_Cu) # Plot single layer to file pc.OpenPlotfile(suffix, pcbnew.PLOT_FORMAT_GERBER, 'GTL') print('Plotting to ' + pc.GetPlotFileName()) pc.PlotLayer() if (args.bcu or args.all): suffix = 'B.Cu' if (args.protel): suffix = '' pc.SetLayer(pcbnew.B_Cu) pc.OpenPlotfile(suffix, pcbnew.PLOT_FORMAT_GERBER, 'GBL') print('Plotting to ' + pc.GetPlotFileName()) pc.PlotLayer() if (args.fmask or args.all): suffix = 'F.Mask' if (args.protel): suffix = '' pc.SetLayer(pcbnew.F_Mask) pc.OpenPlotfile(suffix, pcbnew.PLOT_FORMAT_GERBER, 'GTS') print('Plotting to ' + pc.GetPlotFileName()) pc.PlotLayer() if (args.bmask or args.all): suffix = 'B.Mask' if (args.protel): suffix = '' pc.SetLayer(pcbnew.B_Mask) pc.OpenPlotfile(suffix, pcbnew.PLOT_FORMAT_GERBER, 'GBS') print('Plotting to ' + pc.GetPlotFileName()) pc.PlotLayer() if (args.fsilks or args.all): suffix = 'F.SilkS' if (args.protel): suffix = '' pc.SetLayer(pcbnew.F_SilkS) pc.OpenPlotfile(suffix, pcbnew.PLOT_FORMAT_GERBER, 'GTO') print('Plotting to ' + pc.GetPlotFileName()) pc.PlotLayer() if (args.bsilks or args.all): suffix = 'B.SilkS' if (args.protel): suffix = '' pc.SetLayer(pcbnew.B_SilkS) pc.OpenPlotfile(suffix, pcbnew.PLOT_FORMAT_GERBER, 'GBO') print('Plotting to ' + pc.GetPlotFileName()) pc.PlotLayer() if (args.edgecuts or args.all): suffix = 'Edge.Cuts' if (args.protel): suffix = '' pc.SetLayer(pcbnew.Edge_Cuts) pc.OpenPlotfile(suffix, pcbnew.PLOT_FORMAT_GERBER, 'GML') print('Plotting to ' + pc.GetPlotFileName()) pc.PlotLayer() pc.ClosePlot()