Skip to content

Commit 50bde26

Browse files
committed
Fix impedance renormalization + add unit tests
1 parent 5239464 commit 50bde26

File tree

9 files changed

+114
-2
lines changed

9 files changed

+114
-2
lines changed

Software/PC_Application/LibreVNA-GUI/Util/util.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,19 @@ double Util::distanceToLine(QPointF point, QPointF l1, QPointF l2, QPointF *clos
6262
}
6363

6464
std::complex<double> Util::SparamToImpedance(std::complex<double> d, std::complex<double> Z0) {
65-
return Z0 * (1.0 + d) / (1.0 - d);
65+
if (d != 1.0) {
66+
return Z0 * (1.0 + d) / (1.0 - d);
67+
} else {
68+
return std::complex<double>(std::numeric_limits<double>::infinity(), 0.0);
69+
}
70+
}
71+
72+
std::complex<double> Util::ImpedanceToSparam(std::complex<double> Z, std::complex<double> Z0) {
73+
if(std::isinf(Z.real())) {
74+
return 1.0;
75+
} else {
76+
return (Z-Z0)/(Z+Z0);
77+
}
6678
}
6779

6880
double Util::dBmTodBuV(double dBm)

Software/PC_Application/LibreVNA-GUI/Util/util.h

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ namespace Util {
5252
return SparamToVSWR(abs(d));
5353
}
5454
std::complex<double> SparamToImpedance(std::complex<double> d, std::complex<double> Z0 = 50.0);
55+
std::complex<double> ImpedanceToSparam(std::complex<double> Z, std::complex<double> Z0 = 50.0);
5556
// all these conversions assume series connection of real and imag part
5657
static inline double SparamToResistance(std::complex<double> d, std::complex<double> Z0 = 50.0) {
5758
return SparamToImpedance(d, Z0).real();

Software/PC_Application/LibreVNA-GUI/VNA/Deembedding/impedancerenormalization.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "ui_impedancenormalizationdialog.h"
44
#include "Tools/parameters.h"
55
#include "appwindow.h"
6+
#include "Util/util.h"
67

78
#include <complex>
89

@@ -44,9 +45,11 @@ void ImpedanceRenormalization::transformDatapoint(DeviceDriver::VNAMeasurement &
4445
name = "S"+QString::number(ports+1)+QString::number(ports+1);
4546
}
4647
for(auto i=1;i<=ports;i++) {
48+
// handle reflection parameters
4749
auto S11name = "S"+QString::number(i)+QString::number(i);
4850
auto S11 = p.measurements[S11name];
49-
transformed[S11name] = Sparam(ABCDparam(Sparam(S11, 0.1, 0.1, 1.0), p.Z0), impedance).m11;
51+
transformed[S11name] = Util::ImpedanceToSparam(Util::SparamToImpedance(S11, p.Z0), impedance);
52+
// handle transmission parameters
5053
for(auto j=i+1;j<=ports;j++) {
5154
auto S12name = "S"+QString::number(i)+QString::number(j);
5255
auto S21name = "S"+QString::number(j)+QString::number(i);

Software/PC_Application/LibreVNA-Test/LibreVNA-Test.pro

+2
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ SOURCES += \
152152
../LibreVNA-GUI/touchstone.cpp \
153153
../LibreVNA-GUI/unit.cpp \
154154
ffttests.cpp \
155+
impedancerenormalizationtests.cpp \
155156
main.cpp \
156157
parametertests.cpp \
157158
portextensiontests.cpp \
@@ -346,6 +347,7 @@ HEADERS += \
346347
../LibreVNA-GUI/touchstone.h \
347348
../LibreVNA-GUI/unit.h \
348349
ffttests.h \
350+
impedancerenormalizationtests.h \
349351
parametertests.h \
350352
portextensiontests.h \
351353
utiltests.h
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "impedancerenormalizationtests.h"
2+
3+
ImpedanceRenormalizationTests::ImpedanceRenormalizationTests()
4+
{
5+
renorm = new ImpedanceRenormalization();
6+
7+
// set it up to normalize to 75 Ohm
8+
nlohmann::json j;
9+
j["impedance"] = 75;
10+
renorm->fromJSON(j);
11+
}
12+
13+
ImpedanceRenormalizationTests::~ImpedanceRenormalizationTests()
14+
{
15+
delete renorm;
16+
}
17+
18+
void ImpedanceRenormalizationTests::OnePortTests()
19+
{
20+
// Create dummy measurements
21+
DeviceDriver::VNAMeasurement measShort;
22+
measShort.pointNum = 0;
23+
measShort.Z0 = 50.0;
24+
measShort.measurements["S11"] = -1.0;
25+
26+
auto measLoad = measShort;
27+
measLoad.measurements["S11"] = 0.0;
28+
29+
auto measOpen = measShort;
30+
measOpen.measurements["S11"] = 1.0;
31+
32+
// perform renormalization
33+
renorm->transformDatapoint(measShort);
34+
renorm->transformDatapoint(measLoad);
35+
renorm->transformDatapoint(measOpen);
36+
37+
QVERIFY(measShort.measurements["S11"] == -1.0);
38+
// a Ohm load renormalized to 75 Ohm impedance has a reflection coefficient of -0.2
39+
QVERIFY(measLoad.measurements["S11"] == -0.2);
40+
QVERIFY(measOpen.measurements["S11"] == 1.0);
41+
}
42+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef IMPEDANCERENORMALIZATIONTESTS_H
2+
#define IMPEDANCERENORMALIZATIONTESTS_H
3+
4+
#include <QtTest>
5+
6+
#include "impedancerenormalization.h"
7+
8+
class ImpedanceRenormalizationTests : public QObject
9+
{
10+
Q_OBJECT
11+
public:
12+
ImpedanceRenormalizationTests();
13+
~ImpedanceRenormalizationTests();
14+
private slots:
15+
void OnePortTests();
16+
17+
private:
18+
ImpedanceRenormalization *renorm;
19+
};
20+
21+
#endif // IMPEDANCERENORMALIZATIONTESTS_H

Software/PC_Application/LibreVNA-Test/main.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "portextensiontests.h"
33
#include "parametertests.h"
44
#include "ffttests.h"
5+
#include "impedancerenormalizationtests.h"
56

67
#include <QtTest>
78

@@ -14,6 +15,7 @@ int main(int argc, char *argv[])
1415
status |= QTest::qExec(new PortExtensionTests, argc, argv);
1516
status |= QTest::qExec(new ParameterTests, argc, argv);
1617
status |= QTest::qExec(new fftTests, argc, argv);
18+
status |= QTest::qExec(new ImpedanceRenormalizationTests, argc, argv);
1719

1820
return status;
1921
}

Software/PC_Application/LibreVNA-Test/utiltests.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,31 @@ void UtilTests::FirmwareComparison()
7878
QVERIFY(Util::firmwareEqualOrHigher("2.2.2", "2.3") == false);
7979
QVERIFY(Util::firmwareEqualOrHigher("2.2", "2.3.1") == false);
8080
}
81+
82+
void UtilTests::ImpedanceSparameterCalculation()
83+
{
84+
// Check impedance to S parameter conversion and back for different values
85+
auto Z = std::complex<double>(50.0);
86+
auto S = Util::ImpedanceToSparam(Z);
87+
QVERIFY(S == 0.0);
88+
QVERIFY(Util::SparamToImpedance(S) == Z);
89+
90+
Z = std::complex<double>(0.0);
91+
S = Util::ImpedanceToSparam(Z);
92+
QVERIFY(S == -1.0);
93+
QVERIFY(Util::SparamToImpedance(S) == Z);
94+
95+
Z = std::complex<double>(100.0);
96+
S = Util::ImpedanceToSparam(Z);
97+
QVERIFY(qFuzzyCompare(S.real(), 1.0/3));
98+
QVERIFY(S.imag() == 0.0);
99+
QVERIFY(qFuzzyCompare(Util::SparamToImpedance(S).real(), Z.real()));
100+
QVERIFY(qFuzzyCompare(Util::SparamToImpedance(S).imag(), Z.imag()));
101+
102+
// Edge case: convert S parameter to impedance at 1.0 (which will give a +inf impedance)
103+
S = 1.0;
104+
Z = Util::SparamToImpedance(S);
105+
// convert back, we must land back at 1.0
106+
auto S_from_Z = Util::ImpedanceToSparam(Z);
107+
QVERIFY(S_from_Z == S);
108+
}

Software/PC_Application/LibreVNA-Test/utiltests.h

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ private slots:
1414
void IdealArcApproximation();
1515
void NoisyCircleApproximation();
1616
void FirmwareComparison();
17+
void ImpedanceSparameterCalculation();
1718
};
1819

1920
#endif // UTILTESTS_H

0 commit comments

Comments
 (0)