Writing an SVG

Here is where things happen. I’m sure if kicad include the svgwrite package or if it picks it up from my python install area. I did need to install it to python to do some experiments before doing anything in Kicad.

Edit Nov 15, 2017

Due to kicad’s change to color management (in favor of RGB over colornames), the code below is not uptodate. Go to github for the latest working version.

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.

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

Class diagram

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

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. ↩

Nets

Want to know all of the nets in your board? Nets can be looked up in two ways:

by name

by netcode – a unique integer identifier for your net.

If you run this code:

# returns a dictionary netcode:netinfo_item
netcodes = board.GetNetsByNetcode()
# list off all of the nets in the board.
for netcode, net in netcodes.items():
print("netcode {}, name {}".format(netcode, net.GetNetname()))
# here's another way of doing the same thing.
print("here's the other way to do it")
nets = board.GetNetsByName()
for netname, net in nets.items():
print("method2 netcode {}, name{}".format(net.GetNet(), netname))
# maybe you just want a single net
# the find method returns an iterator to all matching nets.
# the value of an iterator is a tuple: name, netinfo
clknet = nets.find("/clk").value()[1]
clkclass = clknet.GetNetClass()
print("net {} is on netclass {}".format(clknet.GetNetname(),
clkclass))