This experiment uses data extracted from a vacuum tube datasheet and scipy.optimize to calculate the Child-Langmuir parameters used for circuit simulation.
$$I_a = K (V_{g1k} + D_{g2}V_{g2k} + D_aV_{ak})^\frac{3}{2}$$Now we're adding the van der Veen K modifier,
$$\alpha = \alpha_0\left(\frac{2}{\pi}\arctan \left(\frac{V_{ak}}{V_{g2k}}\right)\right)^\frac{1}{n}$$$$I_a = \alpha K (V_{g1k} + D_{g2}V_{g2k} + D_aV_{ak})^\frac{3}{2}$$$$I_a = \alpha_0\left(\frac{2}{\pi}\arctan\left(\frac{V_{ak}}{V_{g2k}}\right)\right)^\frac{1}{n} K \left(V_{g1k} + D_{g2}V_{g2k} + D_aV_{ak}\right)^\frac{3}{2}$$We are going to use curve fitting to determine $$K, D_a, D_{g2},\alpha_0, \text{ and } n$$
Then we can use Leach's pentode SPICE model with the van der Veen modifier.
In [1]:
import scipy
from scipy.optimize import curve_fit
import numpy as np
import matplotlib.pyplot as plt
from math import pi,atan,log,pow,exp
Starting with the Philips EL34 data sheet, create a PNG of the
Create 9 curves then use 'curve point tool' to add points to each curve
Change export options, "Raw Xs and Ys" and "One curve on each line", otherwise engauge will do some interrupting of your points
In [2]:
%cat data/el34-philips-1958-360V.csv
Need to create scipy array like this
x = scipy.array( [[360, -0.0, 9.66], [360, -0.0, 22.99], ...
y = scipy.array( [0.17962, 0.26382, 0.3227, 0.37863, ...
Vaks = scipy.array( [9.66, 22.99, 41.49, 70.55, 116.61, ...
from the extracted curves
In [3]:
fname = "data/el34-philips-1958-360V.csv"
f = open(fname,'r').readlines()
deltaVgk = -4.0
n = 1.50
VgkVak = []
Iak = []
Vaks = []
f = open(fname,'r').readlines()
vg2k = 360
for l in f:
l = l.strip()
if len(l): # skip blank lines
if l[0] == 'x':
vn = float(l.split("Curve")[1]) - 1.0
Vgk = vn * deltaVgk
continue
else:plt.xkcd()
(Vak,i) = l.split(',')
VgkVak.append([vg2k,float(Vgk),float(Vak)])
Iak.append(float(i))
Vaks.append(float(Vak))
x = scipy.array(VgkVak)
y = scipy.array(Iak)
Vaks = scipy.array(Vaks)
In [4]:
%matplotlib inline
def func(x,K,Da,Dg2,a0,n):
rv = []
for VV in x:
Vg2k = VV[0]
Vg1k = VV[1]
Vak = VV[2]
t = Vg1k + Dg2 * Vg2k + Da * Vak
if t > 0:
a = a0 * ((2/pi) * atan(Vak/Vg2k))**(1/n)
Ia = a * K * t**n
else:
Ia = 0
# print "func",Vg2k,Vg1k,Vak,t,K,Da,Dg2,a0,n
rv.append(Ia)
return rv
popt, pcov = curve_fit(func, x, y,p0=[0.5,0.05,0.05,0.02,5])
#print popt,pcov
(K,Da,Dg2,a0,n) = popt
print "K =",K
print "Da =",Da
print "Dg2 =",Dg2
print "a0 =",a0
print "n =",n
In [5]:
Vg2k = x[0][0]
def IaCalc(Vg1k,Vak):
t = Vg1k + Dg2 * Vg2k + Da * Vak
if t > 0:
a = a0 * ((2/pi) * atan(Vak/Vg2k))**(1/n)
Ia = a * K * t**n
else:
Ia = 0
# print "IaCalc",Vgk,Vak,t,Ia
return Ia
Vgk = np.linspace(0,-32,9)
Vak = np.linspace(0,400,201)
vIaCalc = np.vectorize(IaCalc,otypes=[np.float])
Iavdv = vIaCalc(Vgk[:,None],Vak[None,:])
plt.figure(figsize=(14,6))
for i in range(len(Vgk)):
plt.plot(Vak,Iavdv[i],label=Vgk[i])
plt.scatter(Vaks,y,marker="+")
plt.legend(loc='upper left')
plt.suptitle('EL34@%dV Child-Langmuir-Compton-VanDerVeen Curve-Fit K/Da/Dg2 Model (Philips 1949)'%Vg2k, fontsize=14, fontweight='bold')
plt.grid()
plt.ylim((0,0.5))
plt.xlim((0,400))
plt.show()
Trying the Koren's triode phenomenological model.
$$E_1 = \frac{E_{G2}}{k_P} log\left(1 + exp^{k_P (\frac{1}{u} + \frac{E_{G1}}{E_{G2}})}\right)$$$$I_P = \left(\frac{{E_1}^X}{k_{G1}}\right) \left(1+sgn(E_1)\right)atan\left(\frac{E_P}{k_{VB}}\right)$$Need to fit $X, k_{G1}, k_P, k_{VB}$
In [6]:
mu = 11.0
def sgn(val):
if val >= 0:
return 1
if val < 0:
return -1
def funcKoren(x,X,kG1,kP,kVB):
rv = []
for VV in x:
EG2 = VV[0]
EG1 = VV[1]
EP = VV[2]
if kP < 0:
kP = 0
#print EG2,EG1,EP,kG1,kP,kVB,exp(kP*(1/mu + EG1/EG2))
E1 = (EG2/kP) * log(1 + exp(kP*(1/mu + EG1/EG2)))
if E1 > 0:
IP = (pow(E1,X)/kG1)*(1 + sgn(E1))*atan(EP/kVB)
else:
IP = 0
rv.append(IP)
return rv
popt, pcov = curve_fit(funcKoren,x,y,p0=[1.3,1000,40,20])
#print popt,pcov
(X,kG1,kP,kVB) = popt
print "X=%.8f kG1=%.8f kP=%.8f kVB=%.8f"%(X,kG1,kP,kVB)
# koren's values 12AX7 mu=100 X=1.4 kG1=1060 kP=600 kVB=300
SPICE model
see http://www.normankoren.com/Audio/Tubemodspice_article_2.html#Appendix_A
.SUBCKT 6550 1 2 3 4 ; P G1 C G2 (PENTODE)
+ PARAMS: MU=7.9 EX=1.35 KG1=890 KG2=4200 KP=60 KVB=24
E1 7 0 VALUE={V(4,3)/KP*LOG(1+EXP((1/MU+V(2,3)/V(4,3))*KP))}
G1 1 3 VALUE={(PWR(V(7),EX)+PWRS(V(7),EX))/KG1*ATAN(V(1,3)/KVB)}
G2 4 3 VALUE={(EXP(EX*(LOG((V(4,3)/MU)+V(2,3)))))/KG2}
In [7]:
EG2 = x[0][0]
def IaCalcKoren(EG1,EP):
global X,kG1,kP,kVB,mu
E1 = (EG2/kP) * log(1 + exp(kP*(1/mu + EG1/EG2)))
if E1 > 0:
IP = (pow(E1,X)/kG1)*(1 + sgn(E1))*atan(EP/kVB)
else:
IP = 0
return IP
Vgk = np.linspace(0,-32,9)
Vak = np.linspace(0,400,201)
vIaCalcKoren = np.vectorize(IaCalcKoren,otypes=[np.float])
Iakoren = vIaCalcKoren(Vgk[:,None],Vak[None,:])
plt.figure(figsize=(14,6))
for i in range(len(Vgk)):
plt.plot(Vak,Iakoren[i],label=Vgk[i])
plt.scatter(Vaks,y,marker="+")
plt.legend(loc='upper left')
plt.suptitle('EL34@%dV Child-Langmuir-Compton-Koren Curve-Fit Model (Philips 1949)'%Vg2k, fontsize=14, fontweight='bold')
plt.grid()
plt.ylim((0,0.5))
plt.xlim((0,400))
plt.show()
In [8]:
plt.figure(figsize=(14,6))
for i in range(len(Vgk)):
plt.plot(Vak,Iavdv[i],label=Vgk[i],color='red')
plt.plot(Vak,Iakoren[i],label=Vgk[i],color='blue')
plt.scatter(Vaks,y,marker="+")
plt.legend(loc='upper left')
plt.suptitle('EL34@%dV CLCVDV & CLCK Curve-Fit Model (Philips 1949)'%Vg2k, fontsize=14, fontweight='bold')
plt.grid()
plt.ylim((0,0.5))
plt.xlim((0,400))
plt.show()
In [ ]: