modifying pcbnew layout from python

I my previous post, I talked about querying for information about your layout. In this one I’ll show you how to create your own wires/vias from python. I also cover moving modules. Most of the code is self-explanatory but I find it helpful to have sample “cookbook” code.

The main thing to keep in mind when creating new objects is that even though you have to pass a board pointer to the constructors, you still have to call board.Add(obj). Also, you have to add it before setting the net. If you try to set the net before, it’ll do nothing.

Remember that the units are 1E-6mm. So if you have a mm value multiply it by a million.

Layers

First, let’s generate our layer mapping

layertable = {}

numlayers = pcbnew.LAYER_ID_COUNT
for i in range(numlayers):
 layertable[i] = board.GetLayerName(i)
 print("{} {}".format(i, board.GetLayerName(i)))

Add a track

track = pcbnew.TRACK(board)
track.SetStart(pcbnew.wxPoint(136144000, 95504000))
track.SetEnd(pcbnew.wxPoint(176144000, 95504000))
track.SetWidth(1614400)
track.SetLayer(layertable["F.Cu"])

board.Add(track)
track.SetNet(clknet)

Add a via

In this case, I’m going to copy an existing via. Note that there is also the clone method, but doing it this way you’ll know how to generate a via from scratch.

There isn’t yet a direct way to query a via for its layers. The way I work around this is by looping through all layers and calling IsOnLayer This is one of the reasons I’m showing how to copy an existing via.

The via types will be one of these:

  • pcbnew.VIA_THROUGH
  • pcbnew.VIA_BLIND_BURIED
  • pcbnew.VIA_MICROVIA

The width if the via is the diameter. If you forget to set this, you’ll get funny behavior where via disappears from the display when you zoom in.

newvia = pcbnew.VIA(board)
# need to add before SetNet will work, 
# so just doing it first
board.Add(newvia)

toplayer=-1
bottomlayer=pcbnew.LAYER_ID_COUNT
for l in range(pcbnew.LAYER_ID_COUNT):
   if not track.IsOnLayer(l):
      continue
   toplayer = max(toplayer, l)
   bottomlayer = min(bottomlayer, l)

# now that I have the top and bottom layers, I tell the new
# via
newvia.SetLayerPair(toplayer, bottomlayer)
newvia.SetPosition(pcbnew.wxPoint(track.GetPosition().x+offset[0],
                                  track.GetPosition().y+offset[1]))
newvia.SetViaType(oldvia.GetViaType())
newvia.SetWidth(oldvia.GetWidth())
newvia.SetNet(tonet)

Moving a module

I haven’t tried creating a new module yet. I prefer to let the netlist importer do this for me. I do, however, find it useful to be able to move modules. They all come in on top of each other. There are a variety of placement algorithms one might want to implement. 1

Note that the orientation is degrees*10.0

peer.SetPosition(pcbnew.wxPoint(newx, newy))
peer.SetOrientation(180*10)

Class diagram

I’ve created a class diagram to help me remember. Click to enlarge. Also available in my github


  1. In my previous professional life, one of the more interesting ones I saw was using linear programming. You start with everything in the middle. You create a set of equations representing net connectivity as well as cell overlaps. Solve the equations. Repeat. It was good for a couple hundred thousand cells. Much more than what PCB requires. Simulated Annealing would likely be easier here.

Leave a Reply

Your email address will not be published. Required fields are marked *