def refill(board): try: filler = pcbnew.ZONE_FILLER(board) zones = board.Zones() filler.Fill(zones) except: message('Refill Failed')
def __init__(self, f_name, plot_dir, zone_refill=True): ''' f_name: the .kicad_pcb file to export plot_dir: output directory for the Gerber files zone_refill: if True, re-calculate copper fills before plotting ''' self.plot_dir = plot_dir # Will raise an exception if file cannot be opened self.board = board = pcbnew.LoadBoard(f_name) self.f_name = basename(f_name) # Hack: the file has SE55DE100 clearance set small enough to # pass DRC, but for the Gerber export process it should be set # to the actual desired value. # Really only sets size of clearance circles where these nets # cross power planes. Programming hints from # kicad.mmccoo.com/2017/04/18/modify-design-rules-from-python/ nc_name = "SE55DE100" aa = board.GetDesignSettings().m_NetClasses.Find(nc_name) if aa is None: print("No %s net_class?" % nc_name) else: aa_old = aa.GetClearance() aa_new = 222000 # according to Michal aa_new = 200000 # lets ground plane connect between via pairs escaping FPGA print("Adjusting %s clearance from %d to %d" % (nc_name, aa_old, aa_new)) aa.SetClearance(aa_new) if zone_refill: print('filling zones ...') zf = pcbnew.ZONE_FILLER(board) zf.Fill(board.Zones())
def draw(self, board, layer, origin=Point(), net=0): zone_container = None shape_poly_set = None previous = 0 pen = Point(pt=origin) previous = 0 for c in self.text: self.face.set_char_size(int(self.size * 64.0)) self.face.load_char(c) kerning = self.face.get_kerning(previous, c) zone_container, shape_poly_set = Glyph( c, self.face, self.size).draw(board, layer, pen, zone_container, shape_poly_set) previous = c pen.x += kerning.x * SCALE pen.x += self.face.glyph.advance.x * SCALE pen.y += self.face.glyph.advance.y * SCALE pcbnew.ZONE_FILLER(board).Fill(board.Zones()) return zone_container
def main(): args = parse_args() board = pcbnew.LoadBoard(args.filename) filler = pcbnew.ZONE_FILLER(board) zones = board.Zones() filler.Fill(zones) pcbnew.SaveBoard(args.filename, board)
def plot_layers(f_name, plot_dir, layers=['F.Cu', 'B.Cu'], zone_refill=True): ''' f_name: the .kicad_pcb file to plot plot_dir: output directory for the .pdf files layers: list of layer names to plot zone_refill: if True, re-calculate copper fills before plotting returns: dict with coordinates of bounding box containing the PCB [inches] ''' if not os.path.isfile(f_name) or not os.access(f_name, os.R_OK): print("%s: not readable, aborting" % f_name) return None try: board = pcbnew.LoadBoard(f_name) except Exception: print("%s: failed to load with pcbnew, aborting" % f_name) return None # after this point, chances of failure are low if zone_refill: print('filling zones ...') zf = pcbnew.ZONE_FILLER(board) zf.Fill(board.Zones()) boardbox = board.ComputeBoundingBox() bounds = { 'x': boardbox.GetX() / 1e6 / 25.4, 'y': boardbox.GetY() / 1e6 / 25.4, 'W': boardbox.GetWidth() / 1e6 / 25.4, 'H': boardbox.GetHeight() / 1e6 / 25.4, } # print('bounds [inch]:', bounds) pctl = pcbnew.PLOT_CONTROLLER(board) # pctl.SetColorMode(True) popt = pctl.GetPlotOptions() popt.SetOutputDirectory(plot_dir) popt.SetPlotFrameRef(False) # popt.SetLineWidth(pcbnew.FromMM(0.15)) # popt.SetAutoScale(False) popt.SetScale(1) popt.SetMirror(False) # popt.SetUseGerberAttributes(True) popt.SetExcludeEdgeLayer(False) # popt.SetUseAuxOrigin(True) popt.SetDrillMarksType(popt.FULL_DRILL_SHAPE) for layer in layers: pctl.SetLayer(board.GetLayerID(layer)) pctl.OpenPlotfile(layer, pcbnew.PLOT_FORMAT_PDF, layer) pctl.PlotLayer() pctl.ClosePlot() return bounds
def run_drc_python(cfg): logger.debug("Using Python interface instead of running KiCad") import pcbnew logger.debug("Re-filling zones") filler = pcbnew.ZONE_FILLER(cfg.board) filler.Fill(cfg.board.Zones()) logger.debug("Running DRC") pcbnew.WriteDRCReport(cfg.board, cfg.output_file, pcbnew.EDA_UNITS_MILLIMETRES, True) if cfg.save: logger.info('Saving PCB') os.rename(cfg.input_file, cfg.input_file + '-bak') cfg.board.Save(cfg.input_file)
def __init__(self, f_name, plot_dir, zone_refill=True): ''' f_name: the .kicad_pcb file to export plot_dir: output directory for the gerber files zone_refill: if True, re-calculate copper fills before plotting ''' self.plot_dir = plot_dir # Will raise an exception if file cannot be opened self.board = board = pcbnew.LoadBoard(f_name) self.f_name = basename(f_name) if zone_refill: print('filling zones ...') zf = pcbnew.ZONE_FILLER(board) zf.Fill(board.Zones())
def load_board(pcb_file=None): if not pcb_file: GS.check_pcb() pcb_file = GS.pcb_file try: board = pcbnew.LoadBoard(pcb_file) if BasePreFlight.get_option('check_zone_fills'): pcbnew.ZONE_FILLER(board).Fill(board.Zones()) GS.board = board except OSError as e: logger.error('Error loading PCB file. Corrupted?') logger.error(e) exit(CORRUPTED_PCB) assert board is not None logger.debug("Board loaded") return board
def save(self, filename): """ Saves the panel to a file. """ for edge in self.boardSubstrate.serialize(): self.board.Add(edge) vcuts = self._renderVCutH() + self._renderVCutV() for cut in vcuts: self.board.Add(cut) fillerTool = pcbnew.ZONE_FILLER(self.board) fillerTool.Fill(self.zonesToRefill) self.board.Save(filename) for edge in collectEdges(self.board, "Edge.Cuts"): self.board.Remove(edge) for cut in vcuts: self.board.Remove(cut)
def pour_fills_on_board(pcb_filename): pcb = pcbnew.LoadBoard(pcb_filename) pcb.ComputeBoundingBox(False) bb = pcb.GetBoundingBox() l, t, r, b = bb.GetLeft(), bb.GetTop(), bb.GetRight(), bb.GetBottom() layertable = {} numlayers = pcbnew.PCB_LAYER_ID_COUNT for i in range(numlayers): layertable[pcb.GetLayerName(i)] = i nets = pcb.GetNetsByName() powernets = [] for name in ["GND"]: if (nets.has_key(name)): powernets.append((name, "F.Cu")) powernets.append((name, "B.Cu")) break for netname, layername in (powernets): net = nets.find(netname).value()[1] layer = layertable[layername] newarea = pcb.InsertArea(net.GetNet(), 0, layer, l, t, pcbnew.ZONE_CONTAINER.DIAGONAL_EDGE) newoutline = newarea.Outline() newoutline.Append(l, b) newoutline.Append(r, b) newoutline.Append(r, t) newarea.Hatch() filler = pcbnew.ZONE_FILLER(pcb) zones = pcb.Zones() filler.Fill(zones) pcbnew.SaveBoard(pcb_filename, pcb)
def refill_zones(board): # thanks https://forum.kicad.info/t/filling-zones-copper-pours-inside-the-python-api/19814/3 filler = pcbnew.ZONE_FILLER(board) zones = board.Zones() filler.Fill(zones)
def refill(board): filler = pcbnew.ZONE_FILLER(board, None) zones = board.Zones() filler.Fill(zones)
def generate(): print("Generating Butterboard") board = pcbnew.GetBoard() # This is hard to find but may be useful: #board.GetNetClasses().Add(pcbnew.NETCLASSPTR("helloworld")) #board.SynchronizeNetsAndNetClasses() #board.Add(pcbnew.NETCLASSPTR("hello")) if board.GetCopperLayerCount() < COPPER_LAYERS: board.SetCopperLayerCount(COPPER_LAYERS) # main holes for x in range(MAIN_HOLE_COUNT_X): for y in range(MAIN_HOLE_COUNT_Y): hole_module(board, MAIN_HOLE_SIZE, MAIN_HOLE_DRILL_SIZE, (x * MAIN_HOLE_SHIFT, y * MAIN_HOLE_SHIFT), 0) # text hints for x in range(MAIN_HOLE_COUNT_X + 1): for y in range(MAIN_HOLE_COUNT_Y): text_hint(board, str(chr(ord("A") + y)), TEXT_SIZE_LETTER, TEXT_SIZE_LETTER, TEXT_THICKNESS, (x - 0.5) * MAIN_HOLE_SHIFT, y * MAIN_HOLE_SHIFT) for x in range(MAIN_HOLE_COUNT_X): for y in range(MAIN_HOLE_COUNT_Y + 1): text_hint(board, "%02d" % (x, ), TEXT_SIZE_NUMBER, TEXT_SIZE_NUMBER, TEXT_THICKNESS, x * MAIN_HOLE_SHIFT, (y - 0.5) * MAIN_HOLE_SHIFT) # auxiliary pads for x in range(MAIN_HOLE_COUNT_X + 1): for y in range(MAIN_HOLE_COUNT_Y + 1): pad_types = ("round", ) if (x + y) % 2 == 0: if y % 2 == 0: nets = ("GND", ) else: nets = ("VCC", ) else: nets = ( "AUX_%02d_T" % (x, ), "AUX_%02d_B" % (y, ), ) for net in nets: pad_types = ("first_half", "second_half") if net.endswith("_B"): if x <= 1 or MAIN_HOLE_COUNT_X - 1 <= x: pad_types = ("round", ) if net.endswith("_T"): if y <= 1 or MAIN_HOLE_COUNT_Y - 1 <= y: pad_types = ("round", ) for pad_type in pad_types: actual_net = net if net.endswith("_T"): if pad_type == "second_half" or y <= 1: actual_net += "_%02d" % (y // 2 + 1, ) else: actual_net += "_%02d" % (y // 2 + 0, ) if net.endswith("_B"): if pad_type == "second_half" or x <= 1: actual_net += "_%02d" % (x // 2 + 1, ) else: actual_net += "_%02d" % (x // 2 + 0, ) hole_module(board, AUX_HOLE_SIZE, AUX_HOLE_DRILL_SIZE, ((x - 0.5) * MAIN_HOLE_SHIFT, (y - 0.5) * MAIN_HOLE_SHIFT), ensure_net(board, actual_net), pad_type) # sinusoidal copper pours if COPPER_LAYERS >= 4 and (actual_net == "GND" or actual_net == "VCC"): continue if y <= MAIN_HOLE_COUNT_Y - 2: endcap = "none" if y == 0: endcap = "full_first_half" elif y == 1: endcap = "first_half" if y == MAIN_HOLE_COUNT_Y - 2: endcap = "full_second_half" elif y == MAIN_HOLE_COUNT_Y - 3: endcap = "second_half" actual_net = nets[0] if actual_net != "GND" and actual_net != "VCC": actual_net += "_%02d" % (y // 2 + 1, ) connect_area(board, AUX_HOLE_SIZE, ((x - 0.5) * MAIN_HOLE_SHIFT, (y - 0.5) * MAIN_HOLE_SHIFT), ((x - 0.5) * MAIN_HOLE_SHIFT, (y + 1.5) * MAIN_HOLE_SHIFT), ensure_net(board, actual_net), y % 2 == 0, endcap, board.GetLayerID("F.Cu")) if x <= MAIN_HOLE_COUNT_X - 2: endcap = "none" if x == 0: endcap = "full_first_half" elif x == 1: endcap = "first_half" if x == MAIN_HOLE_COUNT_X - 2: endcap = "full_second_half" elif x == MAIN_HOLE_COUNT_X - 3: endcap = "second_half" if len(nets) > 1: actual_net = nets[1] else: actual_net = nets[0] if actual_net != "GND" and actual_net != "VCC": actual_net += "_%02d" % (x // 2 + 1, ) connect_area(board, AUX_HOLE_SIZE, ((x - 0.5) * MAIN_HOLE_SHIFT, (y - 0.5) * MAIN_HOLE_SHIFT), ((x + 1.5) * MAIN_HOLE_SHIFT, (y - 0.5) * MAIN_HOLE_SHIFT), ensure_net(board, actual_net), x % 2 == 0, endcap, board.GetLayerID("B.Cu")) border( board, max(BORDER_UPSIZE_WIDTH, MAIN_HOLE_SHIFT * (MAIN_HOLE_COUNT_X + 1)), max(BORDER_UPSIZE_HEIGHT, MAIN_HOLE_SHIFT * (MAIN_HOLE_COUNT_Y + 1)), (MAIN_HOLE_COUNT_X - 1) * MAIN_HOLE_SHIFT / 2, (MAIN_HOLE_COUNT_Y - 1) * MAIN_HOLE_SHIFT / 2) pcbnew.ZONE_FILLER(board).Fill(board.Zones()) pcbnew.Refresh() print("Done generating Butterboard")
def RebuildAllZones(pcb): filler = pcbnew.ZONE_FILLER(pcb) filler.Fill(pcb.Zones())