Finding the electrical length of the branches of an N type T – #3

Finding the electrical length of the branches of an N type T – #1 posed a problem, this article looks at one solution.

For convenience, here is the problem.

An interesting problem arises in some applications in trying to measure the electrical length of each branch of a N type T piece.

Let's make some assumptions that the device is of quality, that the connection from each connector to the internal junction is a uniform almost lossless transmission line of Zo=50Ω. Don't assume that the left and right branches above are of the same length (though they often are) and we should not assume that the nearest branch is of the same length as the others (and they are often not).

Before we start, we will calibrate the VNA entering the offsets appropriate to the OPEN and SHORT cal parts.

So, the problem is all the uncertain things that connect to the internal T junction. Lets connect a calibration quality 50Ω termination to the left hand port. We now know that the path from the male port to the remaining female port comprises lengths l2 and l1 of low loss 50Ω transmission line with a 50Ω resistor shunting at the junction of l1 and l2.

Now lets connect a calibration quality short (SC) to the right hand female port, and measure the X component of the impedance looking into the male port. So, the instrument measuring Z at the male connector sees two sections of low loss 50Ω line to the 50Ω load, and the right hand SC stub shunting at the internal T junction.

Without the 50Ω shunting at the internal T junction, Zin would simply be that of a low loss SC stub, and would be a tan curve turning upwards to a peak at a frequency where l2 is 90°.

Above is a Simsmith simulation of Xin to 1500MHz. This is clearly not a tan curve, it does not turn upwards but turns downwards towards 1500MHz. The shape of the curve is due to all configuration factors, the assumed constraints and l1 and l2.

Let's measure

Without the 50Ω shunting at the internal T junction, Zin would simply be that of a low loss SC stub, and would be a tan curve turning upwards to a peak at a frequency where l2 is 90°.

Above is the Smith chart of the sweep from the Agilent E5061A. From that we can extract the Xin vs frequency dataset for curve fitting. We save this sweep as a .s1p file.

Let's curve fit

A Python script was written to extract Xin from the .s1p file, and fit a model of the transmission line structure to the measured data, finding l1 and l2.

Above is the measured and modelled curve fit.

1-Port Network: 'T-N-HPVNA01', 100000000.0-1500000000.0 Hz, 201 pts, z0=[50.+0.j]

Model t: t1= 67.9ps, t2=110.6ps
σ: σ1= 0.08ps, σ2= 0.09ps

Model l: l1= 20.4mm, l2= 33.2mm
σ: σ1= 0.02mm, σ2= 0.03mm

Above are the calculated model values, l1=20.3mm with σ=0.025mm, and l2=33.2mm with σ=0.028mm. This is quite a good model.

Don't forget to then adjust for the offset of the SC used.

Python script

#!/usr/bin/python3
import os,sys
import csv
from scipy import stats
import getopt
import numpy
import math
import cmath
import skrf as rf
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def usage():
  print("Usage: "+sys.argv[0]+"")
  sys.exit(1)

try:
    opts, args = getopt.getopt(sys.argv[1:], "ho:vl:u:", ["help", "output="])
except getopt.GetoptError as err:
    # print help information and exit:
    print(err)  # will print something like "option -a not recognized"
    usage()
#    sys.exit(2)
output = None
verbose = False
for o, a in opts:
    if o == "-v":
        verbose = True
    elif o in ("-h", "--help"):
        usage()
        sys.exit()
    else:
        assert False, "unhandled option"
try:
  pass
  infile=args[0]
except:
  usage()
  
nw1=rf.Network(infile)
print(nw1)
print()
f=numpy.array(nw1.f)
x=numpy.array(nw1.z_im[:,0,0])

c0=299792458
zo=nw1.z0[0][0]

def t_xin(freq,t1,t2):
  p=1/freq*1e12
  z=zo*numpy.tan(t1/p*2*math.pi)*1j
  z=1/(1/z+1/zo)
  x=(zo*(z+zo*numpy.tan(t2/p*2*math.pi)*1j)/(zo+z*numpy.tan(t2/p*2*math.pi)*1j)).imag
  return x

popt,pcov=curve_fit(t_xin,f,x,bounds=(0, [150,150]),method='trf')
perr=numpy.sqrt(numpy.diag(pcov))
print('Model t: t1=%5.1fps, t2=%5.1fps' % tuple(popt))
print('      \u03C3: \u03C31=%5.2fps, \u03C32=%5.2fps' % tuple(perr))
print()
print('Model l: l1=%5.1fmm, l2=%5.1fmm' % tuple(popt*1e-9*c0))
print('      \u03C3: \u03C31=%5.2fmm, \u03C32=%5.2fmm' % tuple(perr*1e-9*c0))

plt.figure(figsize=(8, 6), dpi=128)
plt.plot(f/1e6,x, 'r-', label='measured')
plt.plot(f/1e6,t_xin(f,*popt),'k:',label='fit: t1=%5.2fps, t2=%5.2fps' % tuple(popt))
plt.xlabel('Freq (MHz)')
plt.ylabel('X ($\Omega$)')
plt.legend()
plt.title('T characterisation: '+nw1.name)
plt.ylim(bottom=0)
plt.xlim(left=0)
plt.savefig(nw1.name+'.png')

Credit to Bruce (VK4MQ) for making the measurements, pics etc.