61 views

Skip to first unread message

Jan 22, 2023, 10:05:48â€¯AMJan 22

to scikit-rf

Hi All,

I'm trying to get a script going to implement RF band-pass filter tuning in the time domain.

The script takes as input two s-parameter files, one the template to tune against and the other the filter design to be tuned in an iterative loop between the script and a 3D EM simulator.

The script then plots the s11 magnitude (in dB) of both s-parameter files in the time domain to enable the tuning method.

The snag is that I can't seem to achieve time domain s11 plots with enough resolution as would be expected from the time domain transform on a network anaylser (see plots below).

What I need to see is a plot similar to this:

Any ideas on how I can achieve this/where I'm going wrong?

Cheers,

Nath

Jan 22, 2023, 11:35:19â€¯AMJan 22

to scikit-rf

Hi Nath,

one thing I noticed is the very different time span in your time plots compared to your textbook example below that: your time span is 9 ns (from -3 ns to 6 ns), the textbook plot has 60 ns (from -10 ns to 50 ns).

The time resolution depends on the frequency span and the time span depends on the frequency resolution: dt = 1 / f_span and t_span = 1 / df.

Try increasing the frequency resolution to get a larger time span.

Regards, Vincent

Jan 22, 2023, 3:17:10â€¯PMJan 22

to scikit-rf

Hi Vincent,

Thanks for your quick reply.

I completely agree with your analysis and it is becoming apparent to me that for bandpass filter tuning (which is admittedly a bit of a special case) interpolation of the time domain transform s11 result is needed.

So, for the text book example above (from Joel Dunsmore's* PhD thesis on the bandpass filter tuning method p26) the frequency span is 320 MHz which means the IFFT output resolution is 3.125 ns.

But, examination of the corresponding time domain response shows that the resolution is far finer than 3.125 ns which suggests interpolation of the time domain response is needed prior to plotting which is what happens in networks analysers with time domain as an option.

Since the time domain transform of the frequency domain s11 of a bandpass filter results in a response which is full of peaks and nulls, curve fitting the IFFT s11 output data is not going to work well!

Therefore, the IFFT s11 output data needs to be converted to a linear quantity (e.g. reflection coefficient or scalar input impedance) first which will have a much smoother response which can then be curve fitted much more closely.

This curve-fitted data can then finally be converted to time domain s11 to give a time-domain response like the text book example.

The problem I'm having is trying to implement this since the other network time domain methods in scikit-rf all seem to involve convolution with an impulse to derive TDR-like responses which is not the same as simply performing an IFFT on s11 data.

The only two methods that give the result I need (plot_s_db_time() and plot_s_time_db()) are both plotting methods and so I can't seem to get hold of the output data to implement the interpolation.

Does that explain my challenge a bit better?

Cheers,

Nath

*For those that don't know him he's a top Jedi at Keysight.

Jan 23, 2023, 2:23:55â€¯PMJan 23

to scikit-rf

Hi Nath,

your message does not quite make sense to me, I'm sorry! If I understood correctly, you want to increase the resolution in the time domain to be able to see the nulls. Again, you can do that by increasing the frequency span. I don't see the need for interpolation or curve fitting.

Maybe it's better to discuss a real example. See this these four cases with the same 3rd order Chebyshev bandpass (code below).

Regards, Vincent

Case 1:

Case 2:

Case 3:

Case 4:

import matplotlib.pyplot as mplt

import skrf

c1 = 1.729e-12

c2 = 9.172e-12

c3 = c1

l1 = 24.42e-9

l2 = 4.603e-9

l3 = l1

freq = skrf.Frequency(start=100e6, stop=20.1e9, unit='Hz', npoints=2001)

f_span = freq.span

df = freq.df[0]

t_span = 1 / df

import skrf

c1 = 1.729e-12

c2 = 9.172e-12

c3 = c1

l1 = 24.42e-9

l2 = 4.603e-9

l3 = l1

freq = skrf.Frequency(start=100e6, stop=20.1e9, unit='Hz', npoints=2001)

f_span = freq.span

df = freq.df[0]

t_span = 1 / df

dt = 1 / f_span

tl_media = skrf.DefinedGammaZ0(freq, z0=50, gamma=1j*freq.w/skrf.c)

nw_c1 = tl_media.capacitor(c1, name='C1')

nw_c2 = tl_media.capacitor(c2, name='C2')

nw_c3 = tl_media.capacitor(c3, name='C3')

nw_l1 = tl_media.inductor(l1, name='L1')

nw_l2 = tl_media.inductor(l2, name='L2')

nw_l3 = tl_media.inductor(l3, name='L3')

nw_gnd = skrf.Circuit.Ground(freq, name='GND')

nw_port1 = skrf.Circuit.Port(freq, name='port1', z0=50)

nw_port2 = skrf.Circuit.Port(freq, name='port2', z0=50)

netlist = [[(nw_port1, 0), (nw_l1, 0)],

[(nw_l1, 1), (nw_c1, 0)],

[(nw_c1, 1), (nw_l2, 1), (nw_c2, 1), (nw_c3, 0)],

[(nw_c3, 1), (nw_l3, 0)],

[(nw_l3, 1), (nw_port2, 0)],

[(nw_l2, 0), (nw_c2, 0), (nw_gnd, 0)]]

cir = skrf.Circuit(netlist)

nw_bandpass = cir.network.extrapolate_to_dc()

fig, ax = mplt.subplots(2, 1)

ax[0].set_title(f'f_span = {f_span * 1e-6} MHz, df = {df * 1e-6} MHz')

ax[1].set_title(f't_span = {t_span * 1e9} ns, dt = {dt * 1e9} ns')

nw_bandpass.plot_s_db(0, 0, ax=ax[0])

nw_bandpass.plot_s_db(1, 0, ax=ax[0])

nw_bandpass.plot_s_time_db(0, 0, ax=ax[1])

mplt.tight_layout()

mplt.show()

nw_c1 = tl_media.capacitor(c1, name='C1')

nw_c2 = tl_media.capacitor(c2, name='C2')

nw_c3 = tl_media.capacitor(c3, name='C3')

nw_l1 = tl_media.inductor(l1, name='L1')

nw_l2 = tl_media.inductor(l2, name='L2')

nw_l3 = tl_media.inductor(l3, name='L3')

nw_gnd = skrf.Circuit.Ground(freq, name='GND')

nw_port1 = skrf.Circuit.Port(freq, name='port1', z0=50)

nw_port2 = skrf.Circuit.Port(freq, name='port2', z0=50)

netlist = [[(nw_port1, 0), (nw_l1, 0)],

[(nw_l1, 1), (nw_c1, 0)],

[(nw_c1, 1), (nw_l2, 1), (nw_c2, 1), (nw_c3, 0)],

[(nw_c3, 1), (nw_l3, 0)],

[(nw_l3, 1), (nw_port2, 0)],

[(nw_l2, 0), (nw_c2, 0), (nw_gnd, 0)]]

cir = skrf.Circuit(netlist)

nw_bandpass = cir.network.extrapolate_to_dc()

fig, ax = mplt.subplots(2, 1)

ax[0].set_title(f'f_span = {f_span * 1e-6} MHz, df = {df * 1e-6} MHz')

ax[1].set_title(f't_span = {t_span * 1e9} ns, dt = {dt * 1e9} ns')

nw_bandpass.plot_s_db(0, 0, ax=ax[0])

nw_bandpass.plot_s_db(1, 0, ax=ax[0])

nw_bandpass.plot_s_time_db(0, 0, ax=ax[1])

mplt.tight_layout()

mplt.show()

Jan 26, 2023, 1:11:13â€¯PMJan 26

to scikit-rf

Hi Vincent,

Many thanks for the plots and code, although it looks like it's more complicated than that unfortunately...

Joel Dunsmore's PhD thesis explains things a bit better - see section 3.2.1 (p50) onwards for more details.

In essence, the IFFT is not the tool for the job since the output resolution is limited to 1/Fspan whereas other transform methods provide much finer time resolution suitable for tuning band-pass filters in the time-domain.

So, it's back to school for me and hopefully the scipy library has the functions I need.

Cheers,

Nath

Jan 26, 2023, 4:34:25â€¯PMJan 26

to scikit-rf

In my opinion, the good old IFFT as implemented in scikit-rf is enough. But it's obviously for you to decide what works for your application and what doesn't. It would be interesting to learn what exactly you want to achieve and why it does not work with scikit-rf.

One final attempt to convince you (or at least understand your problem), then I'll let it go:

I did not fully read Joel's thesis and only browsed through, but I think the basic idea is to tune the filter elements so they create distinct notches/nulls in the time domain response of S11. Although the step-by-step tuning process as outlined in Table 4-1 of the thesis did not work for me, the general concept can be demonstrated in scikit-rf with the example from my last message. The discrepancy probably has to do with what Joel calls "VNA time-domain response", which he uses for his examples, and which is different from the regular impulse response obtained from an IFFT. See his Figure 5-6.

I tried another 3rd order bandpass, this time with much smaller bandwidth, similar to Figure 4-16 in the thesis. The frequency settings (and resulting time-domain settings) are printed in the figures; I used start=100e6, stop=2.1e9, npoints=1001 for the frequency, but I manually decreased the plotted frequency range for visibility. As you see, the characteristic notches in the time-domain are clearly visible for the tuned filter and they fade away as the filter gets out of tune.

Case 1 - Tuned:

c1 = 132.8e-15

c2 = 121.7e-12

c3 = c1

l1 = 273.6e-9

l2 = 298.5e-12

l3 = l1

c2 = 121.7e-12

c3 = c1

l1 = 273.6e-9

l2 = 298.5e-12

l3 = l1

Case 2 - slightly detuned:

c1 = 140e-15

c2 = 120e-12

c3 = c1

l1 = 250e-9

l2 = 300e-12

l3 = l1

c2 = 120e-12

c3 = c1

l1 = 250e-9

l2 = 300e-12

l3 = l1

Case 3 - totally detuned:

c1 = 100e-15

c2 = 100e-12

c3 = c1

l1 = 200e-9

l2 = 400e-12

l3 = l1

c2 = 100e-12

c3 = c1

l1 = 200e-9

l2 = 400e-12

l3 = l1

Reply all

Reply to author

Forward

0 new messages

Search

Clear search

Close search

Google apps

Main menu