ism-transceiver-915mhz/sim/mixer_matching.ipynb

6.1 KiB

In [72]:
# matching the mixer LO input and RF output to 50 ohms using the S11/S22 parameters
# calculated using Qucs

import qucs.qucsdata as qd
data = qd.QucsData('bfu520_mixer.dat').data


import numpy as np
# find the index closest to 915 MHz
freqs = data['frequency']
idx = np.abs(freqs - 915e+6).argmin()

s11s = data['S[1,1]']
s22s = data['S[2,2]']

s11s[idx,:], s22s[idx,:]
Out[72]:
(array([0.8645785 -0.09823784j, 0.85954376-0.10151559j,
        0.85534282-0.10389085j, 0.85223139-0.10548823j,
        0.85032448-0.10640486j, 0.84968251-0.10670324j,
        0.85032448-0.10640486j, 0.85223139-0.10548823j,
        0.85534282-0.10389085j, 0.85954376-0.10151559j,
        0.8645785 -0.09823784j]),
 array([0.58060059-0.38299298j, 0.5812387 -0.39895514j,
        0.58112332-0.41153593j, 0.58070618-0.42059005j,
        0.58031978-0.42604352j, 0.58016811-0.42786419j,
        0.58031978-0.42604352j, 0.58070618-0.42059005j,
        0.58112332-0.41153593j, 0.5812387 -0.39895514j,
        0.58060059-0.38299298j]))
In [73]:
s11 = np.mean(s11s, axis=1)
s22 = np.mean(s22s, axis=1)
#print(s11)

import skrf.network as net

# conjugate match the source
z_s = net.s2z(np.array([[[s11[idx]]]]))[0, 0, 0]
print(z_s)

# so it looks like it'll need a large series inductor to compensate the imaginary part, followed by a standard 
# L match to 50 ohms
l_series_s = -np.imag(z_s)/(2*np.pi*915e+6)

# how hard would it be to remove the imaginary part using a shunt element?
print(1j/np.imag(1/z_s))
print(1/(1/z_s + 1/(1j/np.imag(1/z_s))))
print(1/(np.imag(1/z_s)*2*np.pi*915e+6))

# okay, 130 nH is pretty big so I'm going to go with the smaller series option

r_s = np.real(z_s)
q_s = np.sqrt((r_s - 50.)/50.)

x_1_s = r_s/q_s
x_2_s = q_s * 50.
print(r_s, x_1_s, x_2_s)

# let's go with a shunt capacitor followed by an inductor
l_series_s2 = x_1_s/(2*np.pi*915e+6)
c_shunt_s = 1/(2*np.pi*915e+6*x_2_s)
print(l_series_s, c_shunt_s, l_series_s2)
(407.8826087843155-328.42259033407754j)
834.9901269321724j
(672.324866234869+0j)
1.452380394909119e-07
407.8826087843155 152.45788592627554 133.76894422554054
5.712576904340215e-08 1.3003005258265486e-12 2.651849853388749e-08
In [74]:
# double check

z_1 = z_s + 2j*np.pi*l_series_s*915e+6
z_2 = 1/(1/z_1 + 1/(1/(2j*np.pi*915e+6*c_shunt_s)))
z_3 = z_2 + 2j*np.pi*915e+6*l_series_s2

print(z_1, z_2, z_3)

# TODO maybe simulate it using scikit-rf network stuff
(407.8826087843155+0j) (39.61039510850523-120.77834197894384j) (39.61039510850523+31.679543947331695j)
In [76]:
# time to conjugate match the output
#z_l = net.s2z(np.array([[[s22[idx]]]]))[0, 0, 0]
z_l = net.s2z(np.array([[[0.544 - 0.345j]]]))[0, 0, 0]

print(z_l)

# series inductor or shunt inductor to cancel out the imaginary impedance? let's compare values like before
z_series_l = -np.imag(z_l)/(2*np.pi*915e+6)
z_shunt_l = 1/(np.imag(1/z_l))/(2*np.pi*915e+6)

print(z_series_l, z_shunt_l)
print(1/(1/z_l + 1/(2j*np.pi*915e+6*z_shunt_l)))

# so either a pair of 15 nH series inductors or a 47 nH shunt; let's see how to the L section looks 
# before deciding here

#r_l = np.real(z_l)
r_l = np.real(1/(1/z_l + 1/(2j*np.pi*915e+6*z_shunt_l)))
q_l = np.sqrt((r_l - 200.)/200.)

x_1_l = r_l/q_l
x_2_l = q_l * 200.
print(r_l, x_1_l, x_2_l)

# let's give the smaller impedance to the capacitor, so it'll be a shunt inductor
l_shunt_l = x_1_l/(2*np.pi*915e+6)
c_series_l = 1/(2*np.pi*915e+6*x_2_l)
l_shunt_total_l = 1/(1/l_shunt_l + 1/z_shunt_l)

print(l_shunt_total_l, 2*c_series_l)
(89.46617486489218-105.51717177278026j)
1.83536387636225e-08 3.154815993634542e-08
(213.91402966297977+0j)
213.91402966297977 811.0129787222926 52.7523073675072
2.5782248342053757e-08 6.594586557283782e-12
In [ ]:
 
In [ ]: