Kevin Cuzner's Personal Blog

Electronics, Embedded Systems, and Software are my breakfast, lunch, and dinner.


Arranging components in a circle with Kicad

I've been using kicad for just about all of my designs for a little over 5 years now. It took a little bit of a learning curve, but I've really come to love it, especially with the improvements by CERN that came out in version 4. One of the greatest features, in my opinion, is the Python Scripting Console in the PCB editor (pcbnew). It gives (more or less) complete access to the design hierarchy so that things like footprints can be manipulated in a scripted fashion.

In my most recent design, the LED Watch, I used this to script myself a tool for arranging footprints in a circle. What I want to show today was how I did it and how to use it so that you can make your own scripting tools (or just arrange stuff in a circle).

*The python console can be found in pcbnew under Tools->Scripting Console. *

Step 1: Write the script

When writing a script for pcbnew, it is usually helpful to have some documentation. Some can be found here, though I mostly used "dir" a whole bunch and had it print me the structure of the various things once I found the points to hook in. The documentation is fairly spartan at this point, so that made things easier.

Here's my script:

 1#!/usr/bin/env python2
 2
 3# Random placement helpers because I'm tired of using spreadsheets for doing this
 4#
 5# Kevin Cuzner
 6
 7import math
 8from pcbnew import *
 9
10def place_circle(refdes, start_angle, center, radius, component_offset=0, hide_ref=True, lock=False):
11    """
12    Places components in a circle
13    refdes: List of component references
14    start_angle: Starting angle
15    center: Tuple of (x, y) mils of circle center
16    radius: Radius of the circle in mils
17    component_offset: Offset in degrees for each component to add to angle
18    hide_ref: Hides the reference if true, leaves it be if None
19    lock: Locks the footprint if true
20    """
21    pcb = GetBoard()
22    deg_per_idx = 360 / len(refdes)
23    for idx, rd in enumerate(refdes):
24        part = pcb.FindModuleByReference(rd)
25        angle = (deg_per_idx * idx + start_angle) % 360;
26        print "{0}: {1}".format(rd, angle)
27        xmils = center[0] + math.cos(math.radians(angle)) * radius
28        ymils = center[1] + math.sin(math.radians(angle)) * radius
29        part.SetPosition(wxPoint(FromMils(xmils), FromMils(ymils)))
30        part.SetOrientation(angle * -10)
31        if hide_ref is not None:
32            part.Reference().SetVisible(not hide_ref)
33    print "Placement finished. Press F11 to refresh."

There are several arguments to this function: a list of reference designators (["D1", "D2", "D3"] etc), the angle at which the first component should be placed, the position in mils for the center of the circle, and the radius of the circle in mils. Once the function is invoked, it will find all of the components indicated in the reference designator list and arrange them into the desired circle.

Step 2: Save the script

In order to make life easier, it is best if the script is saved somewhere that the pcbnew python interpreter knows where to look. I found a good location at "/usr/share/kicad/scripting/plugins", but the list of all paths that will be searched can be easily found by opening the python console and executing "import sys" followed by "print(sys.path)". Pick a path that makes sense and save your script there. I saved mine as "placement_helpers.py" since I intend to add more functions to it as situations require.

Step 3: Open your PCB and run the script

Before you can use the scripts on your footprints, they need to be imported. Make sure you execute the "Read Netlist" command before continuing.

The scripting console can be found under Tools->Scripting Console. Once it is opened you will see a standard python (2) command prompt. If you placed your script in a location where the Scripting Console will search, you should be able to do something like the following:

 1PyCrust 0.9.8 - KiCAD Python Shell
 2Python 2.7.13 (default, Feb 11 2017, 12:22:40)
 3[GCC 6.3.1 20170109] on linux2
 4Type "help", "copyright", "credits" or "license" for more information.
 5>>> import placement_helpers
 6>>> placement_helpers.place_circle(["D1", "D2"], 0, (500, 500), 1000)
 7D1: 0
 8D2: 180
 9Placement finished. Press F11 to refresh.
10>>>

Now, pcbnew may not recognize that your PCB has changed and enable the save button. You should do something like lay a trace or some other board modification so that you can save any changes the script made. I'm sure there's a way to trigger this in Python, but I haven't got around to trying it yet.

Conclusion

Hopefully this brief tutorial will either help you to place components in circles in Kicad/pcbnew or will help you to write your own scripts for easing PCB layout. Kicad can be a very capable tool and with its new expanded scripting functionality, the sky seems to be the limit.