mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-01-13 20:20:16 +01:00
Fix impedance renormalization + add unit tests
This commit is contained in:
parent
523946447a
commit
50bde261af
|
|
@ -62,7 +62,19 @@ double Util::distanceToLine(QPointF point, QPointF l1, QPointF l2, QPointF *clos
|
|||
}
|
||||
|
||||
std::complex<double> Util::SparamToImpedance(std::complex<double> d, std::complex<double> Z0) {
|
||||
return Z0 * (1.0 + d) / (1.0 - d);
|
||||
if (d != 1.0) {
|
||||
return Z0 * (1.0 + d) / (1.0 - d);
|
||||
} else {
|
||||
return std::complex<double>(std::numeric_limits<double>::infinity(), 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
std::complex<double> Util::ImpedanceToSparam(std::complex<double> Z, std::complex<double> Z0) {
|
||||
if(std::isinf(Z.real())) {
|
||||
return 1.0;
|
||||
} else {
|
||||
return (Z-Z0)/(Z+Z0);
|
||||
}
|
||||
}
|
||||
|
||||
double Util::dBmTodBuV(double dBm)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ namespace Util {
|
|||
return SparamToVSWR(abs(d));
|
||||
}
|
||||
std::complex<double> SparamToImpedance(std::complex<double> d, std::complex<double> Z0 = 50.0);
|
||||
std::complex<double> ImpedanceToSparam(std::complex<double> Z, std::complex<double> Z0 = 50.0);
|
||||
// all these conversions assume series connection of real and imag part
|
||||
static inline double SparamToResistance(std::complex<double> d, std::complex<double> Z0 = 50.0) {
|
||||
return SparamToImpedance(d, Z0).real();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "ui_impedancenormalizationdialog.h"
|
||||
#include "Tools/parameters.h"
|
||||
#include "appwindow.h"
|
||||
#include "Util/util.h"
|
||||
|
||||
#include <complex>
|
||||
|
||||
|
|
@ -44,9 +45,11 @@ void ImpedanceRenormalization::transformDatapoint(DeviceDriver::VNAMeasurement &
|
|||
name = "S"+QString::number(ports+1)+QString::number(ports+1);
|
||||
}
|
||||
for(auto i=1;i<=ports;i++) {
|
||||
// handle reflection parameters
|
||||
auto S11name = "S"+QString::number(i)+QString::number(i);
|
||||
auto S11 = p.measurements[S11name];
|
||||
transformed[S11name] = Sparam(ABCDparam(Sparam(S11, 0.1, 0.1, 1.0), p.Z0), impedance).m11;
|
||||
transformed[S11name] = Util::ImpedanceToSparam(Util::SparamToImpedance(S11, p.Z0), impedance);
|
||||
// handle transmission parameters
|
||||
for(auto j=i+1;j<=ports;j++) {
|
||||
auto S12name = "S"+QString::number(i)+QString::number(j);
|
||||
auto S21name = "S"+QString::number(j)+QString::number(i);
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ SOURCES += \
|
|||
../LibreVNA-GUI/touchstone.cpp \
|
||||
../LibreVNA-GUI/unit.cpp \
|
||||
ffttests.cpp \
|
||||
impedancerenormalizationtests.cpp \
|
||||
main.cpp \
|
||||
parametertests.cpp \
|
||||
portextensiontests.cpp \
|
||||
|
|
@ -346,6 +347,7 @@ HEADERS += \
|
|||
../LibreVNA-GUI/touchstone.h \
|
||||
../LibreVNA-GUI/unit.h \
|
||||
ffttests.h \
|
||||
impedancerenormalizationtests.h \
|
||||
parametertests.h \
|
||||
portextensiontests.h \
|
||||
utiltests.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
#include "impedancerenormalizationtests.h"
|
||||
|
||||
ImpedanceRenormalizationTests::ImpedanceRenormalizationTests()
|
||||
{
|
||||
renorm = new ImpedanceRenormalization();
|
||||
|
||||
// set it up to normalize to 75 Ohm
|
||||
nlohmann::json j;
|
||||
j["impedance"] = 75;
|
||||
renorm->fromJSON(j);
|
||||
}
|
||||
|
||||
ImpedanceRenormalizationTests::~ImpedanceRenormalizationTests()
|
||||
{
|
||||
delete renorm;
|
||||
}
|
||||
|
||||
void ImpedanceRenormalizationTests::OnePortTests()
|
||||
{
|
||||
// Create dummy measurements
|
||||
DeviceDriver::VNAMeasurement measShort;
|
||||
measShort.pointNum = 0;
|
||||
measShort.Z0 = 50.0;
|
||||
measShort.measurements["S11"] = -1.0;
|
||||
|
||||
auto measLoad = measShort;
|
||||
measLoad.measurements["S11"] = 0.0;
|
||||
|
||||
auto measOpen = measShort;
|
||||
measOpen.measurements["S11"] = 1.0;
|
||||
|
||||
// perform renormalization
|
||||
renorm->transformDatapoint(measShort);
|
||||
renorm->transformDatapoint(measLoad);
|
||||
renorm->transformDatapoint(measOpen);
|
||||
|
||||
QVERIFY(measShort.measurements["S11"] == -1.0);
|
||||
// a Ohm load renormalized to 75 Ohm impedance has a reflection coefficient of -0.2
|
||||
QVERIFY(measLoad.measurements["S11"] == -0.2);
|
||||
QVERIFY(measOpen.measurements["S11"] == 1.0);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef IMPEDANCERENORMALIZATIONTESTS_H
|
||||
#define IMPEDANCERENORMALIZATIONTESTS_H
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
#include "impedancerenormalization.h"
|
||||
|
||||
class ImpedanceRenormalizationTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ImpedanceRenormalizationTests();
|
||||
~ImpedanceRenormalizationTests();
|
||||
private slots:
|
||||
void OnePortTests();
|
||||
|
||||
private:
|
||||
ImpedanceRenormalization *renorm;
|
||||
};
|
||||
|
||||
#endif // IMPEDANCERENORMALIZATIONTESTS_H
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
#include "portextensiontests.h"
|
||||
#include "parametertests.h"
|
||||
#include "ffttests.h"
|
||||
#include "impedancerenormalizationtests.h"
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
|
|
@ -14,6 +15,7 @@ int main(int argc, char *argv[])
|
|||
status |= QTest::qExec(new PortExtensionTests, argc, argv);
|
||||
status |= QTest::qExec(new ParameterTests, argc, argv);
|
||||
status |= QTest::qExec(new fftTests, argc, argv);
|
||||
status |= QTest::qExec(new ImpedanceRenormalizationTests, argc, argv);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,3 +78,31 @@ void UtilTests::FirmwareComparison()
|
|||
QVERIFY(Util::firmwareEqualOrHigher("2.2.2", "2.3") == false);
|
||||
QVERIFY(Util::firmwareEqualOrHigher("2.2", "2.3.1") == false);
|
||||
}
|
||||
|
||||
void UtilTests::ImpedanceSparameterCalculation()
|
||||
{
|
||||
// Check impedance to S parameter conversion and back for different values
|
||||
auto Z = std::complex<double>(50.0);
|
||||
auto S = Util::ImpedanceToSparam(Z);
|
||||
QVERIFY(S == 0.0);
|
||||
QVERIFY(Util::SparamToImpedance(S) == Z);
|
||||
|
||||
Z = std::complex<double>(0.0);
|
||||
S = Util::ImpedanceToSparam(Z);
|
||||
QVERIFY(S == -1.0);
|
||||
QVERIFY(Util::SparamToImpedance(S) == Z);
|
||||
|
||||
Z = std::complex<double>(100.0);
|
||||
S = Util::ImpedanceToSparam(Z);
|
||||
QVERIFY(qFuzzyCompare(S.real(), 1.0/3));
|
||||
QVERIFY(S.imag() == 0.0);
|
||||
QVERIFY(qFuzzyCompare(Util::SparamToImpedance(S).real(), Z.real()));
|
||||
QVERIFY(qFuzzyCompare(Util::SparamToImpedance(S).imag(), Z.imag()));
|
||||
|
||||
// Edge case: convert S parameter to impedance at 1.0 (which will give a +inf impedance)
|
||||
S = 1.0;
|
||||
Z = Util::SparamToImpedance(S);
|
||||
// convert back, we must land back at 1.0
|
||||
auto S_from_Z = Util::ImpedanceToSparam(Z);
|
||||
QVERIFY(S_from_Z == S);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ private slots:
|
|||
void IdealArcApproximation();
|
||||
void NoisyCircleApproximation();
|
||||
void FirmwareComparison();
|
||||
void ImpedanceSparameterCalculation();
|
||||
};
|
||||
|
||||
#endif // UTILTESTS_H
|
||||
|
|
|
|||
Loading…
Reference in a new issue