2025年8月21日木曜日

NFCアンテナ(8)というかOpenEMS

OpenEMSでメタルを完全導体から銅に変更して、シミュレーションと実測の結果を比較していく。


OpenEMSのLegacy WikiのOnline ManualのPropertiesのMetalによると、AddMetalに代えてAddConductingSheetとすることで、電気伝導率を設定したメタルにすることができるらしい。しかも、メタル厚さはここで指定するので、形状データに厚さを入れ込む必要はなさそう。
んで、
gen_small_loop_coil.mのなかの
CSX=AddMetal(CSX,metal_name);

#CSX=AddMetal(CSX,metal_name);
CSX=AddConductingSheet(CSX,metal_name,58e6,40e-6);
ってする。
んで、また約7時間かけて実行する。
コイル間距離=96mmで同調をとった後、コイル間距離=20mmで実測と比較
まぁまぁ合ってると言っていいんじゃないかなー
で、もちっと詳細にコイルの等価回路を出していこうと思う。シミュレーションデータはたぶん特に解析周波数の端付近が精度が悪かったりおかしな結果になってたりするっぽいので、波形を理解して定数を推定できない(と思う)。んで、力任せにカーブフィットで定数を推定していく。解析の中心周波数付近で、インピーダンスについて等価回路の計算結果とOpenEMSの結果が一致するようにする。
こんなコードで
coil_param_fit.py
  1. import numpy as np
  2. import skrf as rf
  3. import matplotlib.pyplot as plt
  4. import scipy
  5.  
  6. def Calc_Network(L,Rs,Cp,Cpadd,Rp,gnd,port1):
  7.     cnx=[
  8.         [(port1,0),(L,0),(Cp,0),(Cpadd,0),(Rp,0)],
  9.         [(L,1),(Rs,0)],
  10.         [(Rs,1),(Cp,1),(Cpadd,1),(Rp,1),(gnd,0)]
  11.     ]
  12.     cir=rf.Circuit(cnx)
  13.     ntw=cir.network
  14.     return ntw
  15.  
  16. FILE1=rf.Network('../out_cu_96.s2p')
  17. FILE1.name='FILE1'
  18. f_start=FILE1.frequency.start
  19. f_stop=FILE1.frequency.stop
  20. nop=FILE1.frequency.npoints
  21. freq=FILE1.frequency
  22.  
  23. tl_media = rf.DefinedGammaZ0(freq, z0=50)
  24. gnd = rf.Circuit.Ground(freq, name='gnd')
  25. port1 = rf.Circuit.Port(freq, name='port1', z0=50)
  26.  
  27. f_range_lower=12e6
  28. f_range_upper=15e6
  29.  
  30. L_def=1540e-9
  31. Rs_def=0.5
  32. Cp_def=0.66e-12
  33. Rp_def=75000
  34. Cpadd_def=89e-12
  35.  
  36. tl_media_file= rf.DefinedGammaZ0(freq, z0=50)
  37. gnd_file = rf.Circuit.Ground(freq, name='gnd_file')
  38. port1_file = rf.Circuit.Port(freq, name='port1_file', z0=50)
  39. Cpadd_file=tl_media.capacitor(Cpadd_def, name='Cpadd')
  40. cnx_file=[
  41.     [(port1_file,0),(FILE1,0),(Cpadd_file,0)],
  42.     [(gnd_file,0),(Cpadd_file,1)]
  43. ]
  44. cir_file=rf.Circuit(cnx_file)
  45. ntw_file=cir_file.network
  46.  
  47. x0=(L_def,Rs_def,Cp_def,Rp_def)
  48.  
  49. def generate_network(L_val,Rs_val,Cp_val,Rp_val):
  50.     L=tl_media.inductor(L_val,name='L')
  51.     Rs=tl_media.resistor(Rs_val,name='Rs')
  52.     Cp=tl_media.capacitor(Cp_val, name='Cp')
  53.     Rp=tl_media.resistor(Rp_val,name='Rp')
  54.     Cpadd=tl_media.capacitor(Cpadd_def, name='Cpadd')
  55.     ntw=Calc_Network(L,Rs,Cp,Cpadd,Rp,gnd,port1)
  56.     return ntw
  57.  
  58. def get_err(x):
  59.     ntw=generate_network(*x)
  60.     irange=np.where((ntw.f>=f_range_lower)&(ntw.f<=f_range_upper))
  61.     calc_z_re=ntw.z_re[irange,0,0][0]
  62.     file_z_re=ntw_file.z_re[irange,0,0][0]
  63.     calc_z_im=ntw.z_im[irange,0,0][0]
  64.     file_z_im=ntw_file.z_im[irange,0,0][0]
  65.     err_re=np.sum((file_z_re-calc_z_re) ** 2)
  66.     err_im=np.sum((file_z_im-calc_z_im) ** 2)
  67.     print(err_re+err_im)
  68.     return err_re+err_im
  69.  
  70. res=scipy.optimize.fmin(get_err,x0)
  71. print(res)
  72.  
  73. ntw=generate_network(*res)
  74. irange=np.where((ntw.f>=f_range_lower)&(ntw.f<=f_range_upper))
  75. fig=plt.figure()
  76.  
  77. ax1=fig.add_subplot(2,1,1)
  78. ax1.plot(ntw.f[irange],ntw.z_re[irange,0,0][0])
  79. ax1.plot(ntw_file.f[irange],ntw_file.z_re[irange,0,0][0])
  80.  
  81. ax2=fig.add_subplot(2,1,2)
  82. ax2.plot(ntw.f[irange],ntw.z_im[irange,0,0][0])
  83. ax2.plot(ntw_file.f[irange],ntw_file.z_im[irange,0,0][0])
  84.  
  85. fig.tight_layout()
  86. plt.show()
ついでに、手作りコイルも実測データからこのコードで等価回路定数を推定してしまう。
そすっと
OpenEMS 手作りコイル
TX RX TX RX
L[nH] 1506.69974 644.510935 1535.74693 677.826358
Rs[ohm] 0.692581008 0.683139303 3.82118882 1.63220125
Cp[pF] 2.64885043 1.61053898 13.6028450 11.4099153
Rp[ohm] 3239658.97 4262222.68 22713.4181 3201.28163
(Cpadd)[pF] 89 213 76 191
ってことで、インダクタンス値についてはOpenEMSと手作りコイルでまぁまぁいいレベルで一致しているみたい。Cはまぁどうでもいいとして(手作りコイルは測定のためにツイストで引き出していてそれゆえ容量多くなっているから)、Rはやっぱりあわんのやねーしゃーない。ちなみに、推定した等価回路とOpenEMSやら手作りコイルの実測やらと比較すると、ほんと見た目では差がないくらい一致していた。scipy.optimizeえらい!
で、この定数を使った等価回路と、OpenEMSまたは手作り実測とを比較することで結合係数を推定してみる。
まぁ、こんな感じで、
コイルの結合係数kを調整していく。
これもscikit-rfとscipy.optimizeでやるって手もあるんだけど、1パラメータなので、手でいいかなーって;
コイル間距離[mm] OpenEMS 手作りコイル
2 0.1616 0.1627
4 0.1448 0.1455
12 0.0775 0.0759
20 0.0403 0.0411
なんともOpenEMSと実測はほぼ一致している!やるなーOpenEMS!日曜技術者の器用さもハンパねーって自画自賛(≧▽≦)
賑やかしのため、等価回路と実測を比較したものも載せておく
んで、これでどうしようかって言うと、、、とにかく通信距離を伸ばす方法を考えたいんだけど、まだまだ調査が必要な予感;

0 件のコメント:

コメントを投稿