#!/usr/bin/python3
import math
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
from scipy.optimize import minimize
class Vdmos:
def init(self, master=None, data_pool=None):
# build ui
self.main = XXXXXXXXXXXX(master)
self.main.configure(cursor="arrow")
self.main.overrideredirect("false")
self.main.resizable(True, True)
self.main.title("VDMOS")
self.main.geometry('+%d+100'%((self.main.winfo_screenwidth()-600)/2))
validatefloat = (self.main.register(self.validate_float), "%P")
frame_1 = ttk.Frame(self.main)
frame_1.configure(height=200)
notebook_1 = ttk.Notebook(frame_1)
frame_2 = ttk.Frame(notebook_1)
label_1 = ttk.Label(frame_2)
label_1.configure(justify="right", text='Vto(V)')
label_1.grid(column=0, row=0, sticky="e")
self.vto = ttk.Entry(frame_2)
self.vto.configure(
justify="right",
validate="key",
validatecommand=_validate_float,
width=10)
self.vto.grid(column=1, columnspan=2, row=0, sticky="w")
label_4 = ttk.Label(frame_2)
label_4.configure(
anchor="ne",
justify="right",
text='Vgs(V)',
width=10)
label_4.grid(column=0, row=1, sticky="e")
label_5 = ttk.Label(frame_2)
label_5.configure(justify="right", text='Vds(V)')
label_5.grid(column=1, row=1, sticky="e")
label_6 = ttk.Label(frame_2)
label_6.configure(justify="right", text='Id(A)')
label_6.grid(column=2, row=1, sticky="e")
self.vgs_vds_id = []
for i in range(8):
self.vgs_vds_id.append((ttk.Entry(frame_2), ttk.Entry(frame_2), ttk.Entry(frame_2)))
for j in range(3):
self.vgs_vds_id[i][j].configure(
justify="right",
validate="key",
validatecommand=_validate_float,
width=10)
self.vgs_vds_id[i][j].grid(column=j, row=i+2)
notebook_1.add(frame_2, text='Basic')
frame_4 = ttk.Frame(notebook_1)
frame_4.configure(height=200, width=200)
label_2 = ttk.Label(frame_4)
label_2.configure(text='Vj(V)')
label_2.grid(column=0, row=0, sticky="e")
self.vj = ttk.Entry(frame_4)
self.vj.configure(
justify="right",
validate="key",
validatecommand=_validate_float,
width=10)
self.vj.grid(column=1, columnspan=3, row=0, sticky="w")
label_7 = ttk.Label(frame_4)
label_7.configure(text='Vds(V)')
label_7.grid(column=0, row=1, sticky="e")
label_8 = ttk.Label(frame_4)
label_8.configure(text='Ciss(pF)')
label_8.grid(column=1, row=1, sticky="e")
label_9 = ttk.Label(frame_4)
label_9.configure(text='Coss(pF)')
label_9.grid(column=2, row=1, sticky="e")
label_10 = ttk.Label(frame_4)
label_10.configure(text='Crss(pF)')
label_10.grid(column=3, row=1, sticky="e")
self.vds_ciss_coss_crss = []
for i in range(8):
self.vds_ciss_coss_crss.append((ttk.Entry(frame_4), ttk.Entry(frame_4), ttk.Entry(frame_4), ttk.Entry(frame_4)))
for j in range(4):
self.vds_ciss_coss_crss[i][j].configure(
justify="right",
validate="key",
validatecommand=_validate_float,
width=10)
self.vds_ciss_coss_crss[i][j].grid(column=j, row=i+2)
self.vds_ciss_coss_crss[0][0].insert(0, "0")
self.vds_ciss_coss_crss[0][0].configure(state='disabled')
notebook_1.add(frame_4, text='Cap')
notebook_1.pack(expand=True, fill="x", side="top")
frame_1.pack(side="top")
frame_5 = ttk.Frame(self.main)
self.result = tk.Text(frame_5, name="result")
self.result.configure(
borderwidth=1,
height=9,
relief="flat",
setgrid=False,
state="disabled",
undo=False,
width=30)
self.result.pack(
anchor="w",
expand=True,
fill="x",
ipadx=2,
padx=5,
side="left")
button_1 = ttk.Button(frame_5)
button_1.configure(text='Resolve')
button_1.pack(side="top")
button_1.configure(command=self.resolve)
button_2 = ttk.Button(frame_5, name="button_exit")
button_2.configure(text='Exit')
button_2.pack(side="top")
button_2.configure(command=exit)
frame_5.pack(anchor="w", side="top")
# Main widget
self.mainwindow = self.main
def run(self):
self.mainwindow.mainloop()
def validate_float(self, p_entry_value):
p_entry_value = p_entry_value.replace('.','',1)
return p_entry_value=='' or p_entry_value.isdigit()
@staticmethod
def calc_id(vgs, vds, vto, kp, lamb):
return 0 if vgs<vto else \
kp*(1+lamb*vds)*(vgs-vto-vds/2)*vds if vds<vgs-vto else \
kp*(1+lamb*vds)*(vgs-vto)*(vgs-vto)/2
@staticmethod
def calc_cgd(vds, a, cgdmin, cgdmax):
return (cgdmax*math.pi/2+cgdmin-(cgdmax-cgdmin)*math.atan(a*vds))/(1+math.pi/2)
@staticmethod
def calc_cds(vds, vj, cjo, m):
return cjo/math.pow(1+vds/vj, m)
def resolve(self):
self.result.configure(state='normal')
self.result.delete("1.0", tk.END)
self.result.insert(tk.END, ".model <name> VDMOS\n")
try:
# get vto, kp, lambda
vgs_vds_id = tuple(map(lambda x:tuple(map(lambda y:float(y.get()), x)),
filter(lambda z:all(map(lambda t:t.get()!='', z)),
self.vgs_vds_id)))
if self.vto.get()=='' and len(vgs_vds_id)>=3:
vto_kp_lambda=[0., 0., 0.]
solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_id(y[0], y[1], x[0], x[1], x[2])-y[2])**2, vgs_vds_id)),
vto_kp_lambda, bounds=((0, None),(0,None),(0,None)))
if solution.success:
self.result.insert(tk.END, f'+ vto={solution.x[0]:10.4e} kp={solution.x[1]:10.4e} lambda={solution.x[2]:10.4e}\n')
elif self.vto.get()!='' and len(vgs_vds_id)>=2:
vto=float(self.vto.get())
solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_id(y[0], y[1], vto, x[0], x[1])-y[2])**2, vgs_vds_id)),
(0., 0.), bounds=((0, None),(0,None)))
if solution.success:
self.result.insert(tk.END, f'+ vto={vto:10.4e} kp={solution.x[0]:10.4e} lambda={solution.x[1]:10.4e}\n')
# get cgd
vds_crss = tuple(map(lambda x: (float(x[0].get()), float(x[3].get())),
filter(lambda z:z[0].get()!="" and z[3].get()!="", self.vds_ciss_coss_crss)))
a_cgdmin_cgdmax = None
if len(vds_crss)>=3:
solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_cgd(y[0], x[0], x[1], x[2])-y[1])**2, vds_crss)),
(1., 0., 0.), bounds=((0, None),(0, None),(0,None)))
if solution.success:
a_cgdmin_cgdmax = solution.x
elif len(vds_crss)>=2:
solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_cgd(y[0], 1.0, x[0], x[1])-y[1])**2, vds_crss)),
(0., 0.), bounds=((0, None),(0, None)))
if solution.success:
a_cgdmin_cgdmax = (1.0, *solution.x)
elif len(vds_crss)>=1:
a_cgdmin_cgdmax = (1.0, vds_crss[0][1], vds_crss[0][1])
if a_cgdmin_cgdmax is not None:
self.result.insert(tk.END, f'+ a={a_cgdmin_cgdmax[0]:10.4e} cgdmin={a_cgdmin_cgdmax[1]/1e12:10.4e} cgdmax={a_cgdmin_cgdmax[2]/1e12:10.4e}\n')
# get cgs
vds_ciss = tuple(map(lambda x: (float(x[0].get()), float(x[1].get())),
filter(lambda z:z[0].get()!="" and z[1].get()!="", self.vds_ciss_coss_crss)))
if len(vds_ciss)>=1:
if a_cgdmin_cgdmax is not None:
cgs = max(map(lambda x:x[1]-Vdmos.calc_cgd(x[0], *a_cgdmin_cgdmax), vds_ciss))
else:
cgs = max(map(lambda x:x[1], vds_ciss))
self.result.insert(tk.END, f'+ cgs={cgs/1e12:10.4e}\n')
# get cds
vds_cds = tuple(map(lambda x: (float(x[0].get()), float(x[2].get())),
filter(lambda z:z[0].get()!="" and z[2].get()!="", self.vds_ciss_coss_crss)))
if a_cgdmin_cgdmax is not None:
vds_cds = tuple(map(lambda x: (x[0], x[1]-Vdmos.calc_cgd(x[0], *a_cgdmin_cgdmax)), vds_cds))
if self.vj.get()=='' and len(vds_cds)>=3:
solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_cds(y[0], x[0], x[1], x[2])-y[1])**2, vds_cds)),
(0., 0., 0.), bounds=((0.2, 2),(0, None),(0, None)))
if solution.success:
self.result.insert(tk.END, f'+ vj={solution.x[0]:10.4e} cjo={solution.x[1]/1e12:10.4e} m={solution.x[2]:10.4e}\n')
elif self.vj.get()!='' and len(vds_cds)>=2:
vj = float(self.vj.get())
solution = minimize(lambda x:sum(map(lambda y:(Vdmos.calc_cds(y[0], vj, x[0], x[1])-y[1])**2, vds_cds)),
(0., 0.), bounds=((0, None),(0, None)))
if solution.success:
self.result.insert(tk.END, f'+ vj={vj:10.4e} cjo={solution.x[0]/1e12:10.4e} m={solution.x[1]:10.4e}\n')
except Exception as e:
messagebox.showinfo("Exception", e)
self.result.configure(state='disabled')
if name == "__main__":
app = Vdmos()
XXXXXXXXXXXXXX()