← 講義ポータルへ戻る

第4章:結線をコードで書き、ネットリストを作り、機械で検算する

この章の学習のねらい
前章の足慣らし(分圧器)と同じ骨格で、今回のボード(第1章で決めた、電源部つきのCH32V003ボード)の結線をコードで書き下します。部品を宣言し、基本形の結線を書き、電源部(VIN_5V)を足し、generate_netlist() でネットリストを作り、ERC() で機械に検算させるところまでを通します。あわせて、この章のいちばん大事な線引き――コードで書くのは「結線」まで。トラック幅・ビア径・ベタGNDといった“物理の数値”は、ここでは決めない(次章のKiCadで決める)――を、はっきりさせます。

4.1 書く順番(分圧器と同じ骨格)

やることは、前章の分圧器と同じ3ステップです。①ネット(網)を用意する → ②部品を用意する → ③つなぐ。ボードが大きくなっても、骨格は変わりません。違うのは、部品と結線の数が増えることだけ。だからこそ、増えたぶんを繰り返し(ループ)で畳めるところが出てきます。まずは、今回のボードの「部品」と「主要なネット」を宣言するところから始めます。

この章の“正本”は、KiCad入門・第3章の早見表

基本形(CH32V003まわり)のピンとネットの正確な対応は、KiCad入門・第3章の全結線の早見表が正本です。この章は、その早見表をコードに“写す”方法を示します。以下のコードで、ピン名やネット名を として書いている箇所は、必ずご自分の早見表(と実際に使うシンボルのピン名)に合わせて置き換えてください。ここで新しい配線を発明するのではなく、手で描いたのと同じ結線を、コードで書き直すのが目的です。

4.2 部品を宣言する

基本形の部品(U1・C1・R1・R2・D1・J1~J3)に、第1章で足した電源部(U2・C2・C3・J4)を加えて宣言します。値とフットプリントは、第1章の部品表に合わせます。ライブラリ名とシンボル名は、KiCad入門で選んだものに合わせてください(とくにCH32V003は、環境によって入っているシンボル名が違うことがあります)。

from skidl import *

# ---- 主要なネット(電気的な網)----
vcc  = Net('VCC')       # 3.3V(基板全体)
gnd  = Net('GND')
vin5 = Net('VIN_5V')    # 今回あらたに増える5V入力

# ---- 基本形の部品(値・フットプリントは第1章の部品表どおり)----
# ※ 'ライブラリ:シンボル' は、KiCad入門で選んだものに合わせる
u1 = Part('MCU_WCH', 'CH32V003F4P6',
          footprint='Package_SO:TSSOP-20_4.4x6.5mm_P0.65mm')   # マイコン
c1 = Part('Device', 'C', value='100nF',
          footprint='Capacitor_SMD:C_0805_2012Metric')          # パスコン
r1 = Part('Device', 'R', value='1k',
          footprint='Resistor_SMD:R_0805_2012Metric')           # LED電流制限
r2 = Part('Device', 'R', value='10k',
          footprint='Resistor_SMD:R_0805_2012Metric')           # SWIOプルアップ
d1 = Part('Device', 'LED',
          footprint='LED_SMD:LED_0805_2012Metric')              # LED
j1 = Part('Connector_Generic', 'Conn_01x12',
          footprint='Connector_PinHeader_2.54mm:PinHeader_1x12_P2.54mm_Vertical')  # 左ヘッダ
j2 = Part('Connector_Generic', 'Conn_01x12',
          footprint='Connector_PinHeader_2.54mm:PinHeader_1x12_P2.54mm_Vertical')  # 右ヘッダ
j3 = Part('Connector_Generic', 'Conn_01x03',
          footprint='Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical')  # 書き込み端子

# ---- 電源部の部品(第1章で追加した4点)----
u2 = Part('Regulator_Linear', 'AMS1117-3.3',
          footprint='Package_TO_SOT_SMD:SOT-223-3_TabPin2')      # 5V→3.3V
c2 = Part('Device', 'C', value='10uF',
          footprint='Capacitor_SMD:C_0805_2012Metric')           # 入力側
c3 = Part('Device', 'C', value='10uF',
          footprint='Capacitor_SMD:C_0805_2012Metric')           # 出力側
j4 = Part('Connector_Generic', 'Conn_01x02',
          footprint='Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical')  # 5V入力
部品を宣言しただけでは、まだ何もつながっていない

上のコードは、部品を「用意した」だけです。分圧器のときと同じで、つないで初めて回路になります。次項から、早見表に沿って結線していきます。値(value)とフットプリント(footprint)は、最終的なネットリストに必要な情報なので、この宣言の時点で入れておきます。

4.3 基本形の結線をコードに写す

まず、基本形の結線です。パスコン、SWIOプルアップ、LED、そして書き込み端子。ここは早見表を1行ずつコードに直していく作業です。ネットにピンを足していく書き方(ネット += 部品[ピン])で書けます。

# ---- パスコン C1:VCC-GND間 ----
vcc += c1[1]
gnd += c1[2]

# ---- 書き込み端子 J3:VDD / GND / SWIO の3本(順番は早見表に合わせる)----
swio = Net('SWIO')
vcc  += j3[1]
gnd  += j3[2]
swio += j3[3]

# ---- SWIO まわり:マイコンのSWIOピン と プルアップR2 ----
# ※ CH32V003のSWIOは PD1。ピン名は使うシンボルに合わせる
swio += u1['PD1'], r2[1]
vcc  += r2[2]

# ---- LED:駆動GPIO(LED_A) → R1 → D1 → GND ----
led_a = Net('LED_A')
led_a += u1['PD6'], r1[1]   # 駆動ピンは早見表に合わせる(例:PD6)
r1[2] += d1['A']            # 抵抗の先にLEDのアノード
d1['K'] += gnd             # LEDのカソードをGND

# ---- 電源をマイコンへ:VDD / VSS(ピン名はシンボルに合わせる)----
vcc += u1['VDD']
gnd += u1['VSS']

ここまでは、分圧器の & より少し丁寧に、「このネットに、この部品のこのピンを足す」と書いています。早見表の1行が、コードの1~数行に、素直に対応します。

繰り返しが効くところ:GPIOをJ1・J2へ引き出す

ここが、コードにして楽になる場面です。マイコンの多数のGPIOを、左右のピンヘッダ(J1・J2)へ順番に引き出す――この同じ形の繰り返しを、手で一本ずつ書く代わりに、早見表の並びをリストにして、ループで回します

# ---- GPIOをJ1へ引き出す:早見表の「J1に出す信号」を順に並べる ----
# ※ ネット名・並び順は、必ず早見表に合わせて置き換える(下は例)
j1_signals = ['PA1', 'PA2', 'PC0', 'PC1', 'PC2', 'PC3', 'PC4', 'PC5']

for i, name in enumerate(j1_signals, start=1):
    net = Net(name)             # そのGPIO用のネットを作り
    net += u1[name], j1[i]      # マイコンの当該ピンと、J1のi番ピンをつなぐ

# J2側も同じ要領で、早見表の「J2に出す信号」をリストにして回す
# j2_signals = [...]  # ← 早見表に合わせる
# for i, name in enumerate(j2_signals, start=1):
#     net = Net(name)
#     net += u1[name], j2[i]
この8行に、コードの効きが凝縮している

もし手で回路図を描くなら、GPIOの数だけ名札を置き、線を引くことになります。コードなら、早見表の並びをリストにして、ループを1つ回すだけ。信号が1本増えても、リストに一語足すだけで済みます。第2章で見た「繰り返しはループで畳める」が、まさにこれです。ただし、どのピンをどこに出すかを“決める”のは、あくまで早見表(=人の設計)。コードは、その決定を手早く・間違いなく写し取る道具です。

4.4 電源部の結線を書く(VIN_5V の追加)

次に、第1章で足した電源部です。第1章1.6の結線表を、そのままコードにします。新しく増えるのは VIN_5V というネットだけ。VCCGND は、基本形と共通の網に合流します。

# ---- 電源部:第1章1.6の結線表をコードに ----
# ※ AMS1117のピン名(VI / VO / GND)は使うシンボルに合わせる
vin5 += j4[1], u2['VI'], c2[1]      # 5V入力側:J4-1, U2-IN, C2-1
vcc  += u2['VO'], c3[1]             # 3.3V出力側:U2-OUT, C3-1(基板VCCへ合流)
gnd  += j4[2], u2['GND'], c2[2], c3[2]   # GND:J4-2, U2-GND, C2-2, C3-2

これで、基本形の全結線に、電源部の3行が足されました。vccgnd は、4.3ですでに基本形の各所につながっているので、ここで u2['VO'] を足せば、レギュレータの3.3V出力が、そのまま基板全体のVCCに合流します。同じネット名に足していくだけで、網が広がっていく――これがネットで結線するということです。

第1章の注意を、コードでも忘れずに:電源の供給元は一つに
第1章で触れたとおり、3.3Vの供給元が「書き込み器の3V3(J3経由)」と「レギュレータ出力(U2)」の2つになりえます。コード上は vcc という一つの網にどちらもつながって見えますが、実際の基板では、両方から同時に電気を流さない設計(ジャンパで切り替える等)にします。これは結線(論理)というより運用と物理の判断なので、次章以降の配置・配線で具体化します。コードは「つながっている」ことを表すだけで、「どちらから給電するか」までは決めません。

4.5 ここが肝:コードで書くのは「結線」まで。太さ・ビア・ベタGNDは書かない

この章で、いちばん誤解されやすい線引きをはっきりさせます。skidl(コード)で書けるのは、「どことどこがつながるか」という論理までです。「その線を何ミリの太さで引くか」「ビアの穴径はいくつか」「空き地をどうGND銅箔で埋めるか」――こうした物理の数値は、skidlのネットリストには入りません。入る場所がないのです。

つまずきの正体:太さやベタGNDを、コードに求めてしまう
ここは、実際に多くの人が一度はまるところです。「配線を自動化するのだから、線の太さやGNDベタも、コード側で指定できるはず」と考えてしまう。ところが、トラック幅・クリアランス・ビア径・ベタGND(ゾーン塗りつぶし)は、ネットリストが扱う情報ではありません。これらは基板(物理)の設定であり、KiCadのボード設定側で決めるものです(KiCad入門でいえば、第3章のネットクラス設定と、第6章のベタGNDにあたります)。コードでいくら探しても見つからないのは、そもそもコードの担当ではないから。そう考えると、どちらが何を担当するのかが、はっきりします。

では、コード側では何もできないのかというと、そうではありません。「このネットは電源系だ」という“意図”のラベル(ネットのクラス分け)までは、コードで持てます。たとえば VCCGND を「電源クラス」としてまとめておく、という具合です。ただし、そのクラスに“幅0.5mm”という数値を結びつけて実際の配線に効かせるのは、KiCadのボード設定の仕事です。コードは「これは電源だ」と意図を示すところまで、KiCadは「電源は0.5mmで引く」と物理を決めるところ――と分かれます。

# ネットに「意図」を持たせる(例):電源系をまとめて扱う下地
# ── ただし、ここで幅やビア径の“数値”は決めない ──
#    実際のトラック幅・クリアランス・ビア径・ベタGNDは、
#    次章でKiCadのボード設定として決める(=物理は人の担当)。
power_nets = [vcc, gnd, vin5]   # 電源系はこの3本、という整理まではコードで持てる
この線引きが、このコース全体の背骨

序章の図(論理はコード/物理は人と機械/検算は機械)を思い出してください。4.5は、その背骨がいちばんはっきり出る場面です。コードは論理の担当、KiCadは物理の担当。この境目を、太さ・ビア・ベタGNDという具体でつかんでおくと、次章でKiCadに取り込んだあと、「どこで何を設定するのか」で迷わなくなります。“コードで全部やる”のではなく、“コードに向くところをコードに渡す”――ここが要です。

4.6 ネットリストを作り、機械で検算する

結線を書き終えたら、分圧器のときと同じく、検算とネットリスト出力です。ERC() で電気的なミス(つなぎ忘れ、電源の衝突など)を機械に洗わせ、generate_netlist() でネットリストを出力します。

# ---- 検算とネットリスト出力 ----
ERC()                 # つなぎ忘れ・電源衝突などを機械が点検
generate_netlist()    # KiCadへ渡すネットリストを出力
やること
  1. python このスクリプト.py を実行する。
  2. ERCの警告を読む。 つなぎ忘れや、電源ピンの扱いに関する警告が出たら、早見表と照らして直す。
  3. 出力された .net ファイルを開き、VCCGNDVIN_5V に、意図した部品のピンがぶら下がっているかを目で確かめる。
電源まわりのERC警告と PWR_FLAG

電源ネット(VCC・GNDなど)に対して、ERCが「このネットは、どこから電気が供給されるのか宣言されていない」という趣旨の警告を出すことがあります。KiCad入門・第3章で PWR_FLAG を置いたのと同じ事情です。skidl側でも、電源フラグにあたる部品をVCC・GNDに付けて「ここが電源の供給点だ」と宣言すると、この警告は収まります。付け方はskidlの版で少し変わるので、警告文とあわせて公式の案内を確認してください。大事なのは、警告を放置せず、意味を読んで一つずつ潰すことです。

4.7 次章への橋渡し

この章のゴール
  • 今回のボードの部品(基本形+電源部)を、値・フットプリント付きで宣言した
  • 基本形の結線を早見表から写し、GPIOのJ1/J2引き出しはループで畳んだ
  • 電源部の結線(新規 VIN_5VVCC/GNDへの合流)を書いた
  • 太さ・ビア・ベタGNDはコードに書かない(=物理はKiCadの担当)と線引きした
  • ERC() で検算し、generate_netlist() でネットリストを出力・目視した

これで、今回のボードの「論理(結線)」がコードとネットリストの形で手に入りました。ここまでが「コードの担当」です。次章からは「物理の担当」――このネットリストをKiCadに取り込み、部品を並べ、そして4.5で保留したトラック幅・ビア・ベタGNDを、KiCadのボード設定として自分で決めます。前回のプロジェクトで飛ばしてしまった一手を、今度は正面から押さえにいきます。