Generating regression type tests for pcbnew python

Or if you just want to know the pcbnew API used by a pcbnew plugin.
In my github, you’ll find some code that will wrap all of pcbnew’s functions and methods to track the API calls made by a pcbnew plugin. I wrote it primarily to aid the creation of regression tests.
The output is a “journal” file that should repeat/replay a plugin’s actions.
Over the last couple years, some of the APIs have changed, sometimes intentionally, but often unknowingly. Part of the cure is to extend the regressions beyond the two or three tests that are in there now.
Here is a video describing what I did:

I hope it’s helpful. Comments is the preferred way to follow-up by I often don’t notice them for a while. If I don’t reply in a week or two, feel free to yell at me at mail@mmccoo.com
 
 …

Kicad c++ walkthrough – footprint APIs

I’ve gotten several requests to talk about how to decipher the kicad c++ code base, about how does one add new python APIs.
In the youtube video below, I walk through the changes I needed to make to enable querying about the available footprint libraries. As I walk through the code, I try to give insight on how the code related to that change is put together.
There is a little bit of discussion of this patch on the kicad developer list.
The patch I talk about can be view here.
The old (bad) patch can be viewed here.

The three new APIs (which will hopefully be merged):
[code]
# return a list of modules in a library. Takes a library name:
mods = pcbnew.FootprintsInLib(‘MountingHole’)
# Returns information about a footprint.
# The ‘:’ delimiter between the library and modules is important.
pcbnew.FootprintInfo(‘MountingHole:MountingHole_3.2mm_M3’)
# output:
{ ‘uniquepadcount’: 0, ‘padcount’: 0, ‘name’: ‘MountingHole_3.2mm_M3’,
‘lib’: ‘MountingHole’, ‘doc’: ‘Mounting Hole 3.2mm, no annular, M3’,
‘ordernum’: 0, ‘keywords’: ‘mounting hole 3.2mm no annular m3’}") FootprintInfo;
# returns a list of all available footprint libraries
pcbnew.GetLogicalLibs;
[/code]
 
 
 
 …

Scripting fusion 360 designs into kicad

This blog is about scripting in kicad/pcbnew. This post tries to showcase some of the things that you can do with python scripts in pcbnew.
The layout of this board was designed in fusion 360 and brought into kicad via scripting. Very little manual work was required in pcbnew; it amounted mostly to deleting stuff and changing some zone names. The scripts also did the routing and placed the many vias
The code I demonstrate can be found on my git hub here and here.

This board implements a ring light for photography (I use multiple boards to stay within the 10×10 limit of cheap fabricators:

I’ve created a video show all of the steps in kicad:

I won’t explain the code in this post, I’ll do that in future posts. I will, however, take a moment to recommend some useful python libraries:
The SciPy library is fantastic for graph algorithms like minimum spanning tree and delanay triangulation
The shapely library is very nice for polygon manipulation. Merging polygons, bloating and shrinking them…
The dxf_grabber library is how I parse dxf files. Together with shapely, you can do a lot of import stuff.
Hope it helps…

Zones with holes from SVG

I’ve written about zones and boundaries before. Since then, the data structs behind zones have changed a bit. Also, I didn’t cover zones with holes. The old post is still relevant and there’s a bunch I won’t repeat here.
In this post, I talk about zones with holes and with multiple boundaries. Multiple boundaries makes it easier to move the zones together as a unit.
The code associated with this post is here.

Here’s a video talking mostly about the steps needed in inkscape to draw the graphic. Also has scripting details, but the text below is probably more informative:

 

Zone basics, revisited

pcbnew zones are stored in ZONE_CONTAINERs. They are what you get when you call board.InsertArea to create a new zone. Something like this:
[code]
SCALE = 1000000.0
zone_container = board.InsertArea(powernet.GetNet(), 0, powerlayer,
int(10*SCALE), int(10*SCALE),
pcbnew.CPolyLine.DIAGONAL_EDGE)
[/code]
That creates a single point zone on net powernet and layerpowernet
To modify the zone, you need to access the shape_poly_set. It’s a single data struct that holds all of the coordinates.
[code]
shape_poly_set = zone_container.Outline()
[/code]
To add points:
[code]
shape_poly_set.Append(int(10*SCALE), int(20*SCALE))
[/code]
But there are some details hidden there. Append actually takes a bunch more arguments.…

Panelizing Kicad gerbers

When I google for kicad and panelize, a top link is this one which talks about this panelizer written by Stijn Kuipers. The instructions given there are almost enough for me
I had two difficulties with the panelizer, but once I got beyond those, the process is quite easy. The troubles for me where:

  • I’m a linux guy. The released version doesn’t run under mono. There’s a side version that works well
  • I’m a kicad guy and the hackaday tutorial, while mentioning kicad, seems targeted at Eagle people. This is also easy to deal with if you know a couple key pieces of information.

Edit Dec 29, 2017: I’ve added a section simple panelizing directly in Kicad. Also, I added a comment on pcbshopper in the rant

Running on linux

When I run the released panelizer via the latest mono I could find for linux, I ran into the issue reported here, ie I get a message that contains this:

System.ArgumentException: XOR data length expected 

There’s a bunch of discussion in the issue, but the short answer is to use a compile that runesoeknudsen attached to the ticket. The compiled working version can be downloaded here.…

Copying schematic placement to layout

When importing a netlist to pcbnew, I get what appears to be a random placement. While the schematic placement is usually not a final placement for layout, it’s surely better than random.
For example, say I have a schematic like this (click to enlarge). The leds are annotated D1-8 down the first column.
This is the placement that comes out of netlist read. I don’t see a pattern.

If I run this script from my github, I’ll get this:

Not final, but it’s a sane starting point.
This short two minute video demonstrates. Not much to show, really:
 

How does it work? Pretty simple, actually. I parse the sch file for its device locations  and apply them to the layout. Most of it has been covered in my previous posts, but there are a couple of new things.

Where’s the schematic?

kicad has some infrastructure, called kiway, to pass information between applications. I suspect one could ask for a schematic file path there. I found it easy enough to ask pcbnew for the path to the current board and simply change the file extension.
[code]
import pcbnew
board = pcbnew.GetBoard()
board_path = board.GetFileName()
sch_path = board_path.replace(".kicad_pcb", ".sch")
[/code]

Getting location/transform from the sch

components look like this in the sch files:
[code]
$Comp
L Device:LED D49
U 1 1 5A3B7115
P 6650 1500
F 0 "D49" H 6641 1716 50 0000 C CNN
F 1 "LED" H 6641 1625 50 0000 C CNN
F 2 "Miles:LED_5730" H 6650 1500 50 0001 C CNN
F 3 "~" H 6650 1500 50 0001 C CNN
1 6650 1500
1 0 0 -1
$EndComp
[/code]
I found a bit of documentation on the format on this website, but it’s not complicated.…

Learnings from moving Kicad to wxPython 4.0

This post is likely only of potential interest to Kicad developers.
Kicad uses wx as its GUI platform and has a python interpreter built in. wxPython is used to bridge between wx and python. Kicad uses SWIG to expose its internal data structures to the Python world.
EDIT: the quote below mis-characterizes the person being quoted. See here for a good clarification of what he meant
I think strong scripting is one the best features many tools can provide but I fear that the kicad development team doesn’t share in my enthusiasm. One of the reasons given why python support may be dropped is the need to migrate to wxPython 4.0, which is a rewrite of the previous 3.0.
https://lists.launchpad.net/kicad-developers/msg31672.html

Another thing, there will be no more wxPython releases. The project has been renamed to Phoenix and AFAIR nobody has tried to use it with KiCad. It may turn out that our SWIG work might be dropped/converted or we will stay stuck with wx3.0 forever.

I encourage everyone that finds the python interface to kicad valuable to post to the kicad developers list.
So I tried running Kicad with the Phoenix version of wxPython. It seems to work, but it’s not quite ready to be used in released kicad.…

Modify design rules from python

I was recently asked on the kicad.info forum how to create a new netclass. It was already possible to modify existing ones, but the constructor for new ones hadn’t been exposed to the python interface. I’ve submitted the change to the kicad folks and it’s in the nightly builds.
Even with the constructor exposed, the sequence of steps to get to it isn’t obvious.
[code]
import pcbnew
board = pcbnew.GetBoard()
ds = board.GetDesignSettings()
# ugly. exposes a public member not via an accessor method
nc = ds.m_NetClasses
foo = pcbnew.NETCLASSPTR("foo")
nc.Add(foo)
[/code]
The nc variable (NETCLASSPTR) has lots of useful get’er set’er functions, like SetClearance, SetTrackWidth. These are easy to find in the python window. Just type “foo.” and you should get a popup of available functions. You can also run the function “dir(foo)”…

Pan, Zoom, Refresh from python in pcbnew

So you’ve written a cool new layout modification utility in python. It sure would be nice to see the results on the screen. This is an issue I faced with my placement replicator script. It does what I want except that the user has to click the refresh button to see the results.
Now there’s a way to trigger zoom, pan, and refresh from python. As of this writing (March 20, 2017), you need to use one of the nightlies or build yourself.
To refresh the screen:
[code]
pcbnew.Refresh()
[/code]
To pan and zoom, you need to supply x,y, width, height:
[code]
x = pcbnew.FromMM(10)
y = pcbnew.FromMM(10)
width = pcbnew.FromMM(20)
height = pcbnew.FromMM(20)
pcbnew.WindowZoom(x, y, width, height)
[/code]

Contributing to Kicad is painless

I initially searched and searched in pcbnew’s C code for python APIs like these. Eventually, I came to realize that they didn’t exist yet in pcbnew. So finally, I have my very first code contribution to an open source project.
I’ve been paid to write software for many years but it’s all been in-house stuff. My professional environment was pretty loosey-goosey, with very few formal constraints. Over the years, I’ve read lots of stories about how open source projects can be a pain to deal with.…