KicadでPython

KicadでPythonスクリプトを実行して、面倒な手順をスクリプト実行できるようになってます。どうやって、実装と実行を行えるのかのメモを残しておきます。

KicadのPython環境

Kicadは2系のPythonが使えるようになってます。(まだ2系です)Kicadのインストールディレクトリ下にpython.exeと関連ライブラリが配置されています

C:\Program Files\KiCad\bin\python.exe
C:\Program Files\KiCad\bin\pip.exe
C:\Program Files\KiCad\lib\python2.7\site-packages

また、以下のパスにスクリプトを配置しておくと、ファイル名を指定するだけで実行できます

%USERPROFILE%\AppData\Roaming\kicad\scripting\plugins

Kicad用Pythonスクリプトの実行方法

Python Plugin Development for Pcbnew

https://docs.kicad-pcb.org/doxygen/md_Documentation_development_pcbnew-plugins.html

例えば、pcbnew上でpythonスクリプトを実行したい場合は、pcbnewを起動して、「ツール」-「スクリプトコンソール」を起動すると、Kicad環境が利いた状態でPythonコンソールが立ち上がります。

kicad-python001

pluginsフォルダに実行したいスクリプトを配置して、

>>> import [module名(pythonファイル名)]
>>> module.function()

test.pyを作成して、func01()を実行する

# test.py
def func01():
  print "hello"
>>> import test
>>> test.func01()
hello

ただし、一度ロードしてしまうと、プログラムを修正しても反映されないので、その場合は一旦reload [module name]で再度ロードすれば、修正内容が反映される。

# test.py
def func01():
  print "hello world"
>>> reload test
>>> test.func01()
hello world

この方法ぐらしか、手軽にスクリプトを作成&実行する方法がよくわからないので、トラブルしたときのデバッグ方法がなくて大変そうです。

ほかに方法はないんですかね。。

pcbnewで開いている基板からモジュール部品を取得する

KiCad Pcbnew::Boad Python Scripting (doxygen)

https://mirrors.cqu.edu.cn/kicad/doxygen-python/classpcbnew_1_1BOARD.html

KiCAD Pcbnew マクロ Tips

https://hanya-orz.hatenablog.com/entries/2015/07/22

基板(現在アクティブになっているkicad_pcb)を取得するとからスタートするのが一般的なようです。

まず、基板の原点?を取得して座標値を見てみます。

# test.py
import pcbnew
def func1() :
  board = pcbnew.GetBoard()
  grid_origin = board.GetGridOrigin()
  print grid_origin
>>> import test
>>> test.func1()
(11430000, 11430000)

グリッドの原点を変更して再度実行してみる

kicad-python003

>>> import test
>>> test.func1()
(8890000, 8890000)

変更したところ、値が変わるので、ここでいうオリジンというのはグリッド原点のことで良さそう。X値は左から右へ、Y値は上から下へ値が大きくなるようです。

どうもこの座標値は内部値のようで、変換関数があります。

>>>board = pcbnew.GetBoard()
>>>grid_origin = board.GetGridOrigin()
>>>print grid_origin
(8890000, 8890000)
>>>print pcbnew.ToMM(grid_origin)
(8.89, 8.89)
>>>print pcbnew.ToMils(grid_origin)
(350.0, 350.0)

この値をみると、mm値を1000000倍したものを内部で持っている感じ(精度nm?)で、ToMM()ToMils()で変換できる感じらしい。

pcbnewの下部にある座標値でも確認できる。ここの値が(0,0)になる位置じグリッド原点を移動して、上記関数を実行するとすべて(0,0)になる。グリッド原点が内部的な基準位置と一致したことを表す。

kicad-python004

補助原点の取得は、pcbnew.GetAuxOrigin()で取得できる。値の変換は上記と同じ。

kicad-python005

>>> print board.GetAuxOrigin()
(19050000, 17780000)

設定するAPIももちろんあって、SetGridOrigin()SetAuxOrigin()になる。設定する値の単位はnmになる。

モジュールの基本情報取得

検証として、以下の様な単純な基板を作成して検証してみました。長方形の基板外形内に2個の抵抗を配置。

kicad-python002

GetModules()でモジュールのイテレータが取得できて、各モジュールはMODULEクラスから各種情報にアクセスできます。

import pcbnew
def mod_info() :
  for mod in pcbnew.GetBoard().GetModules():
    print "-----"
    print "ref=%s"%(mod.GetReference())
    print "value=%s"%(mod.GetValue())
    pos = pcbnew.ToMM(mod.GetPosition())
    print "pos_mm=(%.3f, %.3f)"%(pos)
    print "orient=%.3f"%(mod.GetOrientationRadians())

実行結果

-----
ref=R7
value=2.2k
pos_mm=(49.530, 49.530)
orient=1.571
-----
ref=R*
value=R-3.5x2.0
pos_mm=(35.560, 43.180)
orient=0.000

Kicad上で設定できるリファレンスや定数、位置、向きなどが取得できる。向きはRadian、Degree両方ある。

kicad-python006

GetPosition()は基板上の座標値と一致し、フットプリントの原点に相当するようです。

kicad-python007

モジュールの基本情報取得(その2)

Rectとかパッドの情報を取得

https://mirrors.cqu.edu.cn/kicad/doxygen-python/classpcbnew_1_1D__PAD.html

def mod_info2() :
  for mod in pcbnew.GetBoard().GetModules():
    print "-----"
    print "pad_count=%d"%(mod.GetPadCount())
    print "flip=%s"%(mod.IsFlipped())
    rect = mod.GetFootprintRect()
    pos = pcbnew.ToMM(rect.GetOrigin())
    print "foot_origin=(%.3f, %.3f)"%(pos)
    print "foot_width=%.3f"%(pcbnew.ToMM(rect.GetWidth()))
    print "foot_height=%.3f"%(pcbnew.ToMM(rect.GetHeight()))
    rect = mod.GetBoundingBox()
    pos = pcbnew.ToMM(rect.GetOrigin())
    print "bound_origin=(%.3f, %.3f)"%(pos)
    print "bound_width=%.3f"%(pcbnew.ToMM(rect.GetWidth()))
    print "bound_height=%.3f"%(pcbnew.ToMM(rect.GetHeight()))
    for pad in mod.Pads():
      pad_info(pad) 
    
def pad_info(pad):
  print "pad_padname=%s"%(pad.GetPadName())
  pos = pcbnew.ToMM(pad.GetPosition())
  print "pad_origin=(%.3f, %.3f)"%(pos)
  sz = pcbnew.ToMM(pad.GetSize())
  print "pad_size=(%.3f, %.3f)"%(sz)

実行結果

-----
pad_count=2
flip=False
foot_origin=(47.677, 40.565)
foot_width=3.706
foot_height=10.310
bound_origin=(47.677, 40.565)
bound_width=5.021
bound_height=10.310
pad_padname=2
pad_origin=(49.530, 41.910)
pad_size=(1.800, 1.800)
pad_padname=1
pad_origin=(49.530, 49.530)
pad_size=(1.800, 1.800)
-----
pad_count=2
flip=False
foot_origin=(34.535, 42.055)
foot_width=7.150
foot_height=2.250
bound_origin=(34.180, 42.055)
bound_width=7.960
bound_height=3.918
pad_padname=2
pad_origin=(40.640, 43.180)
pad_size=(1.600, 1.600)
pad_padname=1
pad_origin=(35.560, 43.180)
pad_size=(1.600, 1.600)

kicad-python008

リファレンスを見ると、ほとんどすべて?の情報が取得できる。ネット情報とか取れると外部連携などできそうである。

なんでこんな事しているかと言うと、以前投稿したがFusion360の制限で3Dデータ連携に制限が出てきている。

Kicad上で部品配置後の3DデータをSTEPのアセンブリデータとして出力できていたが、Fusion360からSTEPデータのエクスポートに制限が出てきたのでこれができなくなる。

じゃあKicad上でほしい配置情報だけエクスポートして、Fusion360上で自動アセンブル。。などを検討しています。

Kicadの3Dデータ作成ワークフロー(Fusion360個人利用)
https://www.usagi1975.com/202009221150/