Adding your own command buttons to the pcbnew GUI

UPDATE April 14, 2017: You no longer need to use the hardcoded numbers like 6038 mentioned below. You can use pcbnew.ID_H_TOOLBAR.
 
Kicad has three rows of command buttons with predefined functionality. This post is about how to add your own button.
The sample code can be found here.

Perliminaries

Before getting into the code, there are a couple things that are weird about kicad/wxPython’s behavior

Getting proper aui pointers

The first thing is that if you simply open the python scripting window in pcbnew, find the top level window, and look for the command bars, you’ll likely get a pointer of type wxControl. That type doesn’t have the APIs needed to look at, amend, and change the command buttons. The real type of these is wx.aui.AuiToolBar but unless the pointer is cast correctly, you’re out of luck.
After a bunch of poking around, running in the debugger, trying to recompile (unsuccessfully) wxPython with debug symbols turned on, I stumbled upon the easy answer. You have to do this before you run any of the wx scripting apis.
[code]
import wx
import wx.aui # this is the key one
[/code]
After running these, you’ll get the correct pointer types.…

How to add mounting holes

Most of the time, the modules in your design will be introduced via netlist import from eeschema. An important exception to this is mounting holes. Your design may need some holes to enable you to screw the resulting board onto some sort of case/enclosure. In the GUI, you’d do this via the “Add footprints” command. This works, but what if you want to ensure that the resulting holes end up in specific locations? Script it!
Compared to other scripting tasks in pcbnew, figuring out how to add footprints to a design was a pain. In the end, it’s pretty easy
My designs are pretty simple, amounting to rectangular boards. My “enclosures” tend to be a piece of wood to which I mount a board with some drywall screws. Because of this simplicity, it doesn’t really matter where my mounting holes are. Still, I would like for them to at least be in a regular pattern. So I put together a script to put one in each corner of the board’s boundary.
First off, while pcbnew’s add footprint command can access kicad’s footprint libraries on GITHUB, this is not something I’ve achieved yet. For the code in this post to work, you’ll need to clone at least one of kicad’s footprint repos.…

adding GUI elements in pcbnew

In my last post, I talked about how you can run pcbnew headless. In many cases you actually want more GUI. For example, in my code sample for replicating module placement across multiple sheet instances, I have the pivot instances hard coded in the script. Why not do it in a GUI?
Adding GUI elements to pcbnew is what this post is about.. The code I’m talking about can be found here.
The pcbnew GUI is written using wxWidgets/wxPython. If you’re not familiar with wxPython, here is my favorite tutorial so far. All of its python APIs work fine for me in pcbnew so far. I’ve found there are two important things to keep in mind:

  • You don’t need to do the normal app = MyApp(0); app.MainLoop()
  • If you do print from callback (for debugging) the text will not be in the python window. Instead, you can find it in the terminal where you invoked kicad. Keep this in mind if you usually invoke from the kicad project manager or from you OS task launcher.

At the end of this post, we’ll have a new, not particularly attractive, window in pcbnew like this:

As usual, you’ll need some imports:

import wx
import pcbnew

To create a new window, you’ll want to create a new class derived from wx.Frame.…

pcbnew scripting doesn't require the GUI

If you just want to process something in the pcbnew data model, you don’t have to bring up the GUI. You can just start a python job directly from the commandline.
Why would you do this?
In my previous life working for a large semiconductor company, we had many, many quality checks and progress trackers. Now that experience was in VLSI, but surely there are parallels in the PCB world.
Management needs a way to track the progress of the project. Engineering needs a way to enforce layout standards. An obvious example of this is design rule checking. How many opens, shorts and spacing violations are there currently? There are many other things that one could check. Maybe you have rules about the clock network. Maybe you want to check that the power grid is strong enough to handle the current its being asked to carry. Maybe the sub-design you’re working on has some restrictions on it to ensure it’ll fit into the larger design.
At the beginning of a project, we had many millions of such violations. For a while the number wouldn’t change since we were still deciding on the bigger picture stuff. Eventually, we’d change gears and want to move towards tapeout.…

Zones, boundaries, and silkscreen

UPDATE April 14, 2017 two things have changed:

  • LAYER_ID_COUNT has been renamed to PCB_LAYER_ID_COUNT
  • Zones have been changed to use the same data structure as other stuff in kicad. As a result, some of the APIs have changed
    • instead of AppendCorner, you’ll need just Append
    • The Hatch method is on the Area, not the outline. I have not updated the text below, but the code in the github will work on the latest Kicad codebase soon.

 
In previous posts, I’ve talked about the main layout components. Tracks, modules, pads. In this one, I’m focusing on lines. The board boundary, zones, and silkscreens.
At the end of this post, I’ll have a script (you can find the full script here) that redraws the board boundary to shrink wrap around all of the existing components. It’ll also generate a zone on the clk net (of course, it’s more common to use power/gnd). The zone will have the same outline as the board.
Most of the code is pretty straightforward, but I do recommend looking closely at the notes about zones at the end of this post. There are a couple things that are not immediately obvious.
As a reminder, I have a uml diagram in my github area of useful, pcbnew python APIs (click for a bigger view)

Some preliminaries

First, it’s helpful to have a layername->layernumber lookup table.…

Replicating pcbnew new for arrayed sheets

Many circuit designs can have repeated structures. Sadly, pcbnew doesn’t have any features to make the placement and routing any more productive.
Here is a demo of a script I wrote to help:

If you have X copies of the same sheet in eeschema, the script will allow you to place and route one of them and them apply that to the other sheets.

How’s it work?

If you call GetPath() on the modules in your design, you’ll get values like these (note the the path is only the /number/number part):

mod Q1 path /587DA765/58758821
mod Q2 path /5875D13C/58758821
mod Q3 path /5875D13D/58758821
mod Q4 path /5875D13E/58758821
mod R1 path /587DA765/5875882F
mod R2 path /587DA765/5875883D
mod R3 path /5875D13C/5875882F
mod R4 path /5875D13C/5875883D

The first number tells you which sheet instance the module belongs to. The second is an identifier for the module. So from the information above we can tell that these are all in the same sheet:

mod Q1 path /587DA765/58758821
mod R1 path /587DA765/5875882F
mod R2 path /587DA765/5875883D

Similarly, we know that these are the same transistor, just in different instances of the sheet:

mod Q1 path /587DA765/58758821
mod Q2 path /5875D13C/58758821
mod Q3 path /5875D13D/58758821
mod Q4 path /5875D13E/58758821

So if I have placed and routed sheet 587DA765, the script just needs to find all of the members of 5875D13C and simply adjust their positions by some constant increment.…

Querying pcbnew to generate a basic svg file

In a previous post, I gave some basic query capabilies in pcbnew. In this post, I’ll use that to generate a simple svg file.
The result looks like this:

Not the most interesting layout and a bunch of detail is missing, but I was happy to get this far. The code is hopefully self-explanatory. After the last post, I don’t really know what I can add.
The code can be found in my github

Preliminaries

I need to get each of pcbnew’s layer colors. Some of the color names are modified to match svr colors. The real answer is to get the rgb values from colorrefs, but those aren’t exposed in python today
Edit Nov 15, 2017 RGB values are now available in the form of the COLOR4D structure.
[code]
colors = board.Colors()
c4 = colors.GetLayerColor(track.GetLayer())
r = int(round(c4.r*255)
g = int(round(c4.g*255)),
b = int(round(c4.b*255))
[/code]
The colornames map below won’t work anymore.
End edit

colornames = {
 pcbnew.BLACK: 'BLACK',
 pcbnew.DARKDARKGRAY: 'DARKSLATEGRAY', # 'DARKDARKGRAY',
 pcbnew.DARKGRAY: 'DARKGRAY',
 pcbnew.LIGHTGRAY: 'LIGHTGRAY',
 pcbnew.WHITE: 'WHITE',
 pcbnew.LIGHTYELLOW: 'LIGHTYELLOW',
 pcbnew.DARKBLUE: 'DARKBLUE',
 pcbnew.DARKGREEN: 'DARKGREEN',
 pcbnew.DARKCYAN: 'DARKCYAN',
 pcbnew.DARKRED: 'DARKRED',
 pcbnew.DARKMAGENTA: 'DARKMAGENTA',
 pcbnew.DARKBROWN: 'MAROON', # 'DARKBROWN',
 pcbnew.BLUE: 'BLUE',
 pcbnew.GREEN: 'GREEN',
 pcbnew.CYAN: 'CYAN',
 pcbnew.RED: 'RED',
 pcbnew.MAGENTA: 'MAGENTA',
 pcbnew.BROWN: 'BROWN',
 pcbnew.LIGHTBLUE: 'LIGHTBLUE',
 pcbnew.LIGHTGREEN:

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 basics of scripting in pcbnew

I’ve found that, so far, I’m able to do all of the layout queries and manipulations I’ve wanted to do.
Edit April 3, 2018 The comment below about 4.0.5 is not true. Even the most recent 4.0.7 is missing a ton of python related stuff. Until kicad 5.0 comes out, I recommend using one of the nightly builds from the kicad downloads page. End Edit
Note that these examples don’t work on the latest release as of Feb 2017 (4.0.5). You want one of the nightly builds, also in the kicad download area. Or you can build it
The interface is lacking some consistency but it’s fine if you have a map of the classes (click for a larger version or download it from here):

 
In this post, I’ll focus on querying a board for information about it’s contents. The code can be found in this github repo.

Getting started

To invoke any of these examples, you’ll want pcbnew’s scripting window. Tools->scripting console
You’ll probably want these in your scripts

import pcbnew
# most queries start with a board
board = pcbnew.GetBoard()

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.

Compiling Kicad on Ubuntu

Edit Dec 29, 2017: added cmake flag enabling external plugins
Edit Aug 28,2018: added cmake flags for skipping more recent stuff like spice. Also added libboost-all-dev to list of packages installed
These instructions don’t work on ubuntu 18.0 or the recents linux mints (since they’re based on ubuntu 18). This is due to wxpython gtk2/3 issues.
end edit Aug 28, 2018
In my last post, I mentioned that compiling Kicad is something most would not be willing to do.
Most of the scripting in this blog will not work in version 4.0.5 which the most recent as of this writing. I recommend to install either the nightly or build yourself. If you just want the latest verion of Kicad, then you can find nightly builds in the Kicad Downloads Area
Well, this post is about the steps needed to run your own compiled version on Ubuntu . These steps worked for me on a freshly installed VirtualBox Ubuntu install.
The scripting support in the latest source based kicad has progressed a bit beyond the released Kicad. There are one or two APIs that have appeared and the scripting window has some IDE’ish features added . I do want to make some C++ changes, so I have the need to compile.…