Exemple #1
0
def refill(board):
    try:
        filler = pcbnew.ZONE_FILLER(board)
        zones = board.Zones()
        filler.Fill(zones)
    except:
        message('Refill Failed')
Exemple #2
0
    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
Exemple #4
0
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)
Exemple #5
0
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
Exemple #6
0
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())
Exemple #8
0
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
Exemple #9
0
 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)
Exemple #10
0
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)
Exemple #11
0
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)
Exemple #12
0
def refill(board):
    filler = pcbnew.ZONE_FILLER(board, None)
    zones = board.Zones()
    filler.Fill(zones)
Exemple #13
0
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")
Exemple #14
0
def RebuildAllZones(pcb):
    filler = pcbnew.ZONE_FILLER(pcb)
    filler.Fill(pcb.Zones())