Tuesday, September 11, 2018

L-Networks: New Equations for Better Accuracy

Component-value formulas and on-line design tools for L-Network designs typically assume that the components are lossless.  But all components have loss, and the greater this loss, the greater will be the error in the results when using these formulas and tools.

This blog post presents a new set of design equations for low-pass L-network configurations that include component losses.  The resulting calculated L and C component values will provide the correct impedance transformation, irrespective of component Q.

And this post will show how MATLAB's Symbolic Math Toolbox is used to generate these equations (thanks to Dick Benson, W1QG).

Important Note:  The equations will be for the LsCp and CpLs low-pass L-Network configurations, shown in the schematics, below.  Design equations for other network configurations can be derived in a similar fashion to the derivation process I will present later in this post.


Example, Calculating L-Network Values without Loss:

First, let's look at calculating L-network values for an LsCp network and for a CpLs network, assuming the components are lossless (i.e. infinite Q).

As Zload (the load impedance), I'll choose two points from the outer edge of the plot below from my earlier L-network post (note that this edge corresponds to a 10:1 SWR circle).


I'm going to choose the two points where, if component Qs were 100, the L-network would experience its worst power dissipation.  These two points are at 66 and 246 degrees:
  • At 66 degrees Zload is 16.47 + j74.46 ohms.
  • At 246 degrees Zload is 7.079 - j32.01 ohms.
What are the LsCp and CpLs L-network component values that will match these two loads to 50+j0 ohms?

Let's use an on-line calculator, Impedance Matching Network Designer, to find the L-network component values for each load.  Note that the calculator assumes that the L and C components are lossless (i.e. component Q is infinite).

For Zload = 7.079 - j32.01 ohms at 3.5 MHz, the on-line calculator returns the following component values:


Note that the matching network is a CpLs L-network configuration.

And for Zload = 7.079 - j32.01 ohms at 3.5 MHz, the on-line calculator returns the following component values:


This load requires an LsCp L-network configuration.

Let's now plot the resulting matches on Smith Charts to check that they indeed provide a match.  Component Qs are set to be essentially infinite.

First, the CpLs network:


And now the LsCp network:


Both networks match to a 1:1 SWR.

But suppose the network components are instead lossy (i.e. finite Qs), rather than lossless?  Let's see what happens to the SWR if I change the inductor Q and the capacitor Q to each equal 100.  Below are the new Smith Charts...

The CpLs network:


And the LsCp network:


In these two examples the calculated L-network values no longer provide a 1:1 match!  And if component Qs were to decrease further (so that there is more loss), the match would worsen.

Clearly this is not our goal.  Is there a way to accurately calculate L and C component values that take into account real-world component loss?

Yes there is!  Let's look at a set of equations that will exactly calculate the requisite L-network component values to provide a 1:1 match even if these components have low Q values.  And we can derive the equations that do this using MATLAB's Symbolic Math Toolbox.


Example, Calculating L-Network Values with Loss:

Before delving into the equations themselves and their derivation, let me first calculate the component values using these new equations and show that the values, with finite Q (in this case, 100), provide a 1:1 match.

For a CpLs network, the MATLAB script calculates and returns two pairs of inductive (XL) and capacitive (XC) reactance values, given Zload, component Qs, and Zsource.  If a CpLs network exists for this load, then one of the XL,XC pairs will have both of its values positive and real (no imaginary component).  Pairs in which either (or both) values is negative or complex means that the pair is invalid.

Below I've shown the valid XL, XC pair required for the CpLs network to match a Zload of 16.47 + j74.46 ohms, given an inductor Q of 100 and a capacitor Q of 100.


And below is a similar calculation for a Zload of 7.079 - j32.01 ohms and the same network component Qs.  This time, I've calculated the values for an LsCp network.  And again, only one pair of values meets the "both positive and real" criteria.


Given these XL and XC values and an operating frequency of 3.5 MHz, we can easily calculate the capacitance and inductance values from these reactances (an exercise left to the reader, but you will see that I've inserted these values into the SimSmith charts, below).

And here are the resultant Smith Charts.  You can see that the resulting SWRs are now 1:1, even with finite component Qs.



Here is a table with a comparison of the SWRs for the on-line calculator values versus the values found via MATLAB's Symbolic Math:


Note the higher SWR when the Q of the components calculated with the on-line calculator are each 100, compared to the components calculated with MATLAB.

What are the new equations and how were they derived?  Let's look at the MATLAB scripts:


The MATLAB Scripts:

Below is the MATLAB script to calculate the XL and XC values for a CpLs low-pass L-network.  Note that its inputs are Zload, Zsource, Qinductor and Qcapacitor.  The outputs are Xinductor and Xcapacitor.  These are seriously complex equations!

function [ X_L_Val, X_C_Val ] = shunt_C_ser_L_Q_3(Rload,Xload,Rsource,Xsource,Q_L,Q_C)
close
clc

% Formulas generated using symbolic math
% generated in the script: SymMath_CpLs_from_Qs_and_Zload_3.m

% This third version calculates X_C in lieu of B_C

% First, calculating the two XL values:
X_L_Val(1) =   (Q_L*(Q_C*Rsource^2 - 2*Rload*Xsource + Q_L*Rsource^2 + Q_C*Xsource^2 + Q_L*Xsource^2 + (- 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource^3 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xsource^2 + 8*Q_C^2*Q_L*Rload*Rsource^2*Xload - 4*Q_C^2*Q_L*Rsource^3*Xload - 4*Q_C^2*Q_L*Rsource*Xload*Xsource^2 + Q_C^2*Rsource^4 - 4*Q_C^2*Rsource^2*Xload^2 + 2*Q_C^2*Rsource^2*Xsource^2 + Q_C^2*Xsource^4 - 8*Q_C*Q_L^2*Rload^2*Rsource*Xsource + 4*Q_C*Q_L^2*Rload*Rsource^2*Xsource + 4*Q_C*Q_L^2*Rload*Xsource^3 - 4*Q_C*Q_L*Rload*Rsource^3 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xsource^2 + 2*Q_C*Q_L*Rsource^4 - 4*Q_C*Q_L*Rsource^2*Xload*Xsource + 4*Q_C*Q_L*Rsource^2*Xsource^2 - 4*Q_C*Q_L*Xload*Xsource^3 + 2*Q_C*Q_L*Xsource^4 + 4*Q_C*Rsource^3*Xload - 8*Q_C*Rsource*Xload^2*Xsource + 4*Q_C*Rsource*Xload*Xsource^2 - 4*Q_L^2*Rload^2*Xsource^2 + Q_L^2*Rsource^4 + 2*Q_L^2*Rsource^2*Xsource^2 + Q_L^2*Xsource^4 - 4*Q_L*Rload*Rsource^2*Xsource + 8*Q_L*Rload*Xload*Xsource^2 - 4*Q_L*Rload*Xsource^3 + 4*Rsource^2*Xload*Xsource - 4*Xload^2*Xsource^2 + 4*Xload*Xsource^3)^(1/2) - 2*Q_C*Rload*Rsource - 2*Q_L*Xload*Xsource - 2*Q_C*Q_L*Rsource*Xload))/(2*(Q_L^2 + 1)*(Xsource + Q_C*Rsource));

X_L_Val(2) = -(Q_L*(2*Rload*Xsource - Q_C*Rsource^2 - Q_L*Rsource^2 - Q_C*Xsource^2 - Q_L*Xsource^2 + (- 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource^3 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xsource^2 + 8*Q_C^2*Q_L*Rload*Rsource^2*Xload - 4*Q_C^2*Q_L*Rsource^3*Xload - 4*Q_C^2*Q_L*Rsource*Xload*Xsource^2 + Q_C^2*Rsource^4 - 4*Q_C^2*Rsource^2*Xload^2 + 2*Q_C^2*Rsource^2*Xsource^2 + Q_C^2*Xsource^4 - 8*Q_C*Q_L^2*Rload^2*Rsource*Xsource + 4*Q_C*Q_L^2*Rload*Rsource^2*Xsource + 4*Q_C*Q_L^2*Rload*Xsource^3 - 4*Q_C*Q_L*Rload*Rsource^3 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xsource^2 + 2*Q_C*Q_L*Rsource^4 - 4*Q_C*Q_L*Rsource^2*Xload*Xsource + 4*Q_C*Q_L*Rsource^2*Xsource^2 - 4*Q_C*Q_L*Xload*Xsource^3 + 2*Q_C*Q_L*Xsource^4 + 4*Q_C*Rsource^3*Xload - 8*Q_C*Rsource*Xload^2*Xsource + 4*Q_C*Rsource*Xload*Xsource^2 - 4*Q_L^2*Rload^2*Xsource^2 + Q_L^2*Rsource^4 + 2*Q_L^2*Rsource^2*Xsource^2 + Q_L^2*Xsource^4 - 4*Q_L*Rload*Rsource^2*Xsource + 8*Q_L*Rload*Xload*Xsource^2 - 4*Q_L*Rload*Xsource^3 + 4*Rsource^2*Xload*Xsource - 4*Xload^2*Xsource^2 + 4*Xload*Xsource^3)^(1/2) + 2*Q_C*Rload*Rsource + 2*Q_L*Xload*Xsource + 2*Q_C*Q_L*Rsource*Xload))/(2*(Q_L^2 + 1)*(Xsource + Q_C*Rsource));

% ...and calculate the two XC values:
X_C_Val(1) = (Q_C*(2*Rsource*Xload + Q_C*Rsource^2 + Q_L*Rsource^2 + Q_C*Xsource^2 + Q_L*Xsource^2 + (- 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource^3 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xsource^2 + 8*Q_C^2*Q_L*Rload*Rsource^2*Xload - 4*Q_C^2*Q_L*Rsource^3*Xload - 4*Q_C^2*Q_L*Rsource*Xload*Xsource^2 + Q_C^2*Rsource^4 - 4*Q_C^2*Rsource^2*Xload^2 + 2*Q_C^2*Rsource^2*Xsource^2 + Q_C^2*Xsource^4 - 8*Q_C*Q_L^2*Rload^2*Rsource*Xsource + 4*Q_C*Q_L^2*Rload*Rsource^2*Xsource + 4*Q_C*Q_L^2*Rload*Xsource^3 - 4*Q_C*Q_L*Rload*Rsource^3 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xsource^2 + 2*Q_C*Q_L*Rsource^4 - 4*Q_C*Q_L*Rsource^2*Xload*Xsource + 4*Q_C*Q_L*Rsource^2*Xsource^2 - 4*Q_C*Q_L*Xload*Xsource^3 + 2*Q_C*Q_L*Xsource^4 + 4*Q_C*Rsource^3*Xload - 8*Q_C*Rsource*Xload^2*Xsource + 4*Q_C*Rsource*Xload*Xsource^2 - 4*Q_L^2*Rload^2*Xsource^2 + Q_L^2*Rsource^4 + 2*Q_L^2*Rsource^2*Xsource^2 + Q_L^2*Xsource^4 - 4*Q_L*Rload*Rsource^2*Xsource + 8*Q_L*Rload*Xload*Xsource^2 - 4*Q_L*Rload*Xsource^3 + 4*Rsource^2*Xload*Xsource - 4*Xload^2*Xsource^2 + 4*Xload*Xsource^3)^(1/2) - 2*Q_L*Rload*Rsource - 2*Q_C*Xload*Xsource + 2*Q_C*Q_L*Rload*Xsource))/(2*(Q_C^2 + 1)*(Xload - Xsource - Q_L*Rload + Q_L*Rsource));

X_C_Val(2) = (Q_C*(2*Rsource*Xload + Q_C*Rsource^2 + Q_L*Rsource^2 + Q_C*Xsource^2 + Q_L*Xsource^2 - (- 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource^3 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xsource^2 + 8*Q_C^2*Q_L*Rload*Rsource^2*Xload - 4*Q_C^2*Q_L*Rsource^3*Xload - 4*Q_C^2*Q_L*Rsource*Xload*Xsource^2 + Q_C^2*Rsource^4 - 4*Q_C^2*Rsource^2*Xload^2 + 2*Q_C^2*Rsource^2*Xsource^2 + Q_C^2*Xsource^4 - 8*Q_C*Q_L^2*Rload^2*Rsource*Xsource + 4*Q_C*Q_L^2*Rload*Rsource^2*Xsource + 4*Q_C*Q_L^2*Rload*Xsource^3 - 4*Q_C*Q_L*Rload*Rsource^3 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xsource^2 + 2*Q_C*Q_L*Rsource^4 - 4*Q_C*Q_L*Rsource^2*Xload*Xsource + 4*Q_C*Q_L*Rsource^2*Xsource^2 - 4*Q_C*Q_L*Xload*Xsource^3 + 2*Q_C*Q_L*Xsource^4 + 4*Q_C*Rsource^3*Xload - 8*Q_C*Rsource*Xload^2*Xsource + 4*Q_C*Rsource*Xload*Xsource^2 - 4*Q_L^2*Rload^2*Xsource^2 + Q_L^2*Rsource^4 + 2*Q_L^2*Rsource^2*Xsource^2 + Q_L^2*Xsource^4 - 4*Q_L*Rload*Rsource^2*Xsource + 8*Q_L*Rload*Xload*Xsource^2 - 4*Q_L*Rload*Xsource^3 + 4*Rsource^2*Xload*Xsource - 4*Xload^2*Xsource^2 + 4*Xload*Xsource^3)^(1/2) - 2*Q_L*Rload*Rsource - 2*Q_C*Xload*Xsource + 2*Q_C*Q_L*Rload*Xsource))/(2*(Q_C^2 + 1)*(Xload - Xsource - Q_L*Rload + Q_L*Rsource));

 end
Published with MATLAB® R2018a

And below is the MATLAB script (written in large part by Dick Benson, W1QG), using the Symbolic Math Toolbox, that created the four equations, above:

% Script Name:  SymMath_CpLs_from_Qs_and_Zload_3.m

% SYMBOLIC Analysis .... work from Source to Load to get Zin
% Source, Series L then Shunt C , then load

% k6jca: modified w1qg's code, and now use X_C in lieu of B_C

% Make sure the 'syms' line, below is terminated with "real"!
syms Rsource Xsource Rload Xload X_L Q_L X_C Q_C  real

Zseries = (X_L/Q_L + Rload) + 1i*(X_L + Xload); %   Rs = Xs/Q
Zshunt  = (X_C/Q_C) - (1i*X_C);                 %   Rs = Xs/Q
Zin     = 1/(1/Zshunt + 1/Zseries);

eq1   = simplify(real(Zin),'Criterion','preferReal','Steps',50);

eq2   = simplify(imag(Zin),'Criterion','preferReal','Steps',50);

[X_L_Sol, X_C_Sol] = solve([eq1==Rsource,eq2==Xsource],[X_L,X_C]);

XLS= simplify(X_L_Sol,'Steps',50)

XCS= simplify(X_C_Sol,'Steps',50)

% The resulting four equations will appear in MATLAB's
% Command Window, from which they are copied and pasted into
% the script: shunt_C_ser_L_Q_3.m
 
XLS =
 
  (Q_L*(Q_C*Rsource^2 - 2*Rload*Xsource + Q_L*Rsource^2 + Q_C*Xsource^2 + Q_L*Xsource^2 + (- 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource^3 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xsource^2 + 8*Q_C^2*Q_L*Rload*Rsource^2*Xload - 4*Q_C^2*Q_L*Rsource^3*Xload - 4*Q_C^2*Q_L*Rsource*Xload*Xsource^2 + Q_C^2*Rsource^4 - 4*Q_C^2*Rsource^2*Xload^2 + 2*Q_C^2*Rsource^2*Xsource^2 + Q_C^2*Xsource^4 - 8*Q_C*Q_L^2*Rload^2*Rsource*Xsource + 4*Q_C*Q_L^2*Rload*Rsource^2*Xsource + 4*Q_C*Q_L^2*Rload*Xsource^3 - 4*Q_C*Q_L*Rload*Rsource^3 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xsource^2 + 2*Q_C*Q_L*Rsource^4 - 4*Q_C*Q_L*Rsource^2*Xload*Xsource + 4*Q_C*Q_L*Rsource^2*Xsource^2 - 4*Q_C*Q_L*Xload*Xsource^3 + 2*Q_C*Q_L*Xsource^4 + 4*Q_C*Rsource^3*Xload - 8*Q_C*Rsource*Xload^2*Xsource + 4*Q_C*Rsource*Xload*Xsource^2 - 4*Q_L^2*Rload^2*Xsource^2 + Q_L^2*Rsource^4 + 2*Q_L^2*Rsource^2*Xsource^2 + Q_L^2*Xsource^4 - 4*Q_L*Rload*Rsource^2*Xsource + 8*Q_L*Rload*Xload*Xsource^2 - 4*Q_L*Rload*Xsource^3 + 4*Rsource^2*Xload*Xsource - 4*Xload^2*Xsource^2 + 4*Xload*Xsource^3)^(1/2) - 2*Q_C*Rload*Rsource - 2*Q_L*Xload*Xsource - 2*Q_C*Q_L*Rsource*Xload))/(2*(Q_L^2 + 1)*(Xsource + Q_C*Rsource))
 -(Q_L*(2*Rload*Xsource - Q_C*Rsource^2 - Q_L*Rsource^2 - Q_C*Xsource^2 - Q_L*Xsource^2 + (- 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource^3 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xsource^2 + 8*Q_C^2*Q_L*Rload*Rsource^2*Xload - 4*Q_C^2*Q_L*Rsource^3*Xload - 4*Q_C^2*Q_L*Rsource*Xload*Xsource^2 + Q_C^2*Rsource^4 - 4*Q_C^2*Rsource^2*Xload^2 + 2*Q_C^2*Rsource^2*Xsource^2 + Q_C^2*Xsource^4 - 8*Q_C*Q_L^2*Rload^2*Rsource*Xsource + 4*Q_C*Q_L^2*Rload*Rsource^2*Xsource + 4*Q_C*Q_L^2*Rload*Xsource^3 - 4*Q_C*Q_L*Rload*Rsource^3 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xsource^2 + 2*Q_C*Q_L*Rsource^4 - 4*Q_C*Q_L*Rsource^2*Xload*Xsource + 4*Q_C*Q_L*Rsource^2*Xsource^2 - 4*Q_C*Q_L*Xload*Xsource^3 + 2*Q_C*Q_L*Xsource^4 + 4*Q_C*Rsource^3*Xload - 8*Q_C*Rsource*Xload^2*Xsource + 4*Q_C*Rsource*Xload*Xsource^2 - 4*Q_L^2*Rload^2*Xsource^2 + Q_L^2*Rsource^4 + 2*Q_L^2*Rsource^2*Xsource^2 + Q_L^2*Xsource^4 - 4*Q_L*Rload*Rsource^2*Xsource + 8*Q_L*Rload*Xload*Xsource^2 - 4*Q_L*Rload*Xsource^3 + 4*Rsource^2*Xload*Xsource - 4*Xload^2*Xsource^2 + 4*Xload*Xsource^3)^(1/2) + 2*Q_C*Rload*Rsource + 2*Q_L*Xload*Xsource + 2*Q_C*Q_L*Rsource*Xload))/(2*(Q_L^2 + 1)*(Xsource + Q_C*Rsource))
 
 
XCS =
 
 (Q_C*(2*Rsource*Xload + Q_C*Rsource^2 + Q_L*Rsource^2 + Q_C*Xsource^2 + Q_L*Xsource^2 + (- 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource^3 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xsource^2 + 8*Q_C^2*Q_L*Rload*Rsource^2*Xload - 4*Q_C^2*Q_L*Rsource^3*Xload - 4*Q_C^2*Q_L*Rsource*Xload*Xsource^2 + Q_C^2*Rsource^4 - 4*Q_C^2*Rsource^2*Xload^2 + 2*Q_C^2*Rsource^2*Xsource^2 + Q_C^2*Xsource^4 - 8*Q_C*Q_L^2*Rload^2*Rsource*Xsource + 4*Q_C*Q_L^2*Rload*Rsource^2*Xsource + 4*Q_C*Q_L^2*Rload*Xsource^3 - 4*Q_C*Q_L*Rload*Rsource^3 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xsource^2 + 2*Q_C*Q_L*Rsource^4 - 4*Q_C*Q_L*Rsource^2*Xload*Xsource + 4*Q_C*Q_L*Rsource^2*Xsource^2 - 4*Q_C*Q_L*Xload*Xsource^3 + 2*Q_C*Q_L*Xsource^4 + 4*Q_C*Rsource^3*Xload - 8*Q_C*Rsource*Xload^2*Xsource + 4*Q_C*Rsource*Xload*Xsource^2 - 4*Q_L^2*Rload^2*Xsource^2 + Q_L^2*Rsource^4 + 2*Q_L^2*Rsource^2*Xsource^2 + Q_L^2*Xsource^4 - 4*Q_L*Rload*Rsource^2*Xsource + 8*Q_L*Rload*Xload*Xsource^2 - 4*Q_L*Rload*Xsource^3 + 4*Rsource^2*Xload*Xsource - 4*Xload^2*Xsource^2 + 4*Xload*Xsource^3)^(1/2) - 2*Q_L*Rload*Rsource - 2*Q_C*Xload*Xsource + 2*Q_C*Q_L*Rload*Xsource))/(2*(Q_C^2 + 1)*(Xload - Xsource - Q_L*Rload + Q_L*Rsource))
 (Q_C*(2*Rsource*Xload + Q_C*Rsource^2 + Q_L*Rsource^2 + Q_C*Xsource^2 + Q_L*Xsource^2 - (- 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource^3 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xsource^2 + 8*Q_C^2*Q_L*Rload*Rsource^2*Xload - 4*Q_C^2*Q_L*Rsource^3*Xload - 4*Q_C^2*Q_L*Rsource*Xload*Xsource^2 + Q_C^2*Rsource^4 - 4*Q_C^2*Rsource^2*Xload^2 + 2*Q_C^2*Rsource^2*Xsource^2 + Q_C^2*Xsource^4 - 8*Q_C*Q_L^2*Rload^2*Rsource*Xsource + 4*Q_C*Q_L^2*Rload*Rsource^2*Xsource + 4*Q_C*Q_L^2*Rload*Xsource^3 - 4*Q_C*Q_L*Rload*Rsource^3 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xsource^2 + 2*Q_C*Q_L*Rsource^4 - 4*Q_C*Q_L*Rsource^2*Xload*Xsource + 4*Q_C*Q_L*Rsource^2*Xsource^2 - 4*Q_C*Q_L*Xload*Xsource^3 + 2*Q_C*Q_L*Xsource^4 + 4*Q_C*Rsource^3*Xload - 8*Q_C*Rsource*Xload^2*Xsource + 4*Q_C*Rsource*Xload*Xsource^2 - 4*Q_L^2*Rload^2*Xsource^2 + Q_L^2*Rsource^4 + 2*Q_L^2*Rsource^2*Xsource^2 + Q_L^2*Xsource^4 - 4*Q_L*Rload*Rsource^2*Xsource + 8*Q_L*Rload*Xload*Xsource^2 - 4*Q_L*Rload*Xsource^3 + 4*Rsource^2*Xload*Xsource - 4*Xload^2*Xsource^2 + 4*Xload*Xsource^3)^(1/2) - 2*Q_L*Rload*Rsource - 2*Q_C*Xload*Xsource + 2*Q_C*Q_L*Rload*Xsource))/(2*(Q_C^2 + 1)*(Xload - Xsource - Q_L*Rload + Q_L*Rsource))
 

Note that the output from the Symbolic Math appears as four equations in MATLAB's Command Window:


These equations are paired into XL, XC pairs. The first pair is XL(1), XC(1), and the second pair is XL(2), XC(2).  Thus, four different reactances (two inductive, two capacitive) are calculated with these equations.  If a CpLs network configuration exists for Zload, then one and only one of these pairs of reactances will have both of its reactance values "real" (no imaginary component) and "positive".

If neither pair have reactances that are both real and positive, then a CpLs configuration does not exist for the given Zload.


Similarly, below is the MATLAB script to calculate XL and XC values for an LsCp low-pass L-network.  Note that, again, its inputs are Zload, Zsource, Qinductor and Qcapacitor.  The outputs are Xinductor and Xcapacitor.

function [ X_L_Val, X_C_Val ] = ser_L_shunt_C_Q_3(Rload,Xload,Rsource,Xsource,Q_L,Q_C)
close
clc
% Formulas generated using symbolic math contained in the MATLAB script:
% SymMath_LsCp_from_Qs_and_Zload_3.m.

% First, calculating XL.  Note that two values are calculated.
X_L_Val(1) =  -(Q_L*(Q_C*Rload^2 - 2*Rsource*Xload + Q_L*Rload^2 + (4*Q_C^2*Q_L^2*Rload^3*Rsource - 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xload^2 - 4*Q_C^2*Q_L*Rload^3*Xsource + 8*Q_C^2*Q_L*Rload^2*Rsource*Xsource - 4*Q_C^2*Q_L*Rload*Xload^2*Xsource + Q_C^2*Rload^4 + 2*Q_C^2*Rload^2*Xload^2 - 4*Q_C^2*Rload^2*Xsource^2 + Q_C^2*Xload^4 + 4*Q_C*Q_L^2*Rload^2*Rsource*Xload - 8*Q_C*Q_L^2*Rload*Rsource^2*Xload + 4*Q_C*Q_L^2*Rsource*Xload^3 + 2*Q_C*Q_L*Rload^4 - 4*Q_C*Q_L*Rload^3*Rsource + 4*Q_C*Q_L*Rload^2*Xload^2 - 4*Q_C*Q_L*Rload^2*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xload^2 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource + 2*Q_C*Q_L*Xload^4 - 4*Q_C*Q_L*Xload^3*Xsource + 4*Q_C*Rload^3*Xsource + 4*Q_C*Rload*Xload^2*Xsource - 8*Q_C*Rload*Xload*Xsource^2 + Q_L^2*Rload^4 + 2*Q_L^2*Rload^2*Xload^2 - 4*Q_L^2*Rsource^2*Xload^2 + Q_L^2*Xload^4 - 4*Q_L*Rload^2*Rsource*Xload - 4*Q_L*Rsource*Xload^3 + 8*Q_L*Rsource*Xload^2*Xsource + 4*Rload^2*Xload*Xsource + 4*Xload^3*Xsource - 4*Xload^2*Xsource^2)^(1/2) + Q_C*Xload^2 + Q_L*Xload^2 - 2*Q_C*Rload*Rsource - 2*Q_L*Xload*Xsource - 2*Q_C*Q_L*Rload*Xsource))/(2*(Q_L^2 + 1)*(Xload + Q_C*Rload));

X_L_Val(2) =   (Q_L*(2*Rsource*Xload - Q_C*Rload^2 - Q_L*Rload^2 + (4*Q_C^2*Q_L^2*Rload^3*Rsource - 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xload^2 - 4*Q_C^2*Q_L*Rload^3*Xsource + 8*Q_C^2*Q_L*Rload^2*Rsource*Xsource - 4*Q_C^2*Q_L*Rload*Xload^2*Xsource + Q_C^2*Rload^4 + 2*Q_C^2*Rload^2*Xload^2 - 4*Q_C^2*Rload^2*Xsource^2 + Q_C^2*Xload^4 + 4*Q_C*Q_L^2*Rload^2*Rsource*Xload - 8*Q_C*Q_L^2*Rload*Rsource^2*Xload + 4*Q_C*Q_L^2*Rsource*Xload^3 + 2*Q_C*Q_L*Rload^4 - 4*Q_C*Q_L*Rload^3*Rsource + 4*Q_C*Q_L*Rload^2*Xload^2 - 4*Q_C*Q_L*Rload^2*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xload^2 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource + 2*Q_C*Q_L*Xload^4 - 4*Q_C*Q_L*Xload^3*Xsource + 4*Q_C*Rload^3*Xsource + 4*Q_C*Rload*Xload^2*Xsource - 8*Q_C*Rload*Xload*Xsource^2 + Q_L^2*Rload^4 + 2*Q_L^2*Rload^2*Xload^2 - 4*Q_L^2*Rsource^2*Xload^2 + Q_L^2*Xload^4 - 4*Q_L*Rload^2*Rsource*Xload - 4*Q_L*Rsource*Xload^3 + 8*Q_L*Rsource*Xload^2*Xsource + 4*Rload^2*Xload*Xsource + 4*Xload^3*Xsource - 4*Xload^2*Xsource^2)^(1/2) - Q_C*Xload^2 - Q_L*Xload^2 + 2*Q_C*Rload*Rsource + 2*Q_L*Xload*Xsource + 2*Q_C*Q_L*Rload*Xsource))/(2*(Q_L^2 + 1)*(Xload + Q_C*Rload));


% Then, calculating XC.  Note that two values are calculated.
X_C_Val(1) = (Q_C*(2*Rload*Xsource + Q_C*Rload^2 + Q_L*Rload^2 + (4*Q_C^2*Q_L^2*Rload^3*Rsource - 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xload^2 - 4*Q_C^2*Q_L*Rload^3*Xsource + 8*Q_C^2*Q_L*Rload^2*Rsource*Xsource - 4*Q_C^2*Q_L*Rload*Xload^2*Xsource + Q_C^2*Rload^4 + 2*Q_C^2*Rload^2*Xload^2 - 4*Q_C^2*Rload^2*Xsource^2 + Q_C^2*Xload^4 + 4*Q_C*Q_L^2*Rload^2*Rsource*Xload - 8*Q_C*Q_L^2*Rload*Rsource^2*Xload + 4*Q_C*Q_L^2*Rsource*Xload^3 + 2*Q_C*Q_L*Rload^4 - 4*Q_C*Q_L*Rload^3*Rsource + 4*Q_C*Q_L*Rload^2*Xload^2 - 4*Q_C*Q_L*Rload^2*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xload^2 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource + 2*Q_C*Q_L*Xload^4 - 4*Q_C*Q_L*Xload^3*Xsource + 4*Q_C*Rload^3*Xsource + 4*Q_C*Rload*Xload^2*Xsource - 8*Q_C*Rload*Xload*Xsource^2 + Q_L^2*Rload^4 + 2*Q_L^2*Rload^2*Xload^2 - 4*Q_L^2*Rsource^2*Xload^2 + Q_L^2*Xload^4 - 4*Q_L*Rload^2*Rsource*Xload - 4*Q_L*Rsource*Xload^3 + 8*Q_L*Rsource*Xload^2*Xsource + 4*Rload^2*Xload*Xsource + 4*Xload^3*Xsource - 4*Xload^2*Xsource^2)^(1/2) + Q_C*Xload^2 + Q_L*Xload^2 - 2*Q_L*Rload*Rsource - 2*Q_C*Xload*Xsource + 2*Q_C*Q_L*Rsource*Xload))/(2*(Q_C^2 + 1)*(Xload - Xsource - Q_L*Rload + Q_L*Rsource));

X_C_Val(2) = (Q_C*(2*Rload*Xsource + Q_C*Rload^2 + Q_L*Rload^2 - (4*Q_C^2*Q_L^2*Rload^3*Rsource - 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xload^2 - 4*Q_C^2*Q_L*Rload^3*Xsource + 8*Q_C^2*Q_L*Rload^2*Rsource*Xsource - 4*Q_C^2*Q_L*Rload*Xload^2*Xsource + Q_C^2*Rload^4 + 2*Q_C^2*Rload^2*Xload^2 - 4*Q_C^2*Rload^2*Xsource^2 + Q_C^2*Xload^4 + 4*Q_C*Q_L^2*Rload^2*Rsource*Xload - 8*Q_C*Q_L^2*Rload*Rsource^2*Xload + 4*Q_C*Q_L^2*Rsource*Xload^3 + 2*Q_C*Q_L*Rload^4 - 4*Q_C*Q_L*Rload^3*Rsource + 4*Q_C*Q_L*Rload^2*Xload^2 - 4*Q_C*Q_L*Rload^2*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xload^2 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource + 2*Q_C*Q_L*Xload^4 - 4*Q_C*Q_L*Xload^3*Xsource + 4*Q_C*Rload^3*Xsource + 4*Q_C*Rload*Xload^2*Xsource - 8*Q_C*Rload*Xload*Xsource^2 + Q_L^2*Rload^4 + 2*Q_L^2*Rload^2*Xload^2 - 4*Q_L^2*Rsource^2*Xload^2 + Q_L^2*Xload^4 - 4*Q_L*Rload^2*Rsource*Xload - 4*Q_L*Rsource*Xload^3 + 8*Q_L*Rsource*Xload^2*Xsource + 4*Rload^2*Xload*Xsource + 4*Xload^3*Xsource - 4*Xload^2*Xsource^2)^(1/2) + Q_C*Xload^2 + Q_L*Xload^2 - 2*Q_L*Rload*Rsource - 2*Q_C*Xload*Xsource + 2*Q_C*Q_L*Rsource*Xload))/(2*(Q_C^2 + 1)*(Xload - Xsource - Q_L*Rload + Q_L*Rsource));

end
Published with MATLAB® R2018a

And below is the MATLAB script (written in large part by Dick Benson, W1QG), using the Symbolic Math Toolbox, that created the four equations, above:

% Script Name:  SymMath_LsCp_from_Qs_and_Zload_3.m

% SYMBOLIC Analysis .... work from Source to Load to get Zin
% Source, Series L then Shunt C , then load

% This version uses X_C instead of B_C (modified by k6jca)

% Make sure the 'syms' line, below is terminated with "real"!
syms Rsource Xsource Rload Xload X_L Q_L X_C Q_C  real

Zshunt =  1/(1/(X_C/Q_C - (1i*X_C)) + 1/((Rload + 1i*Xload))); % Rs = Xs/Q
Zin = X_L/Q_L + 1i*X_L + Zshunt;


eq1 = simplify(real(Zin),'Criterion','preferReal','Steps',50);

eq2 = simplify(imag(Zin),'Criterion','preferReal','Steps',50);

[X_L_Sol, X_C_Sol] = solve([eq1==Rsource,eq2==Xsource],[X_L,X_C]);

XLS = simplify(X_L_Sol,'Steps',50)

XCS = simplify(X_C_Sol,'Steps',50)

% The resulting four equations will appear in MATLAB's
% Command Window, from which they are copied and then
% pasted into the script: ser_L_shunt_C_Q_3.m
XLS =
 
 -(Q_L*(Q_C*Rload^2 - 2*Rsource*Xload + Q_L*Rload^2 + (4*Q_C^2*Q_L^2*Rload^3*Rsource - 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xload^2 - 4*Q_C^2*Q_L*Rload^3*Xsource + 8*Q_C^2*Q_L*Rload^2*Rsource*Xsource - 4*Q_C^2*Q_L*Rload*Xload^2*Xsource + Q_C^2*Rload^4 + 2*Q_C^2*Rload^2*Xload^2 - 4*Q_C^2*Rload^2*Xsource^2 + Q_C^2*Xload^4 + 4*Q_C*Q_L^2*Rload^2*Rsource*Xload - 8*Q_C*Q_L^2*Rload*Rsource^2*Xload + 4*Q_C*Q_L^2*Rsource*Xload^3 + 2*Q_C*Q_L*Rload^4 - 4*Q_C*Q_L*Rload^3*Rsource + 4*Q_C*Q_L*Rload^2*Xload^2 - 4*Q_C*Q_L*Rload^2*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xload^2 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource + 2*Q_C*Q_L*Xload^4 - 4*Q_C*Q_L*Xload^3*Xsource + 4*Q_C*Rload^3*Xsource + 4*Q_C*Rload*Xload^2*Xsource - 8*Q_C*Rload*Xload*Xsource^2 + Q_L^2*Rload^4 + 2*Q_L^2*Rload^2*Xload^2 - 4*Q_L^2*Rsource^2*Xload^2 + Q_L^2*Xload^4 - 4*Q_L*Rload^2*Rsource*Xload - 4*Q_L*Rsource*Xload^3 + 8*Q_L*Rsource*Xload^2*Xsource + 4*Rload^2*Xload*Xsource + 4*Xload^3*Xsource - 4*Xload^2*Xsource^2)^(1/2) + Q_C*Xload^2 + Q_L*Xload^2 - 2*Q_C*Rload*Rsource - 2*Q_L*Xload*Xsource - 2*Q_C*Q_L*Rload*Xsource))/(2*(Q_L^2 + 1)*(Xload + Q_C*Rload))
  (Q_L*(2*Rsource*Xload - Q_C*Rload^2 - Q_L*Rload^2 + (4*Q_C^2*Q_L^2*Rload^3*Rsource - 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xload^2 - 4*Q_C^2*Q_L*Rload^3*Xsource + 8*Q_C^2*Q_L*Rload^2*Rsource*Xsource - 4*Q_C^2*Q_L*Rload*Xload^2*Xsource + Q_C^2*Rload^4 + 2*Q_C^2*Rload^2*Xload^2 - 4*Q_C^2*Rload^2*Xsource^2 + Q_C^2*Xload^4 + 4*Q_C*Q_L^2*Rload^2*Rsource*Xload - 8*Q_C*Q_L^2*Rload*Rsource^2*Xload + 4*Q_C*Q_L^2*Rsource*Xload^3 + 2*Q_C*Q_L*Rload^4 - 4*Q_C*Q_L*Rload^3*Rsource + 4*Q_C*Q_L*Rload^2*Xload^2 - 4*Q_C*Q_L*Rload^2*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xload^2 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource + 2*Q_C*Q_L*Xload^4 - 4*Q_C*Q_L*Xload^3*Xsource + 4*Q_C*Rload^3*Xsource + 4*Q_C*Rload*Xload^2*Xsource - 8*Q_C*Rload*Xload*Xsource^2 + Q_L^2*Rload^4 + 2*Q_L^2*Rload^2*Xload^2 - 4*Q_L^2*Rsource^2*Xload^2 + Q_L^2*Xload^4 - 4*Q_L*Rload^2*Rsource*Xload - 4*Q_L*Rsource*Xload^3 + 8*Q_L*Rsource*Xload^2*Xsource + 4*Rload^2*Xload*Xsource + 4*Xload^3*Xsource - 4*Xload^2*Xsource^2)^(1/2) - Q_C*Xload^2 - Q_L*Xload^2 + 2*Q_C*Rload*Rsource + 2*Q_L*Xload*Xsource + 2*Q_C*Q_L*Rload*Xsource))/(2*(Q_L^2 + 1)*(Xload + Q_C*Rload))
 
 
XCS =
 
 (Q_C*(2*Rload*Xsource + Q_C*Rload^2 + Q_L*Rload^2 + (4*Q_C^2*Q_L^2*Rload^3*Rsource - 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xload^2 - 4*Q_C^2*Q_L*Rload^3*Xsource + 8*Q_C^2*Q_L*Rload^2*Rsource*Xsource - 4*Q_C^2*Q_L*Rload*Xload^2*Xsource + Q_C^2*Rload^4 + 2*Q_C^2*Rload^2*Xload^2 - 4*Q_C^2*Rload^2*Xsource^2 + Q_C^2*Xload^4 + 4*Q_C*Q_L^2*Rload^2*Rsource*Xload - 8*Q_C*Q_L^2*Rload*Rsource^2*Xload + 4*Q_C*Q_L^2*Rsource*Xload^3 + 2*Q_C*Q_L*Rload^4 - 4*Q_C*Q_L*Rload^3*Rsource + 4*Q_C*Q_L*Rload^2*Xload^2 - 4*Q_C*Q_L*Rload^2*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xload^2 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource + 2*Q_C*Q_L*Xload^4 - 4*Q_C*Q_L*Xload^3*Xsource + 4*Q_C*Rload^3*Xsource + 4*Q_C*Rload*Xload^2*Xsource - 8*Q_C*Rload*Xload*Xsource^2 + Q_L^2*Rload^4 + 2*Q_L^2*Rload^2*Xload^2 - 4*Q_L^2*Rsource^2*Xload^2 + Q_L^2*Xload^4 - 4*Q_L*Rload^2*Rsource*Xload - 4*Q_L*Rsource*Xload^3 + 8*Q_L*Rsource*Xload^2*Xsource + 4*Rload^2*Xload*Xsource + 4*Xload^3*Xsource - 4*Xload^2*Xsource^2)^(1/2) + Q_C*Xload^2 + Q_L*Xload^2 - 2*Q_L*Rload*Rsource - 2*Q_C*Xload*Xsource + 2*Q_C*Q_L*Rsource*Xload))/(2*(Q_C^2 + 1)*(Xload - Xsource - Q_L*Rload + Q_L*Rsource))
 (Q_C*(2*Rload*Xsource + Q_C*Rload^2 + Q_L*Rload^2 - (4*Q_C^2*Q_L^2*Rload^3*Rsource - 4*Q_C^2*Q_L^2*Rload^2*Rsource^2 + 4*Q_C^2*Q_L^2*Rload*Rsource*Xload^2 - 4*Q_C^2*Q_L*Rload^3*Xsource + 8*Q_C^2*Q_L*Rload^2*Rsource*Xsource - 4*Q_C^2*Q_L*Rload*Xload^2*Xsource + Q_C^2*Rload^4 + 2*Q_C^2*Rload^2*Xload^2 - 4*Q_C^2*Rload^2*Xsource^2 + Q_C^2*Xload^4 + 4*Q_C*Q_L^2*Rload^2*Rsource*Xload - 8*Q_C*Q_L^2*Rload*Rsource^2*Xload + 4*Q_C*Q_L^2*Rsource*Xload^3 + 2*Q_C*Q_L*Rload^4 - 4*Q_C*Q_L*Rload^3*Rsource + 4*Q_C*Q_L*Rload^2*Xload^2 - 4*Q_C*Q_L*Rload^2*Xload*Xsource - 4*Q_C*Q_L*Rload*Rsource*Xload^2 + 16*Q_C*Q_L*Rload*Rsource*Xload*Xsource + 2*Q_C*Q_L*Xload^4 - 4*Q_C*Q_L*Xload^3*Xsource + 4*Q_C*Rload^3*Xsource + 4*Q_C*Rload*Xload^2*Xsource - 8*Q_C*Rload*Xload*Xsource^2 + Q_L^2*Rload^4 + 2*Q_L^2*Rload^2*Xload^2 - 4*Q_L^2*Rsource^2*Xload^2 + Q_L^2*Xload^4 - 4*Q_L*Rload^2*Rsource*Xload - 4*Q_L*Rsource*Xload^3 + 8*Q_L*Rsource*Xload^2*Xsource + 4*Rload^2*Xload*Xsource + 4*Xload^3*Xsource - 4*Xload^2*Xsource^2)^(1/2) + Q_C*Xload^2 + Q_L*Xload^2 - 2*Q_L*Rload*Rsource - 2*Q_C*Xload*Xsource + 2*Q_C*Q_L*Rsource*Xload))/(2*(Q_C^2 + 1)*(Xload - Xsource - Q_L*Rload + Q_L*Rsource))
 


L-Network Designer:
With these functions I created my own L-Network Designer script in MATLAB:

% k6jca
% L-Network Designer:  Determines L and C and
% Lowpass L-network Configuration (LsCp or CpLs)
% Given Zsource, Zload, QL, QC, and Frequency.

clear all
close all
clc

Zo = 50;

% Inputs (F, Rsource, Xsource, Q_L, Q_C, Rload,Xload)
F  = 3.5e6;   % Frequency (Hz)
Rs  = Zo;     % Rsource (most likely this will be 50 ohms)
Xs  = 0;      % Xsource (most likely this will be 0)
QL  = 100;    % inductor Q
QC  = 100;    % capacitor Q
Rld = 16.47;  % Rload
Xld = 74.46;  % Xload
% Rld = 7.079;  % Rload
% Xld = -32.01; % Xload

w     = 2*pi*F;
Zs    = Rs + 1i*Xs;   % source impedance
Zload = Rld + 1i*Xld;  % load impedance

% Given Zload, Zsource (which is 50 ohms here), Ql and Qc,
% calculate the XL and XC values of the LsCp or CpLs
% network than will match Zload to Zsource.
%
% Note that for an LsCp network, two XL and two XC terms
% are returned for each load.  Ditto for the CpLs network.
% (Note that the equations in the called functions were
% derived by MATLAB using symbolic math).
[LsCp_XL, LsCp_XC] = ser_L_shunt_C_Q_3(Rld,Xld,Rs,Xs,QL,QC);
[CpLs_XL, CpLs_XC] = shunt_C_ser_L_Q_3(Rld,Xld,Rs,Xs,QL,QC);

% of the four pairs of XL and XC terms returnd by the
% functions(each function call returns two pairs), but
% only one pair is valid.  This pair will have
% no imaginary components (that is, neither XL or XC is a
% complex number)and both XL and XC will be positive.
%
% So let's first check each XL and each XC and identify
% which of these are real (not complex) and positive.
if(isreal(LsCp_XL(1)) && real(LsCp_XL(1)) > 0)
    itsValid(1) = 1;
else
    itsValid(1) = 0;
end

if(isreal(LsCp_XL(2)) && real(LsCp_XL(2)) > 0)
    itsValid(2) = 1;
else
    itsValid(2) = 0;
end

if(isreal(LsCp_XC(1)) && real(LsCp_XC(1)) > 0)
    itsValid(3) = 1;
else
    itsValid(3) = 0;
end

if(isreal(LsCp_XC(2)) && real(LsCp_XC(2)) > 0)
    itsValid(4) = 1;
else
    itsValid(4) = 0;
end

if(isreal(CpLs_XL(1)) && real(CpLs_XL(1)) > 0)
    itsValid(5) = 1;
else
    itsValid(5) = 0;
end

if(isreal(CpLs_XL(2)) && real(CpLs_XL(2)) > 0)
    itsValid(6) = 1;
else
    itsValid(6) = 0;
end

if(isreal(CpLs_XC(1)) && real(CpLs_XC(1)) > 0)
    itsValid(7) = 1;
else
    itsValid(7) = 0;
end

if(isreal(CpLs_XC(2)) && real(CpLs_XC(2)) > 0)
    itsValid(8) = 1;
else
    itsValid(8) = 0;
end

% Next, we are looking for "pairs" of XL and XC that
% are valid. Only one pair should be valid.  The other
% three pairs should be invalid.
% For example, the first check below will be to check
% XL(1) and XC(1) for LsCp networks and see if
% these values are both valid.
if(itsValid(1) && itsValid(3))
    Lnet_id = 'LsCp'
    XL = LsCp_XL(1);
    XC = LsCp_XC(1);
elseif(itsValid(2) && itsValid(4)) % XL(2),XC(2),LsCp netwrk
    Lnet_id = 'LsCp'
    XL = LsCp_XL(2);
    XC = LsCp_XC(2);
elseif(itsValid(5) && itsValid(7)) % XL(1),XC(1),CpLs netwrk
    Lnet_id = 'CpLs'
    XL = CpLs_XL(1);
    XC = CpLs_XC(1);
elseif(itsValid(6) && itsValid(8)) % XL(2),XC(2),CpLs netwrk
    Lnet_id = 'CpLs'
    XL = CpLs_XL(2);
    XC = CpLs_XC(2);
else
    % if there are no valid pairs (which OUGHT NOT OCCUR...
    Lnet_id = 'None!'  % just flag there's a problem.
    disp('huh?');
end

% from XL and XC, calculate Ls and Cp
Ls = XL/w
Cp = 1/(XC*w)

% and calculate the S-parameters based upon whether the
% valid pair is for an LsCp network or for a CpLs network...
if(Lnet_id == 'LsCp')
    Spar = S_LsCp(Ls,QL,Cp,QC, Zo, F);
else
    Spar = S_CpLs(Ls,QL,Cp,QC, Zo, F);
end

% With these, calculate network power loss
Gp_Lnet = powergain(Spar,Zo,Zload,'Gp')
Gp_dBLoss = 10*log10(Gp_Lnet);
Gp_Percent_Loss = (1-Gp_Lnet)*100
Lnet_id =

    'LsCp'


Ls =

   5.3255e-06


Cp =

   9.1308e-10


Gp_Lnet =

    0.9119


Gp_Percent_Loss =

    8.8073


Note that my MATLAB script uses the following two functions, written by Dick Benson, W1QG, that create S-parameters for the LsCp and CpLs L-networks:

function S_LsCp():
function S = S_LsCp(L, Ql, C, Qc, Zo, f )
 % Written by W1QG
 % From Symbolc Math in S_Parameters_for_L_Networks.m results.
 % S Parameters for LsCp configuration.
 w=2*pi*f;
 dxx=(Ql*Zo*2i + L*w*1i + 2*Qc*Ql*Zo + L*Qc*w - L*Ql*w + L*Qc*Ql*w*1i + C*L*Qc*Zo*w^2*1i + C*Qc*Ql*Zo^2*w*1i - C*L*Qc*Ql*Zo*w^2);
 S11_LsCp =  (w*(L*1i + L*Qc - L*Ql + L*Qc*Ql*1i - C*Qc*Ql*Zo^2*1i + C*L*Qc*Zo*w*1i - C*L*Qc*Ql*Zo*w))/ dxx;
 S12_LsCp =  -(Ql*Zo*(Qc + 1i)*2i)/   (2*Ql*Zo + L*w - Qc*Ql*Zo*2i - L*Qc*w*1i + L*Ql*w*1i + L*Qc*Ql*w + C*L*Qc*Zo*w^2 + C*Qc*Ql*Zo^2*w + C*L*Qc*Ql*Zo*w^2*1i);
% S21_LsCp =  -(2*Ql*Zo*(- 1 + Qc*1i))/(2*Ql*Zo + L*w - Qc*Ql*Zo*2i - L*Qc*w*1i + L*Ql*w*1i + L*Qc*Ql*w + C*L*Qc*Zo*w^2 + C*Qc*Ql*Zo^2*w + C*L*Qc*Ql*Zo*w^2*1i);
 S21_LsCp = S12_LsCp;
 S22_LsCp = (w*(L*1i + L*Qc - L*Ql + L*Qc*Ql*1i - C*Qc*Ql*Zo^2*1i - C*L*Qc*Zo*w*1i + C*L*Qc*Ql*Zo*w))/dxx;
 S = [S11_LsCp,S12_LsCp; S21_LsCp,S22_LsCp];
end
Published with MATLAB® R2018a
function S_CpLs():
function S = S_CpLs(L, Ql, C, Qc, Zo, f )
 % Written by W1QG
 % From Symbolc Math in S_Parameters_for_L_Networks.m results.
 % S Parameters for CpLs configuration.
 w=2*pi*f;
 dxx =  (Ql*Zo*2i + L*w*1i + 2*Qc*Ql*Zo + L*Qc*w - L*Ql*w + L*Qc*Ql*w*1i + C*L*Qc*Zo*w^2*1i + C*Qc*Ql*Zo^2*w*1i - C*L*Qc*Ql*Zo*w^2);
 S11_CpLs =     (w*(L*1i + L*Qc - L*Ql + L*Qc*Ql*1i - C*Qc*Ql*Zo^2*1i - C*L*Qc*Zo*w*1i + C*L*Qc*Ql*Zo*w))/dxx;
 S22_CpLs =     (w*(L*1i + L*Qc - L*Ql + L*Qc*Ql*1i - C*Qc*Ql*Zo^2*1i + C*L*Qc*Zo*w*1i - C*L*Qc*Ql*Zo*w))/dxx;
 S12_CpLs =    -(2*Ql*Zo*(- 1 + Qc*1i))/(2*Ql*Zo + L*w - Qc*Ql*Zo*2i - L*Qc*w*1i + L*Ql*w*1i + L*Qc*Ql*w + C*L*Qc*Zo*w^2 + C*Qc*Ql*Zo^2*w + C*L*Qc*Ql*Zo*w^2*1i);
 % S21_CpLs =  -(2*Ql*Zo*(- 1 + Qc*1i))/(2*Ql*Zo + L*w - Qc*Ql*Zo*2i - L*Qc*w*1i + L*Ql*w*1i + L*Qc*Ql*w + C*L*Qc*Zo*w^2 + C*Qc*Ql*Zo^2*w + C*L*Qc*Ql*Zo*w^2*1i)
 S21_CpLs=S12_CpLs;
 S = [S11_CpLs, S12_CpLs; S21_CpLs,S22_CpLs];
end
Published with MATLAB® R2018a

Conclusion:

This post presents low-pass L-network design equations that include component loss.

These equations were derived using MATLAB's Symbolic Math Toolbox, which provides a powerful tool for generating equations that might be too complex for mere pencil-and-paper derivation using standard Circuit Analysis techniques.

A similar technique can be used to derive lossy L-network design equations for other L-network configurations (e.g. high-pass LpCs, CsLp, etc.).  I would encourage the interested reader to do so!

Antenna Tuner Blog Posts:

A quick tutorial on Smith Chart basics:
http://k6jca.blogspot.com/2015/03/a-brief-tutorial-on-smith-charts.html

The L-network:
http://k6jca.blogspot.com/2015/03/notes-on-antenna-tuners-l-network-and.html

A correction to the usual L-network design constraints:
http://k6jca.blogspot.com/2015/04/revisiting-l-network-equations-and.html

Calculating L-Network values when the components are lossy:
http://k6jca.blogspot.com/2018/09/l-networks-new-equations-for-better.html

A look at highpass T-Networks:
http://k6jca.blogspot.com/2015/04/notes-on-antenna-tuners-t-network-part-1.html

More on the W8ZR EZ-Tuner:
http://k6jca.blogspot.com/2015/05/notes-on-antenna-tuners-more-on-w8zr-ez.html  (Note that this tuner is also discussed in the highpass T-Network post).

The Elecraft KAT-500:
http://k6jca.blogspot.com/2015/05/notes-on-antenna-tuners-elecraft-kat500.html

The Nye Viking MB-V-A tuner and the Rohde Coupler:
http://k6jca.blogspot.com/2015/05/notes-on-antenna-tuners-nye-viking-mb-v.html

The Drake MN-4 Tuner:
http://k6jca.blogspot.com/2018/08/notes-on-antenna-tuners-drake-mn-4.html



Standard Caveat:

As always, I might have made a mistake in my equations, assumptions, drawings, or interpretations.  If you see anything you believe to be in error or if anything is confusing, please feel free to contact me or comment below.

And so I should add -- this information is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Wednesday, August 29, 2018

Notes on Antenna Tuners: Determining a Tuner's "Match-Space"


Tuner Performance:  Measuring a Tuner's "Match Space":

Any Antenna Tuner worth its salt should transform a wide range of impedances connected to its Output Port (i.e. its Antenna Port) to 50 ohms (i.e. 1:1 SWR at its Input (Transmitter) Port).

An obvious question is -- what is the actual range of impedances that a specific tuner can match?

It is relatively straight forward to measure these impedances if one has a Vector Network Analyzer (VNA) and to plot them on a Smith Chart.  The resulting region of matchable impedances I call a tuner's "Match Space".

In other words, the "Match Space" is an area on a Smith Chart encompassing the range of impedances that a tuner can transform to 50 + j0 ohms at its input port.

How do we determine what these impedances are?  Do I need a box full of resistors, capacitors, and inductors to connect to the tuner's output and test each combination?

A little network theory...

Assume a two-port lossless network with an impedance of unknown value, Z(unknown), attached to its output port, and assume that the network has been "tuned" so that Z(unknown) is transformed to 50 + j0 ohms when measured at the network's input port.
(Note:  no network is truly "lossless," and I will discuss the effect of loss on these measurements at the end of this blog post.  But let us assume for the moment that the network loss is significantly less than the load's power dissipation/radiation so that the above statement is, essentially, true.)
If I then connect a 50 + j0 load to the network's input port and remove Z(unknown) from the output port, the impedance I measure at the network's output port will be the complex-conjugate of the original Z(unknown) impedance.


So, to determine a tuner's "Match Space", all I need to do is to terminate the tuner's input with 50 + j0 ohms and then, while continuously adjusting the tuner's controls, plot the complex-conjugates of the impedances I measure at the tuner's output.

An ideal task for a Vector Network Analyzer!


Finding a Tuner's Match-Space Using the Complex-Conjugate Method:

Equipment and Software:

To make match-space measurements I use the following equipment and software:
  1. An HP 8753C Vector Network Analyzer (VNA) and an HP 85046A S-Parameter Test Set.
  2. An Agilent 82357B USB/GPIB Interface Module, to interface a computer to the VNA.
  3. A recent version of MATLAB, with the following toolboxes:  1) RF Toolbox, 2) Instrument Control Toolbox.
In addition, I use a MATLAB script (vna_s11_tracks.m) written by Dick Benson, W1QG, to plot the match-space on a Smith Chart.


Measurement Procedure:
  1. Connect an accurate 50 ohm reference load to the Tuner's input port (i.e. Transmitter port).
  2. Launch the MATLAB script vna_s11_tracks.m, but do not yet click its RUN_STOP button on its GUI.
  3. At the VNA set Center Frequency to the desired measurement frequency.
  4. At the VNA set Span to 0 Hz.
  5. At the VNA set Number of Points to 3 (under MENU button in the "Stimulus" button group) for the 8753C).  Default is 201 points.
  6. Perform an S11 open-short-load calibration on the end of the coax that will attach to the Tuner's output port (i.e. antenna port).  Note that the other end of this coax should already be connected to Port 1 of the S-Parameter Test Set.
  7. After calibrating, re-attach the "open" reference load to the same end of the coax that had been calibrated in step 4, above.
  8. Click on the RUN-STOP button.  (The STATUS box on the GUI should say "RUN".)
  9. Verify that a small red square outline appears exactly at the 3 o'clock position of the GUI's Smith Chart.  If it is there, then the VNA has been calibrated correctly.  If it is somewhere else on the Smith Chart, you have done something wrong.  Repeat the calibration steps, above.
  10. Click on the GUI's RUN_STOP button to stop the script.  Remove the "open" reference load from the coax and instead attach the coax to the Tuner's output port.
  11. Click RUN_STOP again and start capturing data, per either the first or second method of plotting, discussed below...
Plotting the Match Space:

For a Tuner (or other two-port network) having two variable controls, I can use the MATLAB script to plot the "Match Space" one of two ways.

The first method is the fastest, and it simply traces the outline of the match-space by sequentially holding one of the two controls fixed while rotating the other control.

In other words, say a tuner has two controls (control A and control B), this method's steps would be:
  1. Place both controls at their maximum counter-clockwise (CCW) position.
  2. With control B fixed at its counter-clockwise position and rotate control A from CCW to its maximum clockwise (CW) position.
  3. With control A now at its maximum CW position, rotate control B from its CCW position to its maximum CW position.
  4. With both controls now at their maximum CW positions, rotate control A from its CW position to its maximum CCW position.
  5. And finally, rotate control B from its CW position to its maximum CCW position.
An example of an outline-plot of a match-space, made using this method, is shown below:


(Note that Dick's MATLAB script allows the user to assign a different color to each of the steps in steps 2 through 5.  I've defined the color assignments in the comment-box at the lower left of the figure.)

An Important Caveat!  This procedure will accurately trace the outline of a Tuner's match space in most cases.  But not always!  If in doubt, then one can use a second, more time-consuming method:

Again, assuming a tuner has two controls (A and B), this second method's steps would be:
  1. Place both controls at their maximum counter-clockwise (CCW) position.
  2. With control B fixed at its maximum counter-clockwise position and rotate control A from CCW to its maximum clockwise (CW) position and back again.
  3. Rotate control B very slightly clockwise.
  4. Again, rotate control A from its CCW position to its maximum clockwise (CW) position and back again.
  5. Repeat steps 3 and 4 until control B is finally at its maximum CW position and control A has been rotated CCW and back again.
Here is an example of a plot made using this method:


In the example above (using an Icom AT-500 Tuner), I stepped one control through 14 positions, and at each step of the first control position I rotated the other control fully clockwise and then counter-clockwise back again.

This second method is much more time consuming to perform, but it can reveal information that might be missed if  one simply traced the match-space outline using the first method.  For example, below is the match-space outline (using the first technique) overlayed on the second method's plot:


Comparing the two plots, you can see that method 1 missed some of the match-space:


Also, if you examine method 2's plots, you will see that the same match-space area missed by method 1 actually has more than one unique Tuner setting for the load impedances in that region.

For example, in the figure, below, note the intersection of two different curves.  This means that the impedance represented by the Smith Chart at this intersection can be matched with two different tuner settings.


And therefore, because the entire region, above (missed by method 1) actually consists of overlapping curves, the impedances in that entire region can be each matched by two different tuner settings.

Note:  This result does not mean that, in the general case, any area missed by the method 1 (and caught by method 2) can actually be matched by multiple tuner setting.  But for this specific example, it does.


Effect of Network Loss on Match-Space Measurements:

As I mentioned earlier in this post, the Match-Space can be found by terminating the network's input port with 50 ohms and measuring the transformed-impedance at the network's output port.  This impedance represents the complex-conjugate of a load impedance that, when attached to the network's output port, will appear as 50 ohms at the network's input port.

But this relationship is only true if the network is lossless.  If the network has loss, there will be error introduced into this complex-conjugate impedance measurement.

Let's look at this error with respect to my Drake MN-4 measurements.

When I measured the tuner's power loss with different loads, I also measured the complex-conjugate of the impedance seen at the tuner's output port when its input was terminated with 50 ohms.

If there were no loss, the impedance I measure should be the same as the original load impedance I had used to make the power-loss measurement.  For example, if I had tuned the tuner to match a load of 150 ohms, then, when I removed the load and attached 50 ohms to the tuner's input port, the measured impedance at the output port should also be 150 ohms.

But I measure a different value.  And it turns out that the greater the network power loss, the greater will be the difference between the actual load value (used for power-loss measurements) and the load value calculated via the complex-conjugate method.

Here's a table containing both the network loss for different loads and the impedance measured at the output port using the complex-conjugate method when the input was terminated with 50 ohms:


(Note the yellow rows -- these are load impedances that I could not tune to 1:1 SWR).

There's a significant difference between the complex-conjugate measurement and the actual load value.  And as you can see, the greater the loss, the greater the error.

Let's explore further, using MATLAB...


Using MATLAB to Examine Loss Effects on Match Space Plots:

How does network loss affect the Drake MN-4's match-space at 3.5 MHz?

Here's the original MN-4 match-space plot made at 3.5 MHz with my VNA:


Next, I will create a model of the tuner in MATLAB to be the basis for my experiments.  But I first must ensure that the model I've created gives me results similar to the plot I made with my physical MN-4 tuner.

I will start with a model using Drake's schematic values for C5-C12 and calculating L2 and L3 to be 9.88 uH and 0.225 uH, respectively (from their dimensions and number of turns).

Matlab will calculate the resulting match-space outline using the complex-conjugate method -- placing 50 ohms at the input of the model and, while stepping through the model's two control settings, calculating the complex-conjugate of the impedance measured at the network's output.

MATLAB's resulting match-space plot of this model looks like this:


This plot is a far cry from my tuner's actual measurements!

This difference is probably due to the actual component values differing from those shown in the schematic, as well as effects caused by parasitic inductance, capacitance, and loss resistance.

Let's play with the component values (and add some network loss, too).  After jiggling them around for a bit, here's a better MATLAB match-space outline:


This new MATLAB plot is much closer to my measured plot.

And below is the circuit, with component values, that I used to generate this plot:


Caveat!  The values I selected might not accurately represent the tuner's actual component values. I chose these values because they generated a plot at 3.5 MHz similar to the one I measured. But other component values might generate a plot that is similar or even more accurate.  Do not assume the values I've chosen reflect the actual values that are in the MN-4 tuner.

OK!  Now that I've created a MATLAB model that seems to represent actual tuner performance, let's use it to run some experiments...

Let's compare the match-space with and without tuner loss (the loss model uses the resistance values from the schematic, above, while the lossless model sets all resistances to 0 ohms):


Note:  the slightly darker colors outline the match-space of the lossless network.

You can see that adding loss to the network both shrinks the match-space outline and shifts it to the right, compared to the lossless match-space outline.

But which of these two curves is closer to predicting the actual load impedances that can be matched to a 1:1 SWR?

I'll run another MATLAB experiment.  This time MATLAB will step each of the model's two tuner controls, one at a time, exactly as I would have stepped the tuning controls on a real tuner to plot the match-space outline manually.  At each incremental step, the MATLAB script will iterate through a range of load impedances, searching for an actual impedance that will give the closest match to a 1:1 SWR for those settings of the model tuner.

In other words, for every tiny change in the tuner's setting, I will search for a load impedance that transforms exactly (or almost exactly) to 50 ohms, when measured at the tuner's input port.

I've added this new plot to the figure below.


(Note: the MATLAB script uses my "jiggled" component values (that include network loss) as the Tuner's components).

The left-most outline represents actual loads that tune to 1:1 SWR, while the right-most outline represents the match-space found by terminating the input with 50 ohms and measuring the complex-conjugate of the impedance at the network's output port.

Let's remove the "lossless" plot...


Note the significant difference between the two remaining outlines.  The match-space outline representing the load impedances the tuner can actually match to a 1:1 SWR is significantly different from the match-space outline found via the "conjugate-match" method described earlier in this post.

This difference is due to loss within the network!

As a sanity check of my MATLAB model, let's see what happens to the three outlines as I reduce network loss.  The differences between the three outlines should become smaller.  To check this, I'll change all of the loss resistances to 0.2 ohms (from the values I used in the schematic, above).

Here's the plot of the three outlines with the reduced loss resistances:


Note that the three outlines are now much closer together, and they are almost coincident with the middle "lossless" outline.  If loss were reduced to zero, the three outlines would be exactly coincident.


Conclusion, the Effect of Loss on Network Match-Space Measurements:

If a two-port network has low loss, the "complex-conjugate" method (described above) can generate a fairly accurate representation of the network's match-space.  But as tuner loss increases, the loads represented by the match-space generated using the complex-conjugate method will diverge further and further from the loads that actually can be matched to a 1:1 SWR.

In other words, when measuring a network's match-space using the complex-conjugate method, be sure to also measure network power loss in order to judge how accurate your results might be.

(Note that network power-loss can be measured using the method described in the link, below:


Antenna Tuner Blog Posts:

A quick tutorial on Smith Chart basics:
http://k6jca.blogspot.com/2015/03/a-brief-tutorial-on-smith-charts.html

The L-network:
http://k6jca.blogspot.com/2015/03/notes-on-antenna-tuners-l-network-and.html

A correction to the usual L-network design constraints:
http://k6jca.blogspot.com/2015/04/revisiting-l-network-equations-and.html

Calculating L-Network values when the components are lossy:
http://k6jca.blogspot.com/2018/09/l-networks-new-equations-for-better.html

A look at highpass T-Networks:
http://k6jca.blogspot.com/2015/04/notes-on-antenna-tuners-t-network-part-1.html

More on the W8ZR EZ-Tuner:
http://k6jca.blogspot.com/2015/05/notes-on-antenna-tuners-more-on-w8zr-ez.html  (Note that this tuner is also discussed in the highpass T-Network post).

The Elecraft KAT-500:
http://k6jca.blogspot.com/2015/05/notes-on-antenna-tuners-elecraft-kat500.html

The Nye Viking MB-V-A tuner and the Rohde Coupler:
http://k6jca.blogspot.com/2015/05/notes-on-antenna-tuners-nye-viking-mb-v.html

The Drake MN-4 Tuner:
http://k6jca.blogspot.com/2018/08/notes-on-antenna-tuners-drake-mn-4.html


Standard Caveat:

As always, I might have made a mistake in my equations, assumptions, drawings, or interpretations.  If you see anything you believe to be in error or if anything is confusing, please feel free to contact me or comment below.

And so I should add -- this information is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.