From d817804827a4db2843f25d3489d44ffa7afb28cf Mon Sep 17 00:00:00 2001 From: fredzo Date: Mon, 18 Nov 2024 19:31:26 +0100 Subject: [PATCH] Added caching for multimeter auto range setting. Added "Overload" to Unit PrettyPrint() when value is double max range. --- scopehal/LeCroyOscilloscope.cpp | 13 +++++- scopehal/LeCroyOscilloscope.h | 2 + scopehal/OwonXDMMultimeter.cpp | 49 +++++++++++++++------- scopehal/OwonXDMMultimeter.h | 2 + scopehal/RohdeSchwarzHMC8012Multimeter.cpp | 15 ++++++- scopehal/RohdeSchwarzHMC8012Multimeter.h | 2 + scopehal/Unit.cpp | 5 +++ scopehal/Unit.h | 2 + 8 files changed, 72 insertions(+), 18 deletions(-) diff --git a/scopehal/LeCroyOscilloscope.cpp b/scopehal/LeCroyOscilloscope.cpp index 656456c2..05ee6a35 100644 --- a/scopehal/LeCroyOscilloscope.cpp +++ b/scopehal/LeCroyOscilloscope.cpp @@ -86,6 +86,7 @@ LeCroyOscilloscope::LeCroyOscilloscope(SCPITransport* transport) , m_interleavingValid(false) , m_meterMode(Multimeter::DC_VOLTAGE) , m_meterModeValid(false) + , m_dmmAutorangeValid(false) , m_highDefinition(false) { //standard initialization @@ -1071,6 +1072,7 @@ void LeCroyOscilloscope::FlushConfigCache() m_triggerOffsetValid = false; m_interleavingValid = false; m_meterModeValid = false; + m_dmmAutorangeValid = false; //Clear cached display name of all channels for(auto c : m_channels) @@ -1891,14 +1893,23 @@ int LeCroyOscilloscope::GetMeterDigits() bool LeCroyOscilloscope::GetMeterAutoRange() { + if(m_dmmAutorangeValid) + return m_dmmAutorange; + auto str = m_transport->SendCommandQueuedWithReply("VBS? 'return = app.acquisition.DVM.AutoRange'"); int ret; sscanf(str.c_str(), "%d", &ret); - return ret ? true : false; + m_dmmAutorange = (ret ? true : false); + + m_dmmAutorangeValid = true; + return m_dmmAutorange; } void LeCroyOscilloscope::SetMeterAutoRange(bool enable) { + m_dmmAutorange = enable; + m_dmmAutorangeValid = true; + if(enable) m_transport->SendCommandQueued("VBS 'app.acquisition.DVM.AutoRange = 1'"); else diff --git a/scopehal/LeCroyOscilloscope.h b/scopehal/LeCroyOscilloscope.h index 2028332a..dc54d133 100644 --- a/scopehal/LeCroyOscilloscope.h +++ b/scopehal/LeCroyOscilloscope.h @@ -375,6 +375,8 @@ class LeCroyOscilloscope bool m_interleavingValid; Multimeter::MeasurementTypes m_meterMode; bool m_meterModeValid; + bool m_dmmAutorangeValid; + bool m_dmmAutorange; std::map m_probeIsActive; //True if we have >8 bit capture depth diff --git a/scopehal/OwonXDMMultimeter.cpp b/scopehal/OwonXDMMultimeter.cpp index 2702a369..d5c8c85a 100644 --- a/scopehal/OwonXDMMultimeter.cpp +++ b/scopehal/OwonXDMMultimeter.cpp @@ -46,6 +46,7 @@ OwonXDMMultimeter::OwonXDMMultimeter(SCPITransport* transport) , SCPIInstrument(transport) , m_modeValid(false) , m_secmodeValid(false) + , m_dmmAutorangeValid(false) { //prefetch operating mode GetMeterMode(); @@ -55,6 +56,9 @@ OwonXDMMultimeter::OwonXDMMultimeter(SCPITransport* transport) // Set speed to high m_transport->SendCommandQueued("RATE F"); + + // Rate limit to 65 Hz (which is the highest measurement supported by the metter) + m_transport->EnableRateLimiting(chrono::milliseconds(1000/65)); } OwonXDMMultimeter::~OwonXDMMultimeter() @@ -108,17 +112,26 @@ int OwonXDMMultimeter::GetMeterDigits() bool OwonXDMMultimeter::GetMeterAutoRange() { + if(m_dmmAutorangeValid) + return m_dmmAutorange; + string reply = m_transport->SendCommandQueuedWithReply("AUTO?"); - return (Trim(reply) == "1"); + m_dmmAutorange = (Trim(reply) == "1"); + + m_dmmAutorangeValid = true; + return m_dmmAutorange; } void OwonXDMMultimeter::SetMeterAutoRange(bool enable) { + m_dmmAutorange = enable; + m_dmmAutorangeValid = true; + if(enable) - m_transport->SendCommandQueued("AUTO"); + m_transport->SendCommandImmediate("AUTO"); else { - m_transport->SendCommandQueued("RANGE 1"); + m_transport->SendCommandImmediate("RANGE 1"); } } @@ -143,6 +156,8 @@ double OwonXDMMultimeter::GetMeterValue() LogWarning("Failed to read value: got '%s'\n",value.c_str()); continue; } + else if(value == "1E+9") // Overload + return std::numeric_limits::max(); istringstream os(value); double result; os >> result; @@ -165,7 +180,9 @@ double OwonXDMMultimeter::GetSecondaryMeterValue() // No secondary reading at this point return 0; } - if(value.empty()||(value.find("NON")!=std::string::npos)) + else if(value == "1E+9") + return std::numeric_limits::max(); // Overload + if(value.empty()) { LogWarning("Failed to read value: got '%s'\n",value.c_str()); continue; @@ -259,43 +276,43 @@ void OwonXDMMultimeter::SetMeterMode(Multimeter::MeasurementTypes type) switch(type) { case DC_VOLTAGE: - m_transport->SendCommandQueued("CONF:VOLT:DC"); + m_transport->SendCommandImmediate("CONF:VOLT:DC"); break; case AC_RMS_AMPLITUDE: - m_transport->SendCommandQueued("CONF:VOLT:AC"); + m_transport->SendCommandImmediate("CONF:VOLT:AC"); break; case DC_CURRENT: - m_transport->SendCommandQueued("CONF:CURR:DC"); + m_transport->SendCommandImmediate("CONF:CURR:DC"); break; case AC_CURRENT: - m_transport->SendCommandQueued("CONF:CURR:AC"); + m_transport->SendCommandImmediate("CONF:CURR:AC"); break; case RESISTANCE: - m_transport->SendCommandQueued("CONF:RES"); + m_transport->SendCommandImmediate("CONF:RES"); break; case CAPACITANCE: - m_transport->SendCommandQueued("CONF:CAP"); + m_transport->SendCommandImmediate("CONF:CAP"); break; case FREQUENCY: - m_transport->SendCommandQueued("CONF:FREQ"); + m_transport->SendCommandImmediate("CONF:FREQ"); break; case DIODE: - m_transport->SendCommandQueued("CONF:DIOD"); + m_transport->SendCommandImmediate("CONF:DIOD"); break; case CONTINUITY: - m_transport->SendCommandQueued("CONF:CONT"); + m_transport->SendCommandImmediate("CONF:CONT"); break; case TEMPERATURE: - m_transport->SendCommandQueued("CONF:TEMP"); + m_transport->SendCommandImmediate("CONF:TEMP"); break; //whatever it is, not supported @@ -313,11 +330,11 @@ void OwonXDMMultimeter::SetSecondaryMeterMode(Multimeter::MeasurementTypes type) switch(type) { case FREQUENCY: - m_transport->SendCommandQueued("FUNC2 \"FREQ\""); + m_transport->SendCommandImmediate("FUNC2 \"FREQ\""); break; case NONE: - m_transport->SendCommandQueued("FUNC2 \"NONe\""); + m_transport->SendCommandImmediate("FUNC2 \"NONe\""); break; //not supported diff --git a/scopehal/OwonXDMMultimeter.h b/scopehal/OwonXDMMultimeter.h index 9de79543..28ec2638 100644 --- a/scopehal/OwonXDMMultimeter.h +++ b/scopehal/OwonXDMMultimeter.h @@ -76,6 +76,8 @@ class OwonXDMMultimeter protected: bool m_modeValid; bool m_secmodeValid; + bool m_dmmAutorangeValid; + bool m_dmmAutorange; MeasurementTypes m_mode; MeasurementTypes m_secmode; diff --git a/scopehal/RohdeSchwarzHMC8012Multimeter.cpp b/scopehal/RohdeSchwarzHMC8012Multimeter.cpp index 70343ce8..05fc7165 100644 --- a/scopehal/RohdeSchwarzHMC8012Multimeter.cpp +++ b/scopehal/RohdeSchwarzHMC8012Multimeter.cpp @@ -41,6 +41,7 @@ RohdeSchwarzHMC8012Multimeter::RohdeSchwarzHMC8012Multimeter(SCPITransport* tran , SCPIInstrument(transport) , m_modeValid(false) , m_secmodeValid(false) + , m_dmmAutorangeValid(false) { //prefetch operating mode GetMeterMode(); @@ -100,6 +101,9 @@ int RohdeSchwarzHMC8012Multimeter::GetMeterDigits() bool RohdeSchwarzHMC8012Multimeter::GetMeterAutoRange() { + if(m_dmmAutorangeValid) + return m_dmmAutorange; + string reply; switch(m_mode) @@ -122,19 +126,28 @@ bool RohdeSchwarzHMC8012Multimeter::GetMeterAutoRange() //no autoranging in temperature mode case TEMPERATURE: + m_dmmAutorangeValid = true; + m_dmmAutorange = false; return false; //TODO default: LogError("GetMeterAutoRange not implemented yet for modes other than DC_CURRENT\n"); + m_dmmAutorangeValid = true; + m_dmmAutorange = false; return false; } - return (reply == "1"); + m_dmmAutorange = (reply == "1"); + m_dmmAutorangeValid = true; + return m_dmmAutorange; } void RohdeSchwarzHMC8012Multimeter::SetMeterAutoRange(bool enable) { + m_dmmAutorange = enable; + m_dmmAutorangeValid = true; + switch(m_mode) { case AC_RMS_AMPLITUDE: diff --git a/scopehal/RohdeSchwarzHMC8012Multimeter.h b/scopehal/RohdeSchwarzHMC8012Multimeter.h index c9c0e1ac..7b90e282 100644 --- a/scopehal/RohdeSchwarzHMC8012Multimeter.h +++ b/scopehal/RohdeSchwarzHMC8012Multimeter.h @@ -71,6 +71,8 @@ class RohdeSchwarzHMC8012Multimeter protected: bool m_modeValid; bool m_secmodeValid; + bool m_dmmAutorangeValid; + bool m_dmmAutorange; MeasurementTypes m_mode; MeasurementTypes m_secmode; diff --git a/scopehal/Unit.cpp b/scopehal/Unit.cpp index d477e761..3a9bf565 100644 --- a/scopehal/Unit.cpp +++ b/scopehal/Unit.cpp @@ -586,6 +586,8 @@ void Unit::GetUnitSuffix(UnitType type, double num, double& scaleFactor, string& */ string Unit::PrettyPrint(double value, int sigfigs, bool useDisplayLocale) const { + if(value >= std::numeric_limits::max()) + return UNIT_OVERLOAD_LABEL; if(useDisplayLocale) SetPrintingLocale(); @@ -961,6 +963,9 @@ string Unit::PrettyPrintRange(double pixelMin, double pixelMax, double rangeMin, */ double Unit::ParseString(const string& str, bool useDisplayLocale) { + if(str == UNIT_OVERLOAD_LABEL) + return std::numeric_limits::max(); + if(useDisplayLocale) SetPrintingLocale(); diff --git a/scopehal/Unit.h b/scopehal/Unit.h index feaf973a..5938308c 100644 --- a/scopehal/Unit.h +++ b/scopehal/Unit.h @@ -46,6 +46,8 @@ #endif +#define UNIT_OVERLOAD_LABEL "Overload" + /** @brief A unit of measurement, plus conversion to pretty-printed output