KiCAD

How to initialize your KiCAD 8 project on the command line

TL;DR:

Inside the directory where you want to create the project, run

wget -qO- https://raw.githubusercontent.com/ulikoehler/KiCAD-ProcessAutomation/master/InitializeKiCad8Project.sh | bash /dev/stdin MyProject

You should replace MyProject (at the end of the command) with your project name.

Note: This will initialize an empty KiCAD project without any libraries. This is equivalent to creating a new project in KiCAD itself (using the GUI).

Continue reading →

Posted by Uli Köhler in Electronics, KiCAD, Shell

KiKit V-Cut panelization script template

#!/bin/sh
export DIRECTORY=panel
export PROJNAME=MyProject
mkdir -p $DIRECTORY
kikit panelize \
    --layout 'grid; rows: 4; cols: 2' \
    --tabs 'full' \
    --cuts 'vcuts ; layer: Edge.Cuts ; clearance: 0.4mm' \
    --post 'millradius: 2mm' \
    ${PROJNAME}.kicad_pcb ${DIRECTORY}/${PROJNAME}.kicad_pcb

Posted by Uli Köhler in KiCAD

KiKit breakaway tab panelization script template

#!/bin/sh
export DIRECTORY=panel
export PROJNAME=MyPCB
mkdir -p $DIRECTORY
kikit panelize \
    --layout 'grid; rows: 4; cols: 2; space: 2mm' \
    --tabs 'fixed; width: 5mm' \
    --cuts 'mousebites; drill: 0.5mm; spacing: 0.8mm; offset: -0.2mm' \
    --post 'millradius: 1mm' \
    ${PROJNAME}.kicad_pcb ${DIRECTORY}/${PROJNAME}.kicad_pcb

Posted by Uli Köhler in KiCAD

How to manually run KiCad KLC visual-diff

The kicad-library-utils have a nice visual diff tools which can be used to compare different versions of symbols.

Run it manually on a symbol library such as Regulator_Switching.kicad_sym using

python ~/dev/kicad-library-utils/html-diff/src/html_diff.py $(git rev-parse origin/master) Regulator_Switching.kicad_sym

This will compare the currently checked-out revision to the current origin/master revision (you might need to git fetch --all to update the current revision).

It will produce a directory Regulator_Switching.diff, containing one HTML files for each changed symbol.

Example:

Regulator_Switching.diff
└── TPS62130.html

 

Posted by Uli Köhler in KiCAD

How to fix “kicad-cli pcb export step” not exporting component 3D models

Problem:

You are trying to export a 3D STEP model of your PCB using a command such as

kicad-cli pcb export step MyPCB.kicad_pcb

but the resulting STEP file is missing all (or almost all) component models (i.e. only the PCB is exported).

Furthermore, in the output of the command, you can read

Cannot add a VRML model to a STEP file.

for every single component, for example

Add component R6.
Cannot add a VRML model to a STEP file.
Add component R21.
Cannot add a VRML model to a STEP file.
Add component C7.
Cannot add a VRML model to a STEP file.
Add component C16.
Cannot add a VRML model to a STEP file.

Solution:

Add the --subst-models flag to kicad-cli in order to automatically substitute VRML models with STEP models:

kicad-cli pcb export step MyPCB.kicad_pcb --subst-models

After that, all available component models will be exported just like in the viewer.

Posted by Uli Köhler in Electronics, KiCAD

How to fix unixODBC “Can’t open lib ‘postgresql’: file not found” on Linux

Problem:

When you try to connect to a PostgreSQL database using a ODBC application such as KiCAD (database library connection), you see the following error message:

[unixODBC][Driver Manager]Can't open lib 'postgresql' : file not found

Solution:

First, install the ODBC PostgreSQL driver adapter:

sudo apt -y install odbc-postgresql

Using that driver, you would typically use a driver setting such as

Driver={PostgreSQL Unicode}

 

Posted by Uli Köhler in Databases, KiCAD, Linux

KiCAD PostgreSQL database connection string example

This has been tested on Linux with sudo apt -y install odbc-postgresql:

Driver={PostgreSQL Unicode};Server=127.0.0.1;Port=5432;Username=kicad;Password=abc123;Database=kicad;

 

Posted by Uli Köhler in Databases, KiCAD

How to install easyeda2kicad on Linux

sudo pip install easyeda2kicad pydantic==1.10.7
mkdir -p ~/Documents/Kicad/easyeda2kicad

This will fix both this pydantic error:

Traceback (most recent call last):
  File "/usr/local/bin/easyeda2kicad", line 5, in <module>
    from easyeda2kicad.__main__ import main
  File "/usr/local/lib/python3.10/dist-packages/easyeda2kicad/__main__.py", line 12, in <module>
    from easyeda2kicad.easyeda.easyeda_importer import (
  File "/usr/local/lib/python3.10/dist-packages/easyeda2kicad/easyeda/easyeda_importer.py", line 6, in <module>
    from easyeda2kicad.easyeda.parameters_easyeda import *
  File "/usr/local/lib/python3.10/dist-packages/easyeda2kicad/easyeda/parameters_easyeda.py", line 26, in <module>
    class EeSymbolPinSettings(BaseModel):
  File "/usr/local/lib/python3.10/dist-packages/pydantic/_internal/_model_construction.py", line 131, in __new__
    cls.__pydantic_decorators__ = DecoratorInfos.build(cls)
  File "/usr/local/lib/python3.10/dist-packages/pydantic/_internal/_decorators.py", line 414, in build
    res.validators[var_name] = Decorator.build(
  File "/usr/local/lib/python3.10/dist-packages/pydantic/_internal/_decorators.py", line 249, in build
    func = shim(func)
  File "/usr/local/lib/python3.10/dist-packages/pydantic/_internal/_decorators_v1.py", line 77, in make_generic_v1_field_validator
    raise PydanticUserError(
pydantic.errors.PydanticUserError: The `field` and `config` parameters are not available in Pydantic V2, please use the `info` parameter instead.

For further information visit https://errors.pydantic.dev/2.0.2/u/validator-field-config-info

and this error related to the missing directory:

-- easyeda2kicad.py v0.6.3 --
Traceback (most recent call last):
  File "/usr/local/bin/easyeda2kicad", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.10/dist-packages/easyeda2kicad/__main__.py", line 239, in main
    if not valid_arguments(arguments=arguments):
  File "/usr/local/lib/python3.10/dist-packages/easyeda2kicad/__main__.py", line 161, in valid_arguments
    os.mkdir(default_folder)
FileNotFoundError: [Errno 2] No such file or directory: '/home/uli/Documents/Kicad/easyeda2kicad'

 

Posted by Uli Köhler in KiCAD

How I export KiCAD pick&place CSVs using kicad-cli

Since KiCAD 7.0, you can use the kicad-cli command line tool to export a pick & place position CSV file from a KiCAD project. You can also export an ASCII format, depending on what software you’ll use to process the data.

My standard export command uses the drill origin as a pick&place origin since you can place it anywhere you like:

kicad-cli pcb export pos MyPCB.kicad_pcb --format csv --use-drill-file-origin --units mm -o MyPCB.positions.csv

 

 

Posted by Uli Köhler in KiCAD

How to read KiCAD XML BOM using Python

This script reads an XML BOM (also called python-bom in kicad-cli) using beautifulsoup4 and – as an usage example, generates a RefDes to footprint name dictionary:

from bs4 import BeautifulSoup

def extract_footprints_by_ref_from_xml(filename):
    footprints_by_ref = {} # e.g. "C3" => "Capacitor_SMD:C_0603_1608Metric"
    
    with open(filename, "r") as infile:
        soup = BeautifulSoup(infile, features="xml")
        
    for component in soup.export.components.findChildren("comp"):
        refdes = component.attrs["ref"]
        footprints_by_ref[refdes] = component.footprint.text
    
    return footprints_by_ref

 

Posted by Uli Köhler in KiCAD, Python

How to export KiCAD XML BOM using kicad-cli

kicad-cli sch export python-bom MyBoard.kicad_sch -o BOM.xml

 

Posted by Uli Köhler in KiCAD

How to export KiCAD PCB as PDF using kicad-cli

This command will create a PDF printout of the PCB. The following example prints the front side in front of the back side:

kicad-cli pcb export pdf MyPCB.kicad_pcb -l "F.Cu,F.Mask,F.Silkscreen,F.Courtyard,Edge.Cuts,B.Cu,B.Mask,B.Silkscreen,B.Courtyard" -o MyPCB.front.pdf

This is the corresponding command to print just the back side, so that it isn’t occluded by the front side.

kicad-cli pcb export pdf MyPCB.kicad_pcb -l "B.Cu,B.Mask,B.Silkscreen,B.Courtyard,Edge.Cuts" -o MyPCB.back.pdf

 

Posted by Uli Köhler in KiCAD

How to iterate footprint pads using KiCAD pcbnew plugin Python API

Iterate the pads of a given pcbnew.FOOTPRINT object using

for pad in list(footprint.Pads()):
    # Example of what to do with [pad]
    print(f"{footprint.GetReference()} {pad.GetNetname()}")

Example of how to print all pads for every footprint on the board:

for footprint in list(pcbnew.GetBoard().GetFootprints()):
    for pad in list(footprint.Pads()):
        # Example of what to do with [pad]
        print(f"{footprint.GetReference()} {pad.GetNetname()}")

This will print, for example:

D1 Net-(D1-K)

 

Posted by Uli Köhler in KiCAD, Python

How to get all footprints on board using KiCAD plugin Python API

Use the following for loop to iterate all footprints in the current board:

for footprint in list(pcbnew.GetBoard().GetFootprints()):
    # Example of what to do with [footprint]
    print(footprint.GetReference())

 

Posted by Uli Köhler in KiCAD, Python

How to get all selected zones using KiCAD pcbnew plugin Python API

In our previous post, we showed how to get all selected objects using the KiCAD python API using

pcbnew.GetCurrentSelection()

You can simply filter these entries to obtain just a list of selected zones using either a for loop with inline filtering:

for selected_object in pcbnew.GetCurrentSelection():
    if type(selected_object).__name__ == 'ZONE':
        print(selected_object.GetReference())

or using a list comprehension:

selected_footprints: list[pcbnew.FOOTPRINT] = [
    zone for zone in pcbnew.GetCurrentSelection() if type(zone).__name__ == 'ZONE'
]

Complete plugin example:

#!/usr/bin/env python
import pcbnew
import os

class SimplePlugin(pcbnew.ActionPlugin):
    def defaults(self):
        self.name = "Plugin Name as shown in Pcbnew: Tools->External Plugins"
        self.category = "A descriptive category name"
        self.description = "A description of the plugin and what it does"
        self.show_toolbar_button = False # Optional, defaults to False
        self.icon_file_name = os.path.join(os.path.dirname(__file__), 'simple_plugin.png') # Optional, defaults to ""

    def Run(self):
        board: pcbnew.BOARD = pcbnew.GetBoard()
        footprints: list[pcbnew.FOOTPRINT] = board.GetFootprints()
        
        # TODO Do something useful with [board]
        for selected_object in pcbnew.GetCurrentSelection():
            print(selected_object)

SimplePlugin().register() # Instantiate and register to Pcbnew

Example output (excerpt):

D39
D32
D23
D37
D18
D34
D11
D15

 

Posted by Uli Köhler in KiCAD, Python

KiCAD minimal pcbnew plugin example

The following python script is more or less the minimal example of a KiCAD pcbnew plugin from our previous post How to show wx dialog message in KiCAD pcbnew plugin.

#!/usr/bin/env python
import pcbnew
import wx

class DialogExamplePlugin(pcbnew.ActionPlugin):
    def defaults(self):
        self.name = "Show dialog example"
        self.category = "A descriptive category name"
        self.description = "A description of the plugin and what it does"
        self.show_toolbar_button = False # Optional, defaults to False

    def Run(self):
        dlg = wx.MessageDialog(None, "Please select one or multiple footprints!\n...or use Ctrl+A to select everything.", "No footprints selected", wx.OK | wx.ICON_ERROR)
        dlg.ShowModal()
        dlg.Destroy()

DialogExamplePlugin().register() # Instantiate and register to Pcbnew

You can place this plugin, for example, in

~/.local/share/kicad/7.0/scripting/plugins/DialogExamplePlugin.py

Don’t forget to refresh the plugins from the pcbnew menu.

Posted by Uli Köhler in KiCAD, Python

How to show wx dialog message in KiCAD pcbnew plugin

When using KiCAD’s Python API for pcbnew, you can show a dialog by using the following snippet

# Show info dialog
dlg = wx.MessageDialog(None, "Please select one or multiple footprints!\n...or use Ctrl+A to select everything.", "No footprints selected", wx.OK | wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()

Note that you need to

import wx

at the top of your plugin.

This code will show the following dialog:

 

Complete plugin example:

#!/usr/bin/env python
import pcbnew
import wx

class DialogExamplePlugin(pcbnew.ActionPlugin):
    def defaults(self):
        self.name = "Show dialog example"
        self.category = "A descriptive category name"
        self.description = "A description of the plugin and what it does"
        self.show_toolbar_button = False # Optional, defaults to False

    def Run(self):
        dlg = wx.MessageDialog(None, "Please select one or multiple footprints!\n...or use Ctrl+A to select everything.", "No footprints selected", wx.OK | wx.ICON_ERROR)
        dlg.ShowModal()
        dlg.Destroy()

DialogExamplePlugin().register() # Instantiate and register to Pcbnew

You can place this plugin, for example, in

~/.local/share/kicad/7.0/scripting/plugins/DialogExamplePlugin.py

Don’t forget to refresh the plugins from the pcbnew menu.

Posted by Uli Köhler in KiCAD, Python

Where to place custom KiCAD plugins on Linux?

In order to create a custom simple KiCAD plugin, save it as NAME.py in the following folder (where NAME is any filename such as MyTestPlugin):

~/.local/share/kicad/7.0/scripting/plugins

For example, you could place a plugin in

~/.local/share/kicad/7.0/scripting/plugins/MyPlugin.py

or in

~/.local/share/kicad/7.0/scripting/plugins/AddMyStuff.py

Note that you don’t need to restat pcbnew to load the plugins, you can just reload all plugins from the menu!

Posted by Uli Köhler in KiCAD

How to read KiCAD pick&place position file using pandas in Python

If you’ve exported a KiCAD pick & place position file using the GUI or the command line:

kicad-cli pcb export pos MyPCB.kicad_pcb --units mm -o MyPCB.pos

you can read it from within your Python script using pandas.read_table(...) like this:

import pandas as pd

pos = pd.read_table('KKS-Microcontroller-Board-R2.2.pos', delim_whitespace=True, names=["Ref", "Val", "Package", "PosX", "PosY", "Rot","Side"], comment="#")

Optionally, you can also index pos by the Ref column (which contains values such as C12D1 or U5):

pos.set_index("Ref", inplace=True)

You can also pack all that into a function:

def read_kicad_pos_file(filename):
    pos = pd.read_table(filename, delim_whitespace=True, names=["Ref", "Val", "Package", "PosX", "PosY", "Rot","Side"], comment="#")
    pos.set_index("Ref", inplace=True)
    return pos

If you’ve used .set_index(), you can access a component such as C13 using

pos.loc["C13"]

Example output:

Val                100nF_25V
Package    C_0603_1608Metric
PosX                187.1472
PosY               -101.8243
Rot                    180.0
Side                     top
Name: C1, dtype: object

 

Posted by Uli Köhler in KiCAD, pandas, Python