まんま!の備忘録

ソフトウェア・ファームウェア・ハードウェア関連の備忘録

KiCADで作成した基板を電磁界シミュレーション(その2:USB2.0)

作成した基板の電磁界シミュレーションするまでをまとめます。Macでの作業です。
openEMSとgerber2EMSを使用します。
前回はこちら。
taogya.hatenablog.com


今回のゴールは以下です。

参考資料

インピーダンス計算は事前にこちらで計算
taogya.hatenablog.com

USB2.0テクニカルマニュアル
https://product.tdk.com/system/files/dam/doc/content/emc-guidebook/ja/jemc_practice_04.pdf

さて、設計した基板が本当に大丈夫かシミュレーションしていきましょう。
対象基板は以下のような形です。赤枠内がUSBラインです。
今回小型基板ですがそのまま実施すると時間かかるので、必要な部分だけ切り出します。
また、部品があるところは配線でショートします。

準備

シミュレーション環境が使えるディレクトリに移動し、ガーバーデータをfabフォルダにコピーします。

$ cd Simulation
$ mkdir fab
$ cp /your_gerber_dir/* fab

シミュレーション実施するために、以下ファイルを作成する必要があります。

  • スタックアップ ファイル
  • ドリルファイル
  • 位置ファイル
  • 構成ファイル
スタックアップ ファイル

PCB スタックアップを説明するファイルです。
各層の定義をjsonファイルに落とし込みます。(2024/03/30時点です)

Key Value
name typeがcopper の場合、「<optional-text>-<name>.gbr 」の nameに当たる部分を指定します。「*_Cu」である必要がある(例えばF_Cu/B_Cu)。それ以外は任意文字列。
type copper, core, prepreg から指定します。
color ソースコード見ると参照していない?とりあえず null で。
thickness この層の厚みを mm で指定します。
material この層の材質を指定するみたいだが、ソースコードでは参照していない?とりあえず FR4 で。
epsilon 誘電率
lossTangent 損失正接

JLCPCBプラグインで出力したガーバーデータのcopper 層のファイル名が 「*-_CuTop.gbr」、「*-_CuBottom.gbr」 となっているので、 「*-F_Cu.gbr」、「*-B_Cu.gbr」に置き換えます。
KiCAD の基板の設定 物理的スタックアップとガーバーデータとgerber2emsのexampleをみながら、 stackup.jsonを作成します。
ついでに、「-EdgeCuts.gbr」のファイル名も「Edge_Cuts.gbr」にする必要あるので直します。

$ for name in fab/*-CuTop.gbr; do mv $name ${name/CuTop/F_Cu}; done && \
for name in fab/*-CuBottom.gbr; do mv $name ${name/CuBottom/B_Cu}; done && \
for name in fab/*-EdgeCuts.gbr; do mv $name ${name/EdgeCuts/Edge_Cuts}; done
$ vi fab/stackup.json
{
    "layers": [
        {
            "name": "F_Cu",
            "type": "copper",
            "color": null,
            "thickness": 0.035,
            "material": null,
            "epsilon": null,
            "lossTangent": null
        },
        {
            "name": "Core",
            "type": "core",
            "color": null,
            "thickness": 1.46,
            "material": "FR4",
            "epsilon": 4.5,
            "lossTangent": 0.02
        },
        {
            "name": "B_Cu",
            "type": "copper",
            "color": null,
            "thickness": 0.035,
            "material": null,
            "epsilon": null,
            "lossTangent": null
        }
    ],
    "format_version": "1.0"
}
ドリルファイル

ガーバーデータに「-PTH.drl」で終わるファイルがあればOKです。

位置ファイル

ポートの位置を記述したCSVファイルです。
ファイル名は「-pos.csv」で終わる必要があります。
copper層を両面で定義しているなら「-top-pos.csv」、「-bottom-pos.csv」で終わるファイルを作成します。

ガーバーデータ見ながら座標を入力していきます。
このcsvで指定する座標は左下が0点で上(y)、右(x)方向がプラスになります。
ガーバーデータは上(y)がマイナスになっているので、逆にします。
また、Rotはポートの入出力端の向きで、
↑:0、→:-90、↓:180、←:90
のようです。

上面

$ vi fab/differential-top-pos.csv
Ref,Val,Package,PosX,PosY,Rot,Side
"SP1","Simulation_Port","Simulation_Port",4.8,9.0,-90,top
"SP2","Simulation_Port","Simulation_Port",21.5,8.05,90,top
"SP3","Simulation_Port","Simulation_Port",4.8,6.9,-90,top
"SP4","Simulation_Port","Simulation_Port",21.5,7.55,90,top

下面

$ vi fab/differential-bottom-pos.csv
Ref,Val,Package,PosX,PosY,Rot,Side

構成ファイル

シミュレーション全体を構成するファイルです。
これは、長いので説明省きます。。すみません。
こちら とexamplesの方を参考に構成してください。
※注意
frequency は in MHz と書いてあるが、Hzの誤記のように思う。
differential_pairs のnameに「.」が含まれているとエラーとなるので「_」などに置き換えておくこと。(USB2_0 のように)
inter_layers は2層だとエラーになる。。2層基板ですがとりあえず4にしてます。
width/lengthは位置ファイルのポートが(PosX,PosY,Rot)=(1, 1, -90)の時、以下のようなイメージで設定します。

meshのサイズはシミュレーション実施始めに 「ems/geometry/F_Cu.png_mesh.png」が生成されるので、その図を見ながら、隣の配線とぶつかっていないか見ながら調整します。だめそうなら、シミュレーション中止して調整します。わからなければ、実施後の結果をみて判断しましょう。
(線太いのでわかりづらいですが。。)


以下、今回の例です。メッシュサイズが小さいと馬鹿みたいに時間かかります。(xy=10にしたら4時間かかった)

$ vi simulation.json
{
    "format_version": "1.1",
    "frequency": {
        "start": 1e8,
        "stop": 3e9
    },
    "max_steps": 8e4,
    "via": {
        "filling_epsilon": 1,
        "plating_thickness": 50
    },
    "mesh": {
        "xy": 50,
        "inter_layers": 4,
        "margin": {
            "xy": 100,
            "z": 100
        }
    },
    "margin": {
        "xy": 500,
        "z": 500
    },
    "ports": [
        {
            "width": 100,
            "length": 400,
            "impedance": 45,
            "layer": 0,
            "plane": 1,
            "excite": true
        },
        {
            "width": 100,
            "length": 400,
            "impedance": 45,
            "layer": 0,
            "plane": 1,
            "excite": false
        },
        {
            "width": 100,
            "length": 400,
            "impedance": 45,
            "layer": 0,
            "plane": 1,
            "excite": true
        },
        {
            "width": 100,
            "length": 400,
            "impedance": 45,
            "layer": 0,
            "plane": 1,
            "excite": false
        }
    ],
    "differential_pairs": [
        {
            "start_p": 0,
            "stop_p": 1,
            "start_n": 2,
            "stop_n": 3,
            "name": "USB2_0"
        }
    ]
}
インピーダンスの確認

では実施します。

$ gerber2ems -a --export-field -d

10分ぐらいかかりました。
だいぶかかりますね。

結果です。ems/results/Z_diff_USB2_0.png に生成されます。

全体的に高いですね。110Ω超えちゃってます。


ついでにParaview(本当はもっとぬるぬる動く)


実測と比較してみないとわかりませんが、以上です。