ある日、基板を編集していました。
うーん...
あれ
素敵じゃん。
ということで、ビアで星空を作ります。
方針
星の数ほどのビアを手動で配置するのは大変なので、KiCadのPython Scriptingを使って自動化してみようと思います。
流れはこんな感じ
- データベースから星の座標を取得
- Python Scriptingでビアを配置
Python Scriptingを触ってみる
Python Scriptingでは、フットプリントのオブジェクトにアクセスして配置やプロパティの変更ができます。スクリプトはKiCadのスクリプトコンソールから実行します。
下記のサイトを参考にさせていただきました。
KiCadのPython scripting機能を使ってみる : 東京工業大学 ロボット技術研究会
KiCad PCBNew Python Scripting Cheat Sheet | atomic14
KiCad Pcbnew Python Scripting: pcbnew Namespace Reference
スクリプトを作る
まずは、スクリプトコンソールを立ち上げます。
PCBエディターのツール > スクリプトコンソール
またはツールバーのボタンから起動できます。
こんな画面が出てくるので、適当にprintでもしてみます。
>>> print("Hello, World!")
Hello, World!
よくある対話型シェルですね。
ただ、このままでは使い勝手がよくないので、pyファイルを作って実行してみます。
KiCadプロジェクトのルート(kicad_proファイルと同階層)にpyファイルを作り、適当なプログラムを書き込みます。
print("Hello, py file!")
実行するには下のようにimport <ファイル名>
をスクリプトコンソールで実行します。
>>> import main
Hello, py file!
以降はこのファイルを編集していきます。
ビアを作成する
pythonから基板を編集するにはpcbnewを使います。KiCadのPCBエディタはpcbnewをラップしているようです。
Pcbnew | 5.1 | 日本語 | Documentation | KiCad
まずは、pcbnewインポートしてBOARD
オブジェクトを取得します。
import pcbnew
board = pcbnew.GetBoard()
取得したBOARD
オブジェクトを介してパーツの追加や移動ができるようになります。注意としては、PCB図面全体をボードとして扱うため、Edge.Cuts
で囲んでいなくても図面全体がボードとなります。
次に、新しいビアを作成してみます。APIを参考にしてPCB_VIA
オブジェクトをインスタンス化します。
KiCad Pcbnew Python Scripting: pcbnew.PCB_VIA Class Reference
import pcbnew
board = pcbnew.GetBoard()
+ via = pcbnew.PCB_VIA(board)
+ via.SetX(int(0 * 1_000_000))
+ via.SetY(int(0 * 1_000_000))
+ via.SetWidth(int(1.5 * 1_000_000))
+ via.SetDrill(int(1.0 * 1_000_000))
コンストラクタの引数には親要素を渡します。今回は先ほど取得したBOARD
オブジェクトです。
__init__(PCB_VIA self, BOARD_ITEM aParent) -> PCB_VIA
ついでに位置と穴径、ランド系も指定します。
位置指定にはPCB_VIA
クラスが継承しているEDA_ITEM
クラスにSetPosition()
関数があるほか、BOARD_ITEM
クラスにSetX()
SetY()
関数があります。SetX()
SetY()
は引数がint型で使い勝手がいいため、今回はこちらで指定しています。
また、pcbnewでは位置や径などの長さをnmで管理しているため、関数の引数もnmに換算してから渡す必要があります。
最後に、作成したビアをボードに追加します。
import pcbnew
board = pcbnew.GetBoard()
via = pcbnew.PCB_VIA(board)
via.SetX(int(0 * 1_000_000))
via.SetY(int(0 * 1_000_000))
via.SetWidth(int(1.5 * 1_000_000))
via.SetDrill(int(1.0 * 1_000_000))
+ board.Add(via)
+ pcbnew.Refresh()
実行してみましょう。
>>> import main
位置(0, 0)に穴径1mm、ランド系1.5mmのビアが追加されました。これで任意の位置にビアを配置できるようになったので、次は配置する座標を決めていきます。
星の座標を取得する
星の座標としてAstro Commonsさんのヒッパルコス星座線恒星データを使わせていただきます。このデータセットには赤道座標を含む690個の恒星が収録されています。
pythonからダウンロードしたcsvファイルを読み込み、赤経と赤緯を抽出してみます。
import csv
with open('hip_constellation_line_star.csv') as f:
reader = csv.reader(f)
for row in reader:
ra = (float(row[1]) * 15) + (float(row[2]) * (15 / 60)) + (float(row[3]) * (15 / 3600))
dec = float(row[4]) + (float(row[5]) * (1 / 60)) + (float(row[6]) * (1 / 3600))
ra
が赤経、dec
が赤緯です。赤緯は° " 'で表すのに対し、赤経はh m sで表し、1 hは15°なので注意が必要です。
完成
ra
をx座標にdec
をy座標に指定して等級によって径を変えれば完成です。
全てのコード
import pcbnew
import csv
import math
board = pcbnew.GetBoard()
with open('hip_constellation_line_star.csv') as f:
reader = csv.reader(f)
for row in reader:
# 行から必要なデータを抽出
ra = (float(row[1]) * 15) + (float(row[2]) * (15 / 60)) + (float(row[3]) * (15 / 3600))
dec = float(row[4]) + (float(row[5]) * (1 / 60)) + (float(row[6]) * (1 / 3600))
magnutude = float(row[7])
number = row[0]
# 平面座標に変換
x = -ra * 1_000_000
y = -dec * 1_000_000
# 等級を適当な曲線でサイズに変換
size = (2 * math.e ** (-0.2 * magnutude)) * 1_000_000
via = pcbnew.PCB_VIA(board)
via.SetX(int(x))
via.SetY(int(y))
via.SetWidth(int(size))
via.SetDrill(int(size * (1 / 1.5)))
board.Add(via)
text = pcbnew.PCB_TEXT(board)
text.SetX(int(x + (size / 2 + 1)))
text.SetY(int(y))
text.SetHorizJustify(pcbnew.GR_TEXT_H_ALIGN_LEFT)
text.SetLayer(pcbnew.F_Fab)
text.SetText(number)
board.Add(text)
pcbnew.Refresh()
いでよ!
それでは観察していきましょう。
オリオン座
いいですねぇ。若干ゼータ星がずれてますがオリオン座になってます。左上の大きなビアがベテルギウス、右下がリゲルですね。
おおいぬ座
これは完全におおいぬ座ですね。ひときわ大きなシリウスが目立ちます。
こいぬ座
これは...線にしか見えない
冬の大三角形
最後に冬の大三角形です。大電流にも対応できそうです。
おしまい
いかがでしたか?
私はとても癒されました。Python Scriptingは情報が少なく、ここまで難儀する部分もありましたが、今回のビア配置を応用すれば様々な作業をPythonで自動化することができます。
今回のプロジェクトはGithubで公開しています。