2020年12月22日 星期二

在HFSS當中取得某一物件顏色並將其顏色設定到另一物件

利用程式取得圓柱體的顏色碼將其轉換成RGB之後設定到方塊物件上。

(圖一) 欲取得圓柱的顏色並設定到方塊上


import ScriptEnv
ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
oDesktop.RestoreWindow()
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.SetActiveEditor("3D Modeler")

code = oEditor.GetPropertyValue('Geometry3DAttributeTab', "Cylinder1", 'Color')

AddWarningMessage(str(code))

code = int(code)
R= code % 256
G = ((code - R) % (256**2)) / 256
B = (code - R - 256*G) / 256**2

oEditor.ChangeProperty(
[
"NAME:AllTabs",
[
"NAME:Geometry3DAttributeTab",
[
"NAME:PropServers",
'Box1'
],
[
"NAME:ChangedProps",
[
"NAME:Color",
"R:=" , R,
"G:=" , G,
"B:=" , B
]
]
]
])
(圖二)執行腳本之後


2020年12月18日 星期五

在3D Layout當中如何取得元件的座標

元件的尺寸大小不一,嚴格來說,更有用的是取得元件所有的pin及pin所在的位置,下面的程式碼可以取得上層電阻的pin及其座標以及pin連接的net name

import ScriptEnv
ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
oDesktop.RestoreWindow()
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.GetActiveEditor()
R_top = []
R_bot = []
for i in oEditor.FindObjects('Type', 'component'):
part_type = oEditor.GetPropertyValue('BaseElementTab', i, 'Part Type')
placement_layer = oEditor.GetPropertyValue('BaseElementTab', i, 'PlacementLayer')
if part_type == 'Resistor':
if placement_layer == 'TOP':
R_top.append(i)

for i in R_top:
for pin in oEditor.GetComponentPins(i):
AddWarningMessage(str(oEditor.GetComponentPinInfo(i, pin)))
(圖一) 輸出Top R對應pin的座標及net name


在3D layout當中如何取得上層或底層的電阻編號?

 要在HFSS 3D Layout運行script來取得PCB上面的電阻/電容/電感編號,可以參考以下代碼:


import ScriptEnv
ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
oDesktop.RestoreWindow()
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.GetActiveEditor()
R_top = []
R_bot = []
for i in oEditor.FindObjects('Type', 'component'):
part_type = oEditor.GetPropertyValue('BaseElementTab', i, 'Part Type')
placement_layer = oEditor.GetPropertyValue('BaseElementTab', i, 'PlacementLayer')
if part_type == 'Resistor':
if placement_layer == 'TOP':
R_top.append(i)
elif placement_layer == 'BOTTOM':
R_bot.append(i)

AddWarningMessage(str(R_top))
AddWarningMessage(str(R_bot))
(圖一) TOP層以以及BOTTOM層的電阻



2020年12月15日 星期二

如何在AEDT當中產生訊息視窗

 我們可以在程式執行完畢之後產生訊息窗告知使用者處理狀況:

import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox

MessageBox.Show("Process Successfully!", 'Message Window')

(圖一) 跳出訊息視窗


2020年12月5日 星期六

如何依照元件連接數排序輸出nets

不同類別的net連接不同數量的原件(IC, R, L, C,...)。訊號線一般是2個,Clock則是兩個到多個,電源net連接的元件數可能多達數十個。GND通常是連接最多元件的net,包含晶片,去耦電容及其他等等。透過讀取這些訊息,可以讓我們對PCB的複雜度有一個初步的了解。以下為程式碼:

import clr, os, sys, System
AnsysEM_Path = 'C:/Program Files/AnsysEM/AnsysEM20.2/Win64/'
sys.path.append(AnsysEM_Path)
os.environ['PATH'] += ';' + AnsysEM_Path

clr.AddReference('Ansys.Ansoft.Edb')
clr.AddReference('Ansys.Ansoft.SimSetupData')
import Ansys.Ansoft.Edb as edb

edb.Database.SetRunAsStandAlone(True)

DB = edb.Database.Open('D:/demo/test.aedb', False)

cell = list(DB.TopCircuitCells)
layout = cell[0].GetLayout()

def getNetInfo(layout):
net_info={}
for n in layout.Nets:
netname=n.GetName()
net_info[netname]={}
for i in n.PadstackInstances:
if len(i.GetName())==0:
continue
try:
net_info[netname][i.GetComponent().GetName()]+=[i.GetName()]
except:
net_info[netname][i.GetComponent().GetName()]=[i.GetName()]

return net_info

netinfo = getNetInfo(layout)
result = []
for i in netinfo:

comps = netinfo[i].keys()
Ucomps = [j for j in comps if j[0] in ['u', 'U']]
NUcomps = [j for j in comps if j[0] not in ['u', 'U']]
sortedcomp = sorted(Ucomps) + sorted(NUcomps)
result.append((len(netinfo[i]), sortedcomp, i))

result.sort()
with open('d:/demo/netinfo.csv', 'w') as f:
for n, comps, net in result:
print(n, comps, net)
f.writelines('{:>4}, {:>32}, {}\n'.format(n, net, comps))

(圖一) 輸出按照連接元件數量排序的net name


2020年12月1日 星期二

如何在Anaconda安裝skrf模組

Scikit-RF提供了S參數讀取,S參數運算及Smith Chart繪圖等功能。我們可以在Anaconda當中安裝該套件來處理S參數的相關運算。套件功能可參考:https://scikit-rf.readthedocs.io/en/latest/index.html 

底下為安裝步驟:

步驟一:開啟Anaconda Prompt視窗

(圖一) 開啟開啟Anaconda Prompt視窗

步驟二:輸入conda install -c conda-forge  scikit-rf。此時Anaconda會檢查環境。

(圖二) 輸入安裝指令

步驟三:完成環境檢查之後,詢問是否安裝,按Y鍵確認。之後會自動聯網下載相關套件並啟動安裝過程,約1-2分鐘可完成。

(圖三) 安裝過程

步驟四:安裝完成之後會出現done的訊息,此時可關閉視窗完成安裝。

(圖四) 結束套件安裝


最後,回到Anaconda之後我們就可以匯入skrf模組來處理S參數了。

(圖五)匯入skrf模組






2020年11月29日 星期日

3D Layout當中該如何找出Overlap物件?

(圖一) 部分紅色圓形與藍色方塊重疊


藍色方塊在Top層,紅色圓形在Bottom層。假設想要找出所有與藍色方塊重疊的紅色圓形並加以刪除,可參考底下程式碼:

import ScriptEnv
ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
oDesktop.RestoreWindow()
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.GetActiveEditor()

x1 = set(oEditor.FindObjects('Type', 'rect'))
y1 = set(oEditor.FindObjects('Layer', 'Top'))
z1 = x1.intersection(y1)

x2 = set(oEditor.FindObjects('Type', 'circle'))
y2 = set(oEditor.FindObjects('Layer', 'Bottom'))
z2 = x2.intersection(y2)

todelete = []
for i in z1:
poly_i = oEditor.GetPolygon(i)
for j in z2:
poly_j = oEditor.GetPolygon(j)
if poly_i.GetIntersectionType(poly_j):
todelete.append(j)

oEditor.Delete(todelete)


(圖二)執行程式之後,重疊紅色圓形已被刪除




2020年11月27日 星期五

透過EDB抓取疊層相關資料

以下代碼可以透過EDB抓取堆疊當中像是厚度,顏色,材料,粗糙度等訊息。注意當中Solver設定只支援HFSS,不支援Planar EM。

import clr, os, sys, System, json
AnsysEM_Path = 'C:/Program Files/AnsysEM/AnsysEM20.2/Win64/'
sys.path.append(AnsysEM_Path)
os.environ['PATH'] += ';' + AnsysEM_Path

clr.AddReference('Ansys.Ansoft.Edb')
clr.AddReference('Ansys.Ansoft.SimSetupData')
import Ansys.Ansoft.Edb as edb

edb.Database.SetRunAsStandAlone(True)

DB = edb.Database.Open('D:/demo/test.aedb', False)

cell = list(DB.TopCircuitCells)
layout = cell[0].GetLayout()

x = layout.GetLayerCollection()
zids =x.GetZoneIds()
print(zids)
y=[]
y = x.Layers([-2, 20])

layer_type ={'SignalLayer': "signal",
'DielectricLayer': "dielectric",
'MeasureLayer': "measures",
'OutlineLayer': "outline",
'SIwaveHFSSSolverRegions': "SIwave HFSS regions",
'AirlinesLayer': "rat",
'ErrorsLayer': "error",
'SymbolLayer': "symbol",
'PostprocessingLayer': "Postprocessing",
'AssemblyLayer': "assembly",
'SilkscreenLayer': "silkscreen",
'SolderPasteLayer': "solderpaste",
'GlueLayer': "glue",
'UserLayer': "user",
}
tb_type = {0: 'top', 1: 'neither', 2:'bottom'}
result = []
for i in y:
ltype = layer_type[str(i.GetLayerType())]
if ltype in ['signal', 'dielectric']:
info = ["NAME:stackup layer"]
else:
info = ["NAME:layer"]
info += ["Name:=", i.GetName()]
info += ["ID:=", i.GetLayerId()]

info += ["Type:=", ltype]
info += ["Top Bottom:=", tb_type[int(i.GetTopBottomAssociation())]]
R, G, B = i.GetColor()
colorcode = int(R) + int(G)*(256) + int(B)*(256**2)
info += ["Color:=", colorcode]
info += ["Transparency:=", i.GetTransparency()]
info += ["Pattern:=", 1]
info += ["VisFlag:=", int(i.GetVisibilityMask())]
info += ["Locked:=", i.GetLocked()]
info += ["DrawOverride:=", int(i.GetDrawOverride())]
inzone =[id for id in zids if i.IsInZone(id)]
info += ["Zones:=", inzone]

if ltype in ['signal', 'dielectric']:
values = ["NAME:Sublayer",]
values += ["Thickness:=", str(i.GetThicknessValue())]
values += ["LowerElevation:=", str(i.GetLowerElevationValue())]
values += ["Roughness:=", "0um"]
values += ["BotRoughness:=", "0um"]
values += ["SideRoughness:=", "0um"]
values += ["Material:=", i.GetMaterial()]
if ltype == 'signal':
values += ["FillMaterial:=", i.GetFillMaterial()]
info.append(values)

if i.GetNegative():
info += ["Neg:=", True]

if i.GetUseSolverProperties():
info += ["Usp:=", True]
solver = i.GetHFSSSolverProperties()
solveinside = 'true' if solver.SolveInside else 'false'
dc_type = int(solver.DCType)
dc_thickness = str(solver.DCThickness)
s1 = [
"NAME:Sp",
"Sn:=" , "HFSS",
"Sv:=" , "so(si={}, dt={}, dtv=\'{}\')".format(solveinside, dc_type, dc_thickness)
]
s2= [
"NAME:Sp",
"Sn:=" , "PlanarEM",
"Sv:=" , "so(ifg=false, vly=false)"
]
info.append(s1)
info.append(s2)
if i.IsEtchFactorEnabled():
info += ["Etch:=", str(i.GetEtchFactor())]
info += ["UseEtch:=", True]

if i.IsRoughnessEnabled():
info += ["UseR:=", str(i.IsRoughnessEnabled())]
location = [(edb.Cell.RoughnessModel.Region.Top, "RMdl:=", "NR:=", "HRatio:=", 6),
(edb.Cell.RoughnessModel.Region.Bottom, "BRMdl:=", "BNR:=", "BHRatio:=", 8),
(edb.Cell.RoughnessModel.Region.Side, "SRMdl:=", "SNR:=", "SHRatio:=", 10),
]
for loc, loc_name, nodule_radius, surface_ratio, rough_index in location:
model = i.GetRoughnessModel(loc)

if type(model).__name__ == 'HurrayRoughnessModel':
info += [loc_name, "Huray"]
info += [nodule_radius, str(model.NoduleRadius)]
info += [surface_ratio, str(model.SurfaceRatio)]
else:
info += [loc_name, "Groisse"]
info += [nodule_radius, "0um"]
info += [surface_ratio, "1"]
values[rough_index] = str(model.Roughness)

result.append(info)

with open('d:/demo/testing.txt', 'w') as f:
for i in result:
f.writelines( str(i) + '\n')
print(str(i))
(圖一)在PyCharm抓取疊層相關訊息




2020年11月23日 星期一

AEDT當中如何產生表格視窗

 以下是一個簡單的程式碼產生表格視窗,各位可以在3D Layout的Toolkits/Reports底下找到許多用表格視窗顯示結果的toolkit:

import sys
from System.IO import Path

sys.path.append(Path.Combine(oDesktop.GetSysLibDirectory(), r'Toolkits', r'Lib'))
from TableViewForm import TableViewForm

Table = []
for i in range(100):
Table.append([str(i).zfill(3), str(i), str(i**2)])

tvf = TableViewForm(['ID', 'N', 'N*N'], Table)
tvf.Text = 'Net List Report'
tvf.Show()

(圖一)AEDT表格視窗

(圖二)3D Layout支援表格視窗的toolkits


在AEDT訊息視窗顯示進度條

進度條可以讓使用者可以更容易的知道目前工作的進度。以下程式碼為一個簡單的範例:

oDesktop.ClearMessages('', '', 2)
import time
import threading

t0 = time.time()

def func(x, result):
data = []

for j in range(x, x + 1000):
data.append(j)
x = sum(data)
result.append(str(x))

def progressbar(x):
if 0 <= x <= 100:
i = x // 2
j = x % 2
if j == 0:
AddWarningMessage(u"\u2588" * (i) + u"\u2581" * (50 - i) + '[{:4}%]'.format(x))
else:
AddWarningMessage(u"\u2588" * (i) + u"\u2585" + u"\u2581" * (49 - i) + '[{:4}%]'.format(x))
else:
pass

result = []
threads = []
for i in range(101):
t = threading.Thread(target=func, args=(i, result))
t.start()
threads.append(t)
progressbar(i)

for i in threads:
t.join()

AddWarningMessage(str(result))
AddWarningMessage(str(time.time() - t0) + '(secs)')
(圖一)進度條範例


2020年11月22日 星期日

如何在AEDT訊息視窗顯示正確的計算進度

在AEDT編寫自動化程式,我們會習慣在程式碼當中利用AddWarningMessage()來顯示進度。一開始的進度顯示正常,但是到後段顯示會中斷,直到完成計算訊息視窗才會一口氣將後段的所有訊息一次列出來。這就失去了進度顯示的意義。比方說下面一段程式碼到了60%,訊息視窗就停止更新,等到全部計算完畢才一次將70%-100%訊息列印出來:

oDesktop.ClearMessages('', '', 2)
import time

t0 = time.time()
result = []
for i in range(10):
data = []

for j in range(i, i + 1000000):
data.append(j)
x = sum(data)
AddWarningMessage('{}\n'.format(x))
AddWarningMessage('{}%\n'.format((i + 1) * 10))
result.append(str(x))

AddWarningMessage(str(result))
AddWarningMessage(str(time.time() - t0) + '(secs)')

我們可以透過Threading的方式解決這個問題,訊息視窗會按照正常的進度輸出訊息:

oDesktop.ClearMessages('', '', 2)
import time
import threading

t0 = time.time()

def func(x, result):
data = []

for j in range(x, x + 1000000):
data.append(j)
x = sum(data)
AddWarningMessage('{}\n'.format(x))
result.append(str(x))

result = []
for i in range(10):
t = threading.Thread(target=func, args=(i, result))
t.start()
t.join()
AddWarningMessage('{}%\n'.format((i + 1) * 10))

AddWarningMessage(str(result))
AddWarningMessage(str(time.time() - t0) + '(secs)')
(圖一) 顯示計算進度


2020年11月15日 星期日

如何取得Q3D的net及其類別和net上面的物件名

編寫Q3D自動化程式需要取得設計當中的net name及類別(signal, ground, floating)。也必須知道物件所對應的net名稱。底下程式碼可以取得以上所提到的資訊:

oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.SetActiveEditor('3D Modeler')
oModule = oDesign.GetModule('BoundarySetup')
x = oModule.GetExcitations()
info = zip(x[0::2], x[1::2])
AddWarningMessage(str(info))

signal_nets = [i for i, j in info if j=='SignalNet']

result = {}
for s in signal_nets:
result[s] = []
for i in oModule.GetExcitationAssignment(s):
objname = oEditor.GetObjectNameByID(int(i))
result[s].append(objname)

AddWarningMessage(str(result))
(圖一)輸出net名稱及其類型,輸出net所包括的物件名




如何在ACT當中將設計名稱加到下拉選單當中

當我們在App Builder建立了選單之後,可以輸出.xml及.py檔。在.xml當中<step>層級底下加入<onrefresh></onrefresh>標籤,並在當中呼叫RefreshChoice函數。

combobox.xml的內容

<!-- autogenerated by XmlWriter ( 15/11/2020 05:32:32 ) -->
<extension name="combobox">
<imagedirectory>.</imagedirectory>
<guid>b39d25c3-456b-47db-93fa-31e4f172e169</guid>
<script src="IDEGeneratedMain.py" />
<wizard name="cb" caption="cb" version="1" context="ElectronicsDesktop">
<step name="Step_1" version="0" caption="Step_1">
<property control="select" name="design" caption="design" persistent="False" parameterizable="False">
<attributes options="Refresh" />
</property>

<callbacks>
<onrefresh>RefreshChoice</onrefresh>
</callbacks>
</step>
</wizard>
</extension>
在.py檔當中,定義RefreshChoice函數,當中讀取專案底下所有的設計並加到下拉選單當中。
IDEGeneratedMain.py的內容
def onupdateStep(step):
pass

def RefreshChoice(step):
Designs_Field = step.Properties["design"]
Designs_Field.Options.Clear()

ActiveProject = oDesktop.GetActiveProject()
DesignList = ActiveProject.GetTopDesignList()
if len(DesignList) != 0:
ActiveDesign = ActiveProject.GetActiveDesign()

for design in DesignList:
Designs_Field.Options.Add(design)

當啟動ACT之後,點一下下拉選單的Refresh選項之後,下拉選單便會更新加入所有的設計名稱。
(圖一)下拉選單在Refresh之後會加入所有設計的名稱


2020年11月6日 星期五

如何取得3D Layout的database?

在開發3D Layout的自動化程式,某些時候我們需要取得Layout的一些訊息,偏偏函式庫不提供對應的函數,這時候就只能透過EDB的函式庫來抓取。但是如何才能從AEDT函式連結到專案對應到的EDB呢?這時候就可以透過下面指令來達成:

DB = edb.Database.Attach(int(oProject.GetEDBHandle()))

當中GetEDBHandle()可以取得現在開啟當中的Project對應到的資料庫編號,此時用edb.Database.Attach()輸入編號便可以返回資料庫物件做資料的抓取了。以下範例便是透過EDB抓到3D Layout所有的net及net連接的元件及pin,並將其輸出到AEDT的訊息視窗。
import clr

clr.AddReference('Ansys.Ansoft.Edb')
clr.AddReference('Ansys.Ansoft.SimSetupData')
import Ansys.Ansoft.Edb as edb

import ScriptEnv

ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
oDesktop.RestoreWindow()
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.GetActiveEditor()

def getNetInfo():
DB = edb.Database.Attach(int(oProject.GetEDBHandle()))
cells = list(DB.TopCircuitCells)

for i in cells:
if i.GetName() == (oDesign.GetName() if ';' not in oDesign.GetName() else oDesign.GetName().split(';')[1]):
layout = i.GetLayout()
break

net_info = {}
for n in layout.Nets:
netname = n.GetName()
net_info[netname] = {}
for i in n.PadstackInstances:
if len(i.GetName()) == 0:
continue
try:
net_info[netname][i.GetComponent().GetName()] += [i.GetName()]
except:
net_info[netname][i.GetComponent().GetName()] = [i.GetName()]

return net_info

AddWarningMessage(str(getNetInfo())) 


(圖一) 輸出net, net連接到的元件及pin


2020年11月2日 星期一

如何利用EDB庫取得PCB上Via及Pin的相關訊息

這些訊息包含via/pin的名稱、歸屬的net-name、padstack的類型,位置XY座標及旋轉角度。

import clr, os, sys, System, json
AnsysEM_Path = 'C:/Program Files/AnsysEM/AnsysEM20.2/Win64/'
sys.path.append(AnsysEM_Path)
os.environ['PATH'] += ';' + AnsysEM_Path

clr.AddReference('Ansys.Ansoft.Edb')
clr.AddReference('Ansys.Ansoft.SimSetupData')
import Ansys.Ansoft.Edb as edb

edb.Database.SetRunAsStandAlone(True)

DB = edb.Database.Open('D:/demo/test.aedb', False)

cell = list(DB.TopCircuitCells)
layout = cell[0].GetLayout()
data = []

for i in layout.PadstackInstances:
pad_name = i.GetName()
cmp_name = i.GetComponent().GetName()
net_name = i.GetNet().GetName()
padstacktype = i.GetPadstackDef().GetName()
_, location, angle = i.GetPositionAndRotationValue()

if cmp_name:
pad_name = cmp_name + '-' + pad_name

data.append((pad_name, net_name, padstacktype, str(location), str(angle)))
with open('d:/demo/pcb.log', 'w') as f:
json.dump(data, f, indent=4)

(圖一) 輸出的pin及via相關訊息


 

2020年10月31日 星期六

如何用EDB函式庫輸出path跟polygon的座標點

在3D Layout當中的電路板設計。

(圖一) HFSS 3D Layout

以下程式碼讀取.aedb並輸出trace, polygon的座標訊息,並輸出到json檔案當中

import clr, os, sys, System, json
AnsysEM_Path = 'C:/Program Files/AnsysEM/AnsysEM20.2/Win64/'
sys.path.append(AnsysEM_Path)
os.environ['PATH'] += ';' + AnsysEM_Path

clr.AddReference('Ansys.Ansoft.Edb')
clr.AddReference('Ansys.Ansoft.SimSetupData')
import Ansys.Ansoft.Edb as edb

edb.Database.SetRunAsStandAlone(True)

DB = edb.Database.Open('D:/demo/test.aedb', False)

cell = list(DB.TopCircuitCells)
layout = cell[0].GetLayout()
data = {}
type_group = set()
for i in layout.Primitives:
name = i.GetId()
net = i.GetNet().GetName()
layer = i.GetLayer().GetName()
ptype = i.GetPrimitiveType()
key = ','.join([str(net), str(name), str(layer), str(ptype)])
type_group.add(str(ptype))

data[key]=[]
for p in i.GetPolygonData().Points:
_x = p.X.ToDouble()
_y = p.Y.ToDouble()
if _x == sys.float_info.max or _y == sys.float_info.max:
continue
data[key].append((_x, _y))
sk = sorted(data.keys())
newdata = {str(i):data[i] for i in sk}

print(type_group)
with open('d:/demo/pcb.log', 'w') as f:
json.dump(newdata, f, indent=4)

為了要確保抓到的資料是否完整,我們接著到Anaconda Spyder環境當中讀取.json檔的內容並根據座標輸出圖片。注意輸出結果並不包含pads及via的相關結構。

import json
import matplotlib.pyplot as plt
plt.figure(figsize=(30, 20))
with open('d:/demo/pcb.log', 'r') as f:
data = json.load(f)

for i in data:
net, gid, layer, ptype = i.split(',')
if layer == 'PWR':
x, y = zip(*data[i])
plt.fill(list(x)+[x[0]], list(y)+[y[0]], color='r')

plt.savefig('d:/demo/top.png')
plt.show()
(圖二)用Matplotlib繪圖


2020年10月30日 星期五

如何利用EDB函式輸出3D Layout當中元件SolderBall的訊息

在不打開AEDT的狀況之下,我們可以透過直接讀取3D Layout的.aedb方式取得版圖相關訊息。這裡示範如何取得某一個IC元件的Solder Ball的類別、直徑及高度。

(圖一) IC Component Solder Ball參數

import clr, os, sys, System
AnsysEM_Path = 'C:/Program Files/AnsysEM/AnsysEM20.2/Win64/'
sys.path.append(AnsysEM_Path)
os.environ['PATH'] += ';' + AnsysEM_Path

clr.AddReference('Ansys.Ansoft.Edb')
clr.AddReference('Ansys.Ansoft.SimSetupData')
import Ansys.Ansoft.Edb as edb

edb.Database.SetRunAsStandAlone(True)

DB = edb.Database.Open('D:/demo/test.aedb', False)

cell = list(DB.TopCircuitCells)
layout = cell[0].GetLayout()

u2a5 = edb.Cell.Hierarchy.Component.FindByName(layout, 'U2A5')
u2a5_property = u2a5.GetComponentProperty().GetSolderBallProperty()
print(u2a5_property.GetShape())
print(u2a5_property.GetDiameter())
print(u2a5_property.GetHeight())

comp_names=[]
for c in layout.Groups:
comp_names.append(c.GetName())
print(comp_names)
輸出結果:
(圖二)輸出solderball及所有PCB元件

2020年10月20日 星期二

如何在PyCharm當中編寫SIwave腳本

在PyCharm開啟專案時,Existing Interpreter需指向AEDT的IronPython路徑,如圖一:

(圖一)開啟新檔時設定IronPython路徑

接著程式碼需先取得oApp,以下為範例程式碼,抓取SIwave版本及專案名稱,並輸出"Hello World"到訊息視窗:

(圖二)取得並輸出SIwave訊息

from System import Activator, Type

SIwaveVerision = "SIwave.Application.2020.2"
oApp = Activator.CreateInstance(Type.GetTypeFromProgID(SIwaveVerision))

print(oApp.GetVersion())

oDoc = oApp.GetActiveProject()
print(oDoc.GetName())

oDoc.ScrLogMessage("Hello World")

(圖三)SIwave輸出訊息



2020年10月11日 星期日

IronPython如何讀取內含中文的.txt並輸出到message window

底下為範例碼:

# -*- coding: utf-8 -*-

import codecs
with codecs.open('d:/demo/help.txt', 'r', 'utf-8', errors = 'ignore') as f:
info = f.read()

    AddWarningMessage(info)


(圖一) help.txt


(圖二) 輸出到訊息視窗


2020年10月9日 星期五

如何取得HFSS可以輸出的solution種類、頻率範圍以及變數?

 要輸出HFSS結果,必須先知道想要的數值屬於哪一種類別,比方說:

  • Fields
  • Modal Solution Type
  • Antenna Parameters
  • Emission Test
  • Far Fields
  • ...

不同類別各自包含不同的solution。而每一個soulution有對應的頻率範圍及變數範圍。底下的函式GetSolutionInfo()可以一次輸出現有專案內關於模擬結果的所有相關訊息:

def GetSolutionInfo():
'''Get all solution variables'''
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()

oModule_rs = oDesign.GetModule("ReportSetup")
oModule_sol = oDesign.GetModule("Solutions")

result = {}
for report_type in oModule_rs.GetAvailableReportTypes():
result[report_type] = []

for solution in oModule_rs.GetAvailableSolutions(report_type):
result[report_type].append((solution,
oModule_sol.GetSolveRangeInfo(solution),
oModule_sol.GetAvailableVariations(solution),
))
# AddWarningMessage(str(result))
return result

if __name__ == '__main__':
info = GetSolutionInfo()
for i in info:
AddWarningMessage(i)
AddInfoMessage(str(info[i]))
(圖一)不同類別及其包括的solution



2020年10月3日 星期六

如何用PyQT5建立TableView?

以下為一個範例檔,欄位當中可以勾選。

tableview.py檔

import os, sys

os.chdir(os.path.dirname(__file__))

from PyQt5 import QtCore
from PyQt5 import QtWidgets, uic
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QBrush, QColor

Ui_MainWindow, QtBaseClass = uic.loadUiType('tableview.ui')


class MainUi(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.initializeNetTAB()

def initializeNetTAB(self):
tableModel = QStandardItemModel(self)
tableModel.itemChanged.connect(self.itemChanged)

tableModel.setHorizontalHeaderLabels(['Name', 'import', 'ports', 'pwr/gnd'])
for i in range(4):
item = QStandardItem(f"case{i}")
tableModel.setItem(i, 0, item)

for j in range(1, 4):
item = QStandardItem()
item.setCheckable(True)
item.setEditable(False)
tableModel.setItem(i, j, item)

self.tableView.setModel(tableModel)

def itemChanged(self, item):
if item.isCheckable() == False:
return

if item.checkState():
item.setText('Yes')
item.setForeground((QBrush(QColor(0, 0, 255, 255))))
else:
item.setText('No')
item.setForeground((QBrush(QColor(100, 100, 100, 255))))


if __name__ == "__main__":
def run_app():
app = QtWidgets.QApplication(sys.argv)
window = MainUi()
window.show()
app.exec_()

run_app()


tableview.ui檔
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>582</width>
<height>751</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QTableView" name="tableView">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>561</width>
<height>691</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>582</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
(圖一) TableView表格