Skip to main content

Scripting KiCad Pcbnew exports

This is my first post in a series about the open source split-flap display I’ve been designing in my free time. Check out a video of the prototype.

Posts in the series:
Scripting KiCad Pcbnew exports
Automated KiCad, OpenSCAD rendering using Travis CI
Using UI automation to export KiCad schematics
OpenSCAD Rendering Tricks, Part 2: Laser Cutting
OpenSCAD Rendering Tricks, Part 3: Web viewer

For the past few months I’ve been designing an open source split-flap display in my free time — the kind of retro electromechanical display that used to be in airports and train stations before LEDs and LCDs took over and makes that distinctive “tick tick tick tick” sound as the letters and numbers flip into place.

I designed the electronics in KiCad, and one of the things I wanted to do was include a nice picture of the current state of the custom PCB design in the project’s README file. Of course, I could generate a snapshot of the PCB manually whenever I made a change by using the “File→Export SVG file” menu option and then check that image into my git repo…


…but that gets tedious, is prone to human error, pollutes the git history with a bunch of old binary files, and isn’t very customizable.

For instance, the manual SVG export uses opaque colors which make it hard to see features that overlap, as well as using two different colors for items on the same layer (yellow and teal are both part of the front silkscreen layer below):

Functional rendering, but not exactly what I wanted.
Luckily, Pcbnew has built-in Python bindings which make it pretty straightforward to invoke certain features from standalone Python scripts. As a simple example, here’s how to plot a single layer to an SVG:

import pcbnew

# Load board and initialize plot controller
board = pcbnew.LoadBoard("splitflap.kicad_pcb")
pc = pcbnew.PLOT_CONTROLLER(board)
po = pc.GetPlotOptions()
po.SetPlotFrameRef(False)

# Set current layer
pc.SetLayer(pcbnew.F_Cu)

# Plot single layer to file
pc.OpenPlotfile("front_copper", pcbnew.PLOT_FORMAT_SVG, "front_copper")
print("Plotting to " + pc.GetPlotFileName())
pc.PlotLayer()
pc.ClosePlot()


As a minor note, there's not much documentation of the Python bindings, but if you search through the KiCad source code you can find the C++ interfaces that are exposed to Python. E.g. above, pcbnew.F_Cu is one of many possible layer constants and pcbnew.PLOT_FORMAT_SVG is one of several different plot formats.

While it’s in theory possible to specify the colors to use when plotting, I ran into issues where certain items were always plotted in their default color. For instance, when I plot the front silkscreen layer with the following options, the footprints are plotted in teal rather than the specified color, red:

pc.SetLayer(pcbnew.F_SilkS)
pc.SetColorMode(True)
po.SetColor(pcbnew.RED) # <-- NOTE THIS LINE po.SetReferenceColor(pcbnew.GREEN)
po.SetValueColor(pcbnew.BLUE)


A lot of the silkscreen ended up teal instead of red.

So instead of trying to get Pcbnew to output the exact SVG I wanted, I decided to export each layer as a separate monochrome SVG image and then post-process them to apply colors and merge them into a single output file. Since SVG images are just XML, it was easy to write a script, svg_processor.py, which allowed me to override the “fill” and “stroke” style attributes of the shapes, and then wrap all of the shapes in a <g> group tag to set the desired opacity.

(Note: the reason for wrapping in a group before applying opacity is that things like traces are rendered as a combination of multiple shapes, like a line + circle, so if you applied alpha=0.5 to each shape individually, a single trace would have varying degrees of opacity depending on how its subcomponents overlapped)

This allowed me to write a simple definition of the PCB layers to export and turn that into a nice, customizable rendering:

layers = [
  {'layer': pcbnew.B_SilkS, 'color': '#CC00CC', 'alpha': 0.8 },
  {'layer': pcbnew.B_Cu, 'color': '#33EE33', 'alpha': 0.5 },
  {'layer': pcbnew.F_Cu, 'color': '#CC0000', 'alpha': 0.5 },
  {'layer': pcbnew.F_SilkS, 'color': '#00CCCC', 'alpha': 0.8},
]

Ooooh, so beautiful!

As a final step after processing and merging, I use Inkscape's command line interface to shrink the .svg canvas to fit the image and convert the vector .svg file into a raster .png image like you see above:

inkscape --export-area-drawing --export-width=320 --export-png output.png --export-background '#FFFFFF' input.svg

The complete script to export .svg and .png renderings of the PCB can be found at https://github.com/scottbez1/splitflap/blob/580a11538d801041cedf59a3c5d1c91b5f56825d/electronics/generate_svg.py

In the next post, I cover how I automated this rendering process on every commit using Travis CI with S3 deployments to keep the image and gerbers referenced in the README always up to date!

Comments

  1. Have you read this: https://lists.launchpad.net/kicad-developers/msg25213.html ?

    ReplyDelete
  2. Have you considered breaking out the SVG code into a separate Python library? I think your approach remains useful, even if all the quirks on the C++ side get worked out.

    ReplyDelete

Post a Comment

Popular posts from this blog

OpenSCAD Rendering Tricks, Part 3: Web viewer

This is my sixth post in a series about the  open source split-flap display  I’ve been designing in my free time. Check out a  video of the prototype . Posts in the series: Scripting KiCad Pcbnew exports Automated KiCad, OpenSCAD rendering using Travis CI Using UI automation to export KiCad schematics OpenSCAD Rendering Tricks, Part 1: Animated GIF OpenSCAD Rendering Tricks, Part 2: Laser Cutting OpenSCAD Rendering Tricks, Part 3: Web viewer One of my goals when building the split-flap display was to make sure it was easy to visualize the end product and look at the design in detail without having to download the full source or install any programs. It’s hard to get excited about a project you find online if you need to invest time and effort before you even know how it works or what it looks like. I’ve previously blogged about automatically exporting the schematics, PCB layout , and even an animated gif of the 3D model to make it easier to understand the project at a glanc

OpenSCAD Rendering Tricks, Part 1: Animated GIF

This is my fourth post in a series about the open source split-flap display I’ve been designing in my free time. Check out a video of the prototype . Posts in the series: Scripting KiCad Pcbnew exports Automated KiCad, OpenSCAD rendering using Travis CI Using UI automation to export KiCad schematics OpenSCAD Rendering Tricks, Part 1: Animated GIF OpenSCAD Rendering Tricks, Part 2: Laser Cutting OpenSCAD Rendering Tricks, Part 3: Web viewer Early when designing the split flap 3D model using OpenSCAD I wanted to include a visualization in the project’s README so others could see what it looked like. It’s possible to capture an image manually (File→Export→Export as Image), but that’s an extra thing to remember to do after every change and it’s also not very consistent. The image that’s exported is basically a snapshot of the current preview window, so the image dimensions and camera angle would be different each time. Plus, a single static image doesn’t fully convey the 3D mo