Production Variants with KiBot

5 min read

#keebs#proto

Will Puckett

In August, I started working on what I thought would be a small, couple of hours project to make yet another diode matrix rework of the Ferris Sweep Half Swept for Seeed Xiao called Swoon. I hoped to make a flippable, hand-solderable version that could be produced as cheaply as possible, and a version that could be fully assembled by the board house.

I had been flirting with Andrey Shmakov’s idea of PCBOps, which I had been introduced to via Pete Johanson’s revxlp repository. As I began to explore KiBot, I found that what I was trying to do had a name: variant. Variants come in two types: production and assembly. While assembly variants primarily address the BOM and CPL files and are fully implemented in KiBot, production variants change the copper/mask/silk layers and are still under development. Luckily, I didn't realize there was a difference and just dove in expecting production variants to work, which with the help of the KiBot team, they have.

Structuring the Schematic

KiBot can use three different variant systems, which I think contributed to the difficulty I had unraveling how to use them. Components which need to be addressed with the system should have a field called Config, which can be added in the component properties view, or gloablly in the symbol editor (Schematic Editor > Tools > Edit Symbol Fields...).

I ultimately used the KiBoM variant style, which the docs describe as

The Config field (configurable) contains a comma separated list of variant directives.
    -VARIANT excludes a component from VARIANT.
    +VARIANT includes the component ONLY if we are using this variant.

Components with a Config field with no value are included in all variants.

I created a testpoint with a 0.00001mm pad as a placeholder (Swoon:TestPoint_Pad_Empty) and implemented the following in my symbol editor:

Reference Value Footprint LCSC Config flip:Footprint left:Footprint right:Footprint
J1,J2,J5,J6,...J61,J62,J65,J66 3305-0-15-80-47-27-10-0 Swoon:3305-0-15-80-47-27-10-0 C17370797 +left Swoon:TestPoint_Pad_Empty Swoon:3305-0-15-80-47-27-10-0 Swoon:TestPoint_Pad_Empty
J69,J71 310-13-107-41-001000 Swoon:MF254V-11-07-0743 C5504401 +left Swoon:TestPoint_Pad_Empty Swoon:MF254V-11-07-0743 Swoon:TestPoint_Pad_Empty
J73 Mill Max 0906-2-15-20-75-14-11-0 Swoon:0906-2-15-20-75-14-11-0 C5261048 +left Swoon:TestPoint_Pad_Empty Swoon:0906-2-15-20-75-14-11-0 Swoon:TestPoint_Pad_Empty
TP1,TP3,...TP17,TP19 TestPoint_Small Swoon:TestPoint_Pad_Empty +left Swoon:TestPoint_Pad_Empty Swoon:TestPoint_Pad_1.0x1.0mm Swoon:TestPoint_Pad_Empty
D1,D3,...D31,D33 CD4148WS Swoon:D_0805_2012Metric C38587762 +left,+flip Swoon:D_0805_2012Metric Swoon:D_0805_2012Metric Swoon:TestPoint_Pad_Empty
SW18 MST22D18G2 125 Swoon:SW-SMD_MST22D18G2 C2906280 +left,+flip Swoon:SW-SMD_MST22D18G2 Swoon:SW-SMD_MST22D18G2 Swoon:TestPoint_Pad_Empty
U2 MY-LR44-02 Swoon:BAT-SMD_MY-LR44-02 C2902345 +left,+flip Swoon:BAT-SMD_MY-LR44-02 Swoon:BAT-SMD_MY-LR44-02 Swoon:TestPoint_Pad_Empty
J3,J4,J7,J8...J63,J64,J67,J68 3305-0-15-80-47-27-10-0 Swoon:3305-0-15-80-47-27-10-0 C17370797 +right Swoon:TestPoint_Pad_Empty Swoon:TestPoint_Pad_Empty Swoon:3305-0-15-80-47-27-10-0
J70,J72 310-13-107-41-001000 Swoon:MF254V-11-07-0743 C5504401 +right Swoon:TestPoint_Pad_Empty Swoon:TestPoint_Pad_Empty Swoon:MF254V-11-07-0743
J74 Mill Max 0906-2-15-20-75-14-11-0 Swoon:0906-2-15-20-75-14-11-0 C5261048 +right Swoon:TestPoint_Pad_Empty Swoon:TestPoint_Pad_Empty Swoon:0906-2-15-20-75-14-11-0
TP2,TP4,...TP18,TP20 TestPoint_Small Swoon:TestPoint_Pad_Empty +right Swoon:TestPoint_Pad_Empty Swoon:TestPoint_Pad_Empty Swoon:TestPoint_Pad_1.0x1.0mm
D2,D4,...D32,D34 CD4148WS Swoon:D_0805_2012Metric C38587762 +right,+flip Swoon:D_0805_2012Metric Swoon:TestPoint_Pad_Empty Swoon:D_0805_2012Metric
SW19 MST22D18G2 125 Swoon:SW-SMD_MST22D18G2 C2906280 +right,+flip Swoon:SW-SMD_MST22D18G2 Swoon:TestPoint_Pad_Empty Swoon:SW-SMD_MST22D18G2
U3 MY-LR44-02 Swoon:BAT-SMD_MY-LR44-02 C2902345 +right,+flip Swoon:BAT-SMD_MY-LR44-02 Swoon:TestPoint_Pad_Empty Swoon:BAT-SMD_MY-LR44-02

Variants need to run a var_rename filter to replace footprints. I added the variants to swoon.kibot.yaml:

variants:
  - name: flip
    comment: For Hand Soldering
    type: kibom
    file_id: FLIP
    variant: flip
    pre_transform:
      - variant_rename
      - fix_rotation
  - name: left
    comment: Left for PCBA
    type: kibom
    file_id: LEFT
    variant: left
    pre_transform:
      - variant_rename
      - fix_rotation
  - name: right
    comment: Right for PCBA
    type: kibom
    file_id: RIGHT
    variant: right
    pre_transform:
      - variant_rename
      - fix_rotation

filters:
  - name: variant_rename
    comment: Remove single sided components
    type: var_rename
    separator: ':'
    variant_to_value: false

I exictedly pushed my changes, certain I had conquered the world. They errored shortly thereafter.

Setting Up the Action

I tottled around a little more, then posted my difficulties to the KiBot issues area.

Footprint replacements are still in dev, so I needed to use uses: INTI-CMNB/KiBot@v2_dk8 for the GitHub Action, and

{
  "image": "ghcr.io/inti-cmnb/kicad8_auto_full:dev"
}

for my devcontainer. I tried running my outputs and met a couple of additional errors. Over the following week, Salvador from the KiBot team resolved issues with drill file generation and getting replacement footprints on the correct side of the board. Salvador cautions that footprint replacement (production variants) are still in development, and asks that issues be reported with patience in as much detail as possible.

☙ ❧

I’m delighted to report that, using KiBot’s ‘var_rename’ filter as a ‘pre_transform’ for variants, I’m now able to output production variants using KiBot in a PCBOps pipeline. There were several issues I encountered along the way but the process seems to be working well now. Given that KiBot wasn’t successfully outputting the variant files before Salvador’s work and bug fixes over the past few weeks, it seems unlikely that people have done this using KiCad, and it has some really useful implications for keyboard designers.

If we examine for instance, the revxlp repository, there is a ‘10u’ and a 12u’ directory, both of which contain 3 different pcb files: a main pcb for components and switches, a top plate, and a bottom plate. With KiBot’s support of production variants, those could all be generated from the single 12u pcb file, using ‘var_rename’ to switch the board outline footprint to the 10u version, depopulate the unneeded components for the top and bottom plates, and replace the key switch footprint with the cutout version for the top plate. See this demonstration repository, which implements the concept. It's notable that being able to execute a global deletion of tracks and vias, or some other method to clean up the top and bottom plates would be nice. Using footprint replacement can even allow for switching graphic artwork on top and bottom plates as well, for those so inclined.

Using this sort of KiBot build matrix has made an iterative design approach more comfortable for me. I feel like I can focus my time having fun with board outlines and ergonomics without the cognitive burden of propogating changes across multiple outputs. Hopefully the simplified project structure makes it easier for others to navigate as well.