def Run( self ): pcb = pcbnew.GetBoard() io = pcbnew.PCB_IO() origin = pcb.GetAuxOrigin() center = pcbnew.wxPoint(origin.x,(origin.y + GAP)) offset = pcbnew.wxPoint(0,GAP) for fid in TOP_FID: mod = io.FootprintLoad(fiducial_lib, "Fiducial") mod.SetPosition(center) mod.SetReference(fid) pcb.Add(mod) center = center + offset center = pcbnew.wxPoint((origin.x + GAP),(origin.y + GAP)) offset = pcbnew.wxPoint(0,GAP) for fid in BOT_FID: mod = io.FootprintLoad(fiducial_lib, "Fiducial") mod.SetPosition(center) mod.Flip(center) mod.SetReference(fid) pcb.Add(mod) center = center + offset
def PlaceHoleCorners(dim_cor=10): global g_startx global g_starty global g_width global g_height global hole_type x_coord = [0, 0] y_coord = [0, 0] x_coord[0] = dim_cor + g_startx x_coord[1] = g_startx + g_width - dim_cor y_coord[0] = g_starty + dim_cor y_coord[1] = g_starty + g_height - dim_cor board = pcbnew.GetBoard() global footprint_lib io = pcbnew.PCB_IO() point = pcbnew.wxPoint(0, 0) for xx in x_coord: for yy in y_coord: mod = io.FootprintLoad(footprint_lib, hole_type) point.x = GetCoordinates(xx) point.y = GetCoordinates(yy) mod.SetPosition(point) board.Add(mod) pcbnew.Refresh()
def addHole(p): io = pcbnew.PCB_IO() mod = io.FootprintLoad( '/home/matt/projects/kicad-library/cache/Mounting_Holes.pretty', 'MountingHole_3.2mm_M3') mod.SetPosition(pcbnew.wxPoint(p.x + X_OFFSET, p.y + Y_OFFSET)) mod.SetReference("") pcb.Add(mod)
def circle_action(self, center, radius): d = str(radius * 2) if d not in self.footprint_mapping: raise ValueError( "diameter {} not found in footprint mapping".format(d)) fp = self.footprint_mapping[d] io = pcbnew.PCB_IO() mod = io.FootprintLoad(fp[0], fp[1]) mod.SetPosition(pcbpoint.pcbpoint(center).wxpoint()) self.board.Add(mod)
def addNPTHole(self, position, diameter): """ Add a drilled non-plated hole to the position (`wxPoint`) with given diameter. """ module = pcbnew.PCB_IO().FootprintLoad(KIKIT_LIB, "NPTH") module.SetPosition(position) for pad in module.Pads(): pad.SetDrillSize(pcbnew.wxSize(diameter, diameter)) pad.SetSize(pcbnew.wxSize(diameter, diameter)) self.board.Add(module)
def add_module(x, y): io = pcbnew.PCB_IO() board = pcbnew.GetBoard() layertable = get_layertable() footprint_lib = "/home/mattvenn/work/nfc-ring/python/fp.pretty" mod = io.FootprintLoad(footprint_lib, "matt") pt = pcbnew.wxPoint(x, y) mod.SetPosition(pt) board.Add(mod) pcbnew.Refresh()
def save(self, library_path): """Save footprint in given library library_path should end with .pretty """ self._module.SetFPID(pcbnew.FPID(self._module.GetReference())) io = pcbnew.PCB_IO() try: io.FootprintLibCreate(library_path) except IOError: pass # we try to create, but may be it exists already io.FootprintSave(library_path, self._module)
def addFiducial(self, position, copperDiameter, openingDiameter, bottom=False): """ Add fiducial, i.e round copper pad with solder mask opening to the position (`wxPoint`), with given copperDiameter and openingDiameter. By setting bottom to True, the fiducial is placed on bottom side. """ module = pcbnew.PCB_IO().FootprintLoad(KIKIT_LIB, "Fiducial") module.SetPosition(position) if(bottom): module.Flip(position) for pad in module.Pads(): pad.SetSize(pcbnew.wxSize(copperDiameter, copperDiameter)) pad.SetLocalSolderMaskMargin(int((openingDiameter - copperDiameter) / 2)) pad.SetLocalClearance(int((openingDiameter - copperDiameter) / 2)) self.board.Add(module)
def PlaceHoleCenter(typex=1, dim_cor=10): global g_startx global g_starty global g_width global g_height global hole_type x_coord = [0, 0] y_coord = [0, 0] if typex == 1: horizont = 1 vertic = 1 elif typex == 2: horizont = 1 vertic = 0 else: horizont = 0 vertic = 1 #horizontal holes board = pcbnew.GetBoard() global footprint_lib io = pcbnew.PCB_IO() point = pcbnew.wxPoint(0, 0) x_coord[0] = g_startx + g_width / 2 y_coord[0] = g_starty + dim_cor y_coord[1] = g_starty + g_height - dim_cor if horizont == 1: for yy in y_coord: mod = io.FootprintLoad(footprint_lib, hole_type) point.x = GetCoordinates(x_coord[0]) point.y = GetCoordinates(yy) mod.SetPosition(point) board.Add(mod) #vertical holes x_coord[0] = g_startx + dim_cor x_coord[1] = g_startx + g_width - dim_cor y_coord[0] = g_starty + g_height / 2 if vertic == 1: for xx in x_coord: mod = io.FootprintLoad(footprint_lib, hole_type) point.x = GetCoordinates(xx) point.y = GetCoordinates(y_coord[0]) mod.SetPosition(point) board.Add(mod) pcbnew.Refresh()
def dxf_to_mountholes(board, footprint_mapping, filepath): dxf = dxfgrabber.readfile(filepath) io = pcbnew.PCB_IO() for e in dxf.entities.get_entities(): if (e.dxftype == "CIRCLE"): print("center {} radius {}".format(e.center, e.radius)) d = str(e.radius * 2) if d not in footprint_mapping: raise ValueError( "diameter {} not found in footprint mapping".format(d)) fp = footprint_mapping[d] mod = io.FootprintLoad(fp[0], fp[1]) mod.SetPosition(pcbpoint.pcbpoint(e.center).wxpoint()) board.Add(mod) pcbnew.Refresh()
def __init__(self, board): self._board = board self._io = pcbnew.PCB_IO() self.layerI = { pcbnew.BOARD_GetStandardLayerName(n): n for n in range(pcbnew.PCB_LAYER_ID_COUNT) } self.layerN = {s: n for n, s in self.layerI.iteritems()} # generate a LUT with shape integers to a string self.padShapes = { pcbnew.PAD_SHAPE_CIRCLE: "PAD_SHAPE_CIRCLE", pcbnew.PAD_SHAPE_OVAL: "PAD_SHAPE_OVAL", pcbnew.PAD_SHAPE_RECT: "PAD_SHAPE_RECT", pcbnew.PAD_SHAPE_TRAPEZOID: "PAD_SHAPE_TRAPEZOID" } if hasattr(pcbnew, 'PAD_SHAPE_ROUNDRECT'): self.padShapes[pcbnew.PAD_SHAPE_ROUNDRECT] = "PAD_SHAPE_ROUNDRECT" # returns a dictionary netcode:netinfo_item self.netCodes = self._board.GetNetsByNetcode()
def CreateSMTClone(board, mod, footprintLib, footprintName, rot=0, offset=None): if offset is None: offset = pcbnew.wxPoint(0, 0) new_mod = pcbnew.PCB_IO().FootprintLoad(footprintLib, footprintName) new_mod.SetPosition(ModuleMidPoint(mod) + offset) new_mod.SetOrientation(mod.GetOrientation() + rot) new_mod.SetReference(mod.GetReference()) new_mod.SetValue(mod.GetValue()) new_mod.SetLocalClearance(mod.GetLocalClearance()) board.Add(new_mod) CopyText(mod.Reference(), new_mod.Reference()) CopyText(mod.Value(), new_mod.Value()) for newPad in new_mod.Pads(): oldPad = mod.FindPadByName(newPad.GetName()) net = oldPad.GetNet() newPad.SetNet(net) newPad.SetLocalClearance(oldPad.GetLocalClearance()) return new_mod
def CreateSMTClone2(board, mod, footprintLib, footprintName): new_mod = pcbnew.PCB_IO().FootprintLoad(footprintLib, footprintName) new_mod.SetPosition(ModuleMidPoint(mod)) new_mod.SetOrientation(mod.GetOrientation()) new_mod.SetReference(mod.GetReference()) new_mod.SetValue(mod.GetValue()) new_mod.SetLocalClearance(mod.GetLocalClearance()) board.Add(new_mod) CopyText(mod.Reference(), new_mod.Reference()) CopyText(mod.Value(), new_mod.Value()) for newPad in new_mod.Pads(): oldPad = mod.FindPadByName(newPad.GetName()) net = oldPad.GetNet() newPad.SetNet(net) newPad.SetLocalClearance(oldPad.GetLocalClearance()) # Create via at some offset from the new pad in # the direction of the old pad. TRACK_WIDTH = int(12 * MIL) VIA_DISTANCE = int(30 * MIL) direction = Normalize(oldPad.GetPosition() - newPad.GetPosition()) offset = Scale(direction, VIA_DISTANCE) viaPos = newPad.GetPosition() + offset via = pcbnew.VIA(board) board.Add(via) via.SetPosition(viaPos) via.SetNet(net) via.SetWidth(net.GetNetClass().GetViaDiameter()) via.SetLayerPair(pcbnew.F_Cu, pcbnew.B_Cu) # Create track between new pad and the via. track = pcbnew.TRACK(board) board.Add(track) track.SetStart(newPad.GetPosition()) track.SetEnd(via.GetPosition()) track.SetNet(net) track.SetWidth(int(12 * MIL)) track.SetLayer(pcbnew.F_Cu) return new_mod
def Run(self): """ The entry function of the plugin that is executed on user action """ board = pcbnew.GetBoard() # TODO also aggregate and bin by optional attributes, like tolerances radii = set() circles = [] # TODO don't add an extra hole in same place -> overwrite # get circles drawn on board # TODO maybe include some means of filtering out possible circular board outline drawing_list = board.DrawingsList() for d in drawing_list: if d.GetLayerName() == 'Edge.Cuts': # to gaurd against random stuff being on edge cuts for some reason # causing weird errors assert type( d) == pcbnew.DRAWSEGMENT, 'non-DRAWSEGMENT on Edge.Cuts' if d.GetShapeStr() == 'Circle': # TODO check these are what i want, and don't need modification # w/ thickness or whatever (check using dxf import) r = d.GetRadius() radii.add(r) c = d.GetCenter() circles.append((c.x, c.y, r)) # TODO make optional # how to do? board.RemoveNative(d) # TODO option to use nearest hole in existing library option / next largest # (report error) # TODO easiest way to get available footprints (and their radii?) # TODO option to take a set of target hole sizes (for DFM purposes) # TODO include either global use next largest / next smallest # (maybe ignore locked, and say that, to complement this?) # or let people check for each hole whether they want to use next up or down # TODO option to make new hole components and put in project specific library # TODO include field for library to be saved to (maybe mandatory if this option?) # TODO fail gracefully if board filename is empty (board not saved yet) target_footprint_lib = '.'.join(str(board.GetFileName()).split('.')[:-1]) \ + '.pretty' if not os.path.exists(target_footprint_lib): print('creating project specific footprint library' + \ ' {}'.format(target_footprint_lib)) pcbnew.PCB_IO().FootprintLibCreate(target_footprint_lib) else: print('using footprint library {}'.format(target_footprint_lib)) # make a new footprint for each distinct hole radius we need # save to project specific library by default for r in radii: r_mm = nm_to_mm(r) print('generating footprint for hole of radius {}mm'.format(r_mm)) footprint = pcbnew.MODULE(None) # for non-electronic parts like these footprint.SetAttributes(pcbnew.MOD_VIRTUAL) footprint.SetLastEditTime() footprint.SetKeywords('non-plated through hole NPTH') # TODO it looks like the module itself needs to be specified to be on F.Cu? # how? (see github for example output) # TODO set tags to include non-plated through hole, npth? #footprint.SetDescription('{}mm diameter non-plated through hole') pad = pcbnew.D_PAD(footprint) # other library mounting hole pads seem to have this pad number pad.SetName('1') # TODO does this change the layers and stuff automatically? pad shape? pad.SetAttribute(pcbnew.PAD_ATTRIB_HOLE_NOT_PLATED) pad.SetShape(pcbnew.PAD_SHAPE_CIRCLE) # TODO do i need setsize / setstartend? # size seems to equal (r, r) for existing npth library parts # all holes in KiCad currently have to reside on one of the (external?) # copper layers (F.Cu should be one of these layers. mask the other?) pad.SetLayerSet(pcbnew.D_PAD_UnplatedHoleMask()) # TODO are holes alone actually rendered, or do you need the other stuff? # there seems to be a PAD_DRILL_SHAPE_CIRCLE and PAD_DRILL_SHAPE_OBLONG # but when are they ever not circular? oblong = limited routing? # would advanced circuits do oblong, for instance? #pad.SetDrillShape() # huh??? # TODO why isn't this a single number? what gens (drill X)? # TODO why is x in (size x x) slightly larger than 1.5? pad.SetDrillSize(pcbnew.wxSize(r, r)) footprint.Add(pad) footprint_id = 'R{}mm_NPTH'.format(r_mm) footprint.SetReference(footprint_id) ''' footprint.Reference().SetPosition(pcbnew.wxPoint()1) footprint.Value().SetPosition(pcbnew.wxPoint()1) ''' # aiming for a visible layer that does not translate into manufacture comment_layer_id = get_layer_id_by_name('Cmts.User') footprint.Reference().SetLayer(comment_layer_id) footprint.Value().SetLayer(comment_layer_id) # this is the filename, preceeding .kicad_mod fpid = pcbnew.LIB_ID(footprint_id) footprint.SetFPID(fpid) # seems to work to lock all imports by default footprint.SetLocked(True) print('saving footprint to {}'.format(os.path.join(\ target_footprint_lib, footprint_id + '.kicad_mod'))) pcbnew.PCB_IO().FootprintSave(target_footprint_lib, footprint) for x, y, r_curr in circles: if r == r_curr: f_new = pcbnew.PCB_IO().FootprintLoad( target_footprint_lib, footprint_id) f_new.SetPosition(pcbnew.wxPoint(x, y)) board.Add(f_new)
'Faceplate_Rail_Mount_Slot': 'Faceplate_Rail_Mount_Slot', 'Faceplate_Hole_Spacer_Mount_256': 'Faceplate_Hole_Spacer_Mount_256', 'Faceplate_Hole_FSR_slot': 'Faceplate_Hole_FSR_slot', 'last_item': 'last_item' } remove_fps = ['R0603', 'C0603', 'PAD-06'] import pcbnew board = pcbnew.GetBoard() io = pcbnew.PCB_IO() SCALE = 1000000.0 def find_pcb_outline_bbox(): """Get the bounding box around all edge cuts drawings""" boundingbox = None for d in board.GetDrawings(): if (d.GetLayerName() != "Edge.Cuts"): continue if (boundingbox == None): boundingbox = d.GetBoundingBox() else: boundingbox.Merge(d.GetBoundingBox()) boundingbox.Inflate(-150000) #assume a 0.15mm line width return boundingbox
def Run(self): import faceplate_footprint_lib footprint_lib = faceplate_footprint_lib.get_lib_location() railmount_fp = "Faceplate_Rail_Mount_Slot" SCALE = 1000000.0 msg = "" board = pcbnew.GetBoard() io = pcbnew.PCB_IO() # Find the pcb outline and a list of the drawings on the edgecuts layer pcboutline, edgecuts_dwgs = find_pcb_outline_bbox(board) # Find the center of the pcb outline pcbcenter = pcboutline.Centre() # Move the previous edge cuts to comments layer move_drawings(edgecuts_dwgs, pcbnew.Cmts_User) # Set the fp width to the smallest standard HP size that's larger than the pcb width pcbwidth = pcboutline.GetWidth() fphp, fpwidth = find_width_to_hp(pcbwidth / SCALE) msg += "Faceplate is %d HP wide by 128.5mm high\n" % fphp # Calculate the left and right edges of the faceplate fpleft = pcbcenter.x - fpwidth * SCALE / 2.0 fpright = fpleft + fpwidth * SCALE # Calculate the top and bottom edges of the faceplate (128.5mm height) fpbottom = pcbcenter.y + 128.5 * SCALE / 2.0 fptop = fpbottom - 128.5 * SCALE # Calculate the four corners bottomleft = pcbnew.wxPoint(int(fpleft), int(fpbottom)) bottomright = pcbnew.wxPoint(int(fpright), int(fpbottom)) topleft = pcbnew.wxPoint(int(fpleft), int(fptop)) topright = pcbnew.wxPoint(int(fpright), int(fptop)) # Draw the board outline segments bottomline = pcbnew.DRAWSEGMENT(board) board.Add(bottomline) bottomline.SetLayer(pcbnew.Edge_Cuts) bottomline.SetStart(bottomleft) bottomline.SetEnd(bottomright) topline = pcbnew.DRAWSEGMENT(board) board.Add(topline) topline.SetLayer(pcbnew.Edge_Cuts) topline.SetStart(topleft) topline.SetEnd(topright) leftline = pcbnew.DRAWSEGMENT(board) board.Add(leftline) leftline.SetLayer(pcbnew.Edge_Cuts) leftline.SetStart(topleft) leftline.SetEnd(bottomleft) rightline = pcbnew.DRAWSEGMENT(board) board.Add(rightline) rightline.SetLayer(pcbnew.Edge_Cuts) rightline.SetStart(topright) rightline.SetEnd(bottomright) #add rail mount slots railmount_topleft = pcbnew.wxPoint(topleft.x + 0.295 * 25.4 * SCALE, topleft.y + 0.118 * 25.4 * SCALE) railmount_topright = pcbnew.wxPoint(topright.x - 0.295 * 25.4 * SCALE, topright.y + 0.118 * 25.4 * SCALE) railmount_bottomleft = pcbnew.wxPoint( bottomleft.x + 0.295 * 25.4 * SCALE, bottomleft.y - 0.118 * 25.4 * SCALE) railmount_bottomright = pcbnew.wxPoint( bottomright.x - 0.295 * 25.4 * SCALE, bottomright.y - 0.118 * 25.4 * SCALE) mod = io.FootprintLoad(footprint_lib, railmount_fp) mod.SetPosition(railmount_topleft) board.Add(mod) mod = io.FootprintLoad(footprint_lib, railmount_fp) mod.SetPosition(railmount_topright) board.Add(mod) mod = io.FootprintLoad(footprint_lib, railmount_fp) mod.SetPosition(railmount_bottomleft) board.Add(mod) mod = io.FootprintLoad(footprint_lib, railmount_fp) mod.SetPosition(railmount_bottomright) board.Add(mod) msg += "Creating four rail mount slots (for 8HP and smaller faceplates, delete two of these)" + "\n" msg += "You may need to refresh the display now. Select Legacy mode, then Modern mode" + "\n"
def convert_and_delete_modules(midline, remove_layer, brd): import faceplate_footprint_lib footprint_lib = faceplate_footprint_lib.get_lib_location() footprint_convert = { # POTS 'TRIM-T73YE': 'Faceplate_Hole_Trim_3.175mm_With_Mask_Opening', 'Potentiometer_Alps_RK09L_Double_Vertical': 'Faceplate_Hole_Pot_16mm', 'Potentiometer_Alpha_RV112_Dual_Vert': 'Faceplate_Hole_Pot_16mm', 'Potentiometer_Alpha_RV112_Dual_Vert_Knurled': 'Faceplate_Hole_Pot_16mm', '16MM-RV16AF-4A': 'Faceplate_Hole_Pot_16mm', 'Pot_16mm_21Det_RV16AF-4A': 'Faceplate_Hole_Pot_16mm', 'Pot_16mm_NoDet_RV16AF-4A': 'Faceplate_Hole_Pot_16mm', 'Pot_16mm_CtrDet_RV16AF-4A': 'Faceplate_Hole_Pot_16mm', 'POT-9MM-ALPHA': 'Faceplate_Hole_Pot_9mm_Metal_Collar', 'Pot_9mm_DShaft': 'Faceplate_Hole_Pot_9mm_Metal_Collar', 'Pot_9mm_DShaft_Det': 'Faceplate_Hole_Pot_9mm_Metal_Collar', 'POT-9MM-SONGHUEI': 'Faceplate_Hole_Pot_9mm', 'Pot_9mm_Knurl_Det': 'Faceplate_Hole_Pot_9mm', 'Pot_9mm_Knurl_NoDet': 'Faceplate_Hole_Pot_9mm', # SLIDERS: 'Pot_Slider_LED_20mm_RA2045F': 'Faceplate_Hole_Slider_25mm_Slot', 'POT-SLIDER-LED-ALPHA-RA2045F-20': 'Faceplate_Hole_Slider_25mm_Slot', 'POT-SLIDER-ALPHA-RA2045F-20': 'Faceplate_Hole_Slider_25mm_Slot', # ENCODERS: 'ENC_SPST_12mm': 'Faceplate_Hole_Encoder_290', 'ENC_SPST_12mm_NUDGED': 'Faceplate_Hole_Encoder_290', # Alternative: #'ENC_SPST_12mm_NUDGED': 'Faceplate_Hole_Encoder_KnurledShaft_Alpha' 'ROTENC-12MM-BUT': 'Faceplate_Hole_Encoder_290', 'RGB_ROTARY_ENCODER': 'Faceplate_Hole_Encoder_RGB_NoBushing', 'ENC_RGB_SPST_12mm': 'Faceplate_Hole_Encoder_RGB_NoBushing', 'ENC_RGB_SPST_12mm_NUDGED': 'Faceplate_Hole_Encoder_RGB_NoBushing', # JACKS: 'PJ301M-12': 'Faceplate_Hole_Jack_3.5mm', 'PJ366ST': 'Faceplate_Hole_Jack_3.5mm', 'PJ301M-12-FIX': 'Faceplate_Hole_Jack_3.5mm', 'EighthInch_PJ398SM': 'Faceplate_Hole_Jack_3.5mm', 'EighthInch_Stereo_PJ366ST': 'Faceplate_Hole_Jack_3.5mm', 'Barrel_Vert_PJ064': 'Faceplate_Hole_Jack_Barrel_315', 'EighthInch_PJ398SM_Alt-GND': 'Faceplate_Hole_Jack_3.5mm', 'XLR-NCJ6FA-V-0': 'Faceplate_Hole_XLR_Quarter_Inch', # LEDS AND LIGHTPIPES: 'LED-PLCC4': 'Faceplate_Hole_Lightpipe_With_Mask_Opening', 'LED_PLCC-4': 'Faceplate_Hole_Lightpipe_With_Mask_Opening', 'LED_0603_1608Metric': 'Faceplate_Hole_Lightpipe_With_Mask_Opening', 'PLCC4': 'Faceplate_Hole_Lightpipe_With_Mask_Opening', 'LED-C1-A2-3MM-VERT': 'Faceplate_Hole_LED_3mm', 'LED_D3.0mm-3': 'Faceplate_Hole_LED_3mm', 'LED-3MM-SQUARE-ANODE': 'Faceplate_Hole_LED_3mm', 'LED-T1X2': 'Faceplate_Hole_LED_3mm', 'LED-T1': 'Faceplate_Hole_LED_3mm', 'LED_3mm_C1A2': 'Faceplate_Hole_LED_3mm', # FLIP SWITCHES 'Switch_Toggle_SPDT_Mini_SolderLug': 'Switch_Toggle_Mini_6.35mm_With_Mask_Opening', 'SPDT-SUB': 'Faceplate_Hole_SubMini_Toggle', 'Switch_Toggle_SPDT_SubMini': 'Faceplate_Hole_SubMini_Toggle', # BUTTONS: 'BUTTON-LED-PB61303': 'Faceplate_Hole_LED_Button_7mm_With_Mask_Opening', 'RGB-SPST-LED-TC002': 'Faceplate_Hole_LED_Button_5.4mm_With_Mask_Opening', 'Button_RgbLED_SPST_TC002': 'Faceplate_Hole_LED_Button_5.4mm_With_Mask_Opening', 'Button_LED_PB61303_Adjusted+': 'Faceplate_Hole_LED_Button_7mm_With_Mask_Opening', 'Button_LED_PB61303': 'Faceplate_Hole_LED_Button_7mm_With_Mask_Opening', 'Button_RgbLED_SPST_PB615303HL-7mm': 'Faceplate_Hole_LED_Button_7mm_With_Mask_Opening', # SLIDE SWITCHES 'Slide_Switch_SS22D06-G6-H_Runrun': 'Faceplate_Slide_Switch_SS22D06_Runrun', 'Slide_Switch_Runrun_SS22D06': 'Faceplate_Slide_Switch_SS22D06_Runrun', 'SWITCHCRAFT-STEREO-SW_with_outline': 'Faceplate_Hole_Jack_Quarter_Inch', # SPACERS/MOUNTS/SLOTS 'Faceplate_Rail_Mount_Slot': 'Faceplate_Rail_Mount_Slot', 'Faceplate_Hole_Spacer_Mount_256': 'Faceplate_Hole_Spacer_Mount_256', 'Faceplate_Hole_FSR_slot': 'Faceplate_Hole_FSR_slot', 'last_item': 'last_item' } remove_fps = [ 'R0603', 'C0603', 'PAD-06', 'SOT-363_SC-70-6', 'SOT23-3_PO132', 'R_0603', 'C_0603', 'C_1206' ] io = pcbnew.PCB_IO() SCALE = 1000000.0 msg = "" for m in brd.GetModules(): center = m.GetPosition() try: footpr = str(m.GetFPID().GetFootprintName()) except: footpr = str(m.GetFPID().GetLibItemName()) if footpr in footprint_convert: msg += "Found Back layer footprint: {} at {}mm,{}mm. Changing to {}".format( footpr, center.x / SCALE, center.y / SCALE, footprint_convert[footpr]) msg += "\n" faceplate_mod = io.FootprintLoad(footprint_lib, footprint_convert[footpr]) # Reflect over midline y-axis new_x = midline - (center.x - midline) center.x = new_x faceplate_mod.SetPosition(center) # pads = faceplate_mod.Pads() # for pad in pads: # pad.SetNet(net) brd.Add(faceplate_mod) brd.Remove(m) continue if m.GetLayer() == remove_layer: brd.Remove(m) continue if footpr in remove_fps: brd.Remove(m) continue msg += "Unknown Back layer footprint: {} at {}mm,{}mm. ".format( footpr, center.x / SCALE, center.y / SCALE) msg += "\n" return msg
def placeFootprint(self,pt,orientation,name): io = pcbnew.PCB_IO() footprint = io.FootprintLoad(A100FrontPanel.FOOTPRINT_LIB,name) footprint.SetPosition(pt) footprint.SetOrientationDegrees(orientation) self.fp.Add(footprint)
def AddMountingHoles(): footprint_lib = '/home/mmccoo/kicad/kicad-footprints/MountingHole.pretty' board = pcbnew.GetBoard() # the internal coorinate space of pcbnew is 10E-6 mm. (a millionth of a mm) # the coordinate 121550000 corresponds to 121.550000 SCALE = 1000000.0 rect = None for d in board.GetDrawings(): if (d.GetLayerName() != "Edge.Cuts"): continue if (rect == None): rect = d.GetBoundingBox() else: rect.Merge(d.GetBoundingBox()) #print("{}".format(str(d))) #print("on layer {} {} {}".format(d.GetLayerName(), # str(d.GetStart()), # str(d.GetEnd()))) print("bbox of boundary is centered at {}. Width: {}, Height {}".format( rect.Centre(), rect.GetWidth(), rect.GetHeight())) print("left {} {} {} {}".format(rect.GetLeft(), rect.GetBottom(), rect.GetRight(), rect.GetTop())) io = pcbnew.PCB_IO() board = pcbnew.GetBoard() mod = io.FootprintLoad(footprint_lib, "MountingHole_3.2mm_M3") # what I really want to do is inflating by a negative amount, # but that function takes a xwCoord, which I don't know how # to create given the current python interface. # in this case we want to compute where the mounting # holes should go. # I am reducing with the full width/height of the module because # adjusting width/height of the rect needs both sides modbox = GetModBBox(mod) rect.SetWidth(rect.GetWidth() - modbox.GetWidth()) rect.SetHeight(rect.GetHeight() + modbox.GetHeight()) rect.SetX(rect.GetX() + modbox.GetWidth() / 2) rect.SetY(rect.GetY() - modbox.GetHeight() / 2) print( "new bbox of boundary is centered at {}. Width: {}, Height {}".format( rect.Centre(), rect.GetWidth(), rect.GetHeight())) print("left {} {} {} {}".format(rect.GetLeft(), rect.GetBottom(), rect.GetRight(), rect.GetTop())) # this is here for testing on an empty design # for mod in board.GetModules(): # board.Remove(mod) for point in GetRectCorners(rect): # this looks like a redundant call given the similar call above. # this call basically instantiates a new one. We don't want to add it twice. mod = io.FootprintLoad(footprint_lib, "MountingHole_3.2mm_M3") print("location {}".format(point)) modbox = GetModBBox(mod) point.x = point.x - modbox.Centre().x + mod.GetPosition().x point.y = point.y - modbox.Centre().y + mod.GetPosition().y mod.SetPosition(point) print("mod pos {}, {}".format(point, modbox.Centre())) print("x {} y {}".format(point.x - modbox.Centre().x, point.y - modbox.Centre().y)) board.Add(mod) # In the future, this build connectivity call will not be neccessary. # I have submitted a patch to include this in the code for Refresh. # You'll know you needed it if pcbnew crashes without it. board.BuildConnectivity() pcbnew.Refresh() print("done")