{ "cells": [ { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(array([0.8645785 -0.09823784j, 0.85954376-0.10151559j,\n", " 0.85534282-0.10389085j, 0.85223139-0.10548823j,\n", " 0.85032448-0.10640486j, 0.84968251-0.10670324j,\n", " 0.85032448-0.10640486j, 0.85223139-0.10548823j,\n", " 0.85534282-0.10389085j, 0.85954376-0.10151559j,\n", " 0.8645785 -0.09823784j]),\n", " array([0.58060059-0.38299298j, 0.5812387 -0.39895514j,\n", " 0.58112332-0.41153593j, 0.58070618-0.42059005j,\n", " 0.58031978-0.42604352j, 0.58016811-0.42786419j,\n", " 0.58031978-0.42604352j, 0.58070618-0.42059005j,\n", " 0.58112332-0.41153593j, 0.5812387 -0.39895514j,\n", " 0.58060059-0.38299298j]))" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# matching the mixer LO input and RF output to 50 ohms using the S11/S22 parameters\n", "# calculated using Qucs\n", "\n", "import qucs.qucsdata as qd\n", "data = qd.QucsData('bfu520_mixer.dat').data\n", "\n", "\n", "import numpy as np\n", "# find the index closest to 915 MHz\n", "freqs = data['frequency']\n", "idx = np.abs(freqs - 915e+6).argmin()\n", "\n", "s11s = data['S[1,1]']\n", "s22s = data['S[2,2]']\n", "\n", "s11s[idx,:], s22s[idx,:]" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(407.8826087843155-328.42259033407754j)\n", "834.9901269321724j\n", "(672.324866234869+0j)\n", "1.452380394909119e-07\n", "407.8826087843155 152.45788592627554 133.76894422554054\n", "5.712576904340215e-08 1.3003005258265486e-12 2.651849853388749e-08\n" ] } ], "source": [ "s11 = np.mean(s11s, axis=1)\n", "s22 = np.mean(s22s, axis=1)\n", "#print(s11)\n", "\n", "import skrf.network as net\n", "\n", "# conjugate match the source\n", "z_s = net.s2z(np.array([[[s11[idx]]]]))[0, 0, 0]\n", "print(z_s)\n", "\n", "# so it looks like it'll need a large series inductor to compensate the imaginary part, followed by a standard \n", "# L match to 50 ohms\n", "l_series_s = -np.imag(z_s)/(2*np.pi*915e+6)\n", "\n", "# how hard would it be to remove the imaginary part using a shunt element?\n", "print(1j/np.imag(1/z_s))\n", "print(1/(1/z_s + 1/(1j/np.imag(1/z_s))))\n", "print(1/(np.imag(1/z_s)*2*np.pi*915e+6))\n", "\n", "# okay, 130 nH is pretty big so I'm going to go with the smaller series option\n", "\n", "r_s = np.real(z_s)\n", "q_s = np.sqrt((r_s - 50.)/50.)\n", "\n", "x_1_s = r_s/q_s\n", "x_2_s = q_s * 50.\n", "print(r_s, x_1_s, x_2_s)\n", "\n", "# let's go with a shunt capacitor followed by an inductor\n", "l_series_s2 = x_1_s/(2*np.pi*915e+6)\n", "c_shunt_s = 1/(2*np.pi*915e+6*x_2_s)\n", "print(l_series_s, c_shunt_s, l_series_s2)\n" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(407.8826087843155+0j) (39.61039510850523-120.77834197894384j) (39.61039510850523+31.679543947331695j)\n" ] } ], "source": [ "# double check\n", "\n", "z_1 = z_s + 2j*np.pi*l_series_s*915e+6\n", "z_2 = 1/(1/z_1 + 1/(1/(2j*np.pi*915e+6*c_shunt_s)))\n", "z_3 = z_2 + 2j*np.pi*915e+6*l_series_s2\n", "\n", "print(z_1, z_2, z_3)\n", "\n", "# TODO maybe simulate it using scikit-rf network stuff" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(89.46617486489218-105.51717177278026j)\n", "1.83536387636225e-08 3.154815993634542e-08\n", "(213.91402966297977+0j)\n", "213.91402966297977 811.0129787222926 52.7523073675072\n", "2.5782248342053757e-08 6.594586557283782e-12\n" ] } ], "source": [ "# time to conjugate match the output\n", "#z_l = net.s2z(np.array([[[s22[idx]]]]))[0, 0, 0]\n", "z_l = net.s2z(np.array([[[0.544 - 0.345j]]]))[0, 0, 0]\n", "\n", "print(z_l)\n", "\n", "# series inductor or shunt inductor to cancel out the imaginary impedance? let's compare values like before\n", "z_series_l = -np.imag(z_l)/(2*np.pi*915e+6)\n", "z_shunt_l = 1/(np.imag(1/z_l))/(2*np.pi*915e+6)\n", "\n", "print(z_series_l, z_shunt_l)\n", "print(1/(1/z_l + 1/(2j*np.pi*915e+6*z_shunt_l)))\n", "\n", "# so either a pair of 15 nH series inductors or a 47 nH shunt; let's see how to the L section looks \n", "# before deciding here\n", "\n", "#r_l = np.real(z_l)\n", "r_l = np.real(1/(1/z_l + 1/(2j*np.pi*915e+6*z_shunt_l)))\n", "q_l = np.sqrt((r_l - 200.)/200.)\n", "\n", "x_1_l = r_l/q_l\n", "x_2_l = q_l * 200.\n", "print(r_l, x_1_l, x_2_l)\n", "\n", "# let's give the smaller impedance to the capacitor, so it'll be a shunt inductor\n", "l_shunt_l = x_1_l/(2*np.pi*915e+6)\n", "c_series_l = 1/(2*np.pi*915e+6*x_2_l)\n", "l_shunt_total_l = 1/(1/l_shunt_l + 1/z_shunt_l)\n", "\n", "print(l_shunt_total_l, 2*c_series_l)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }