From da5512f743a2f7dcd5919f9222adc7611583a53c Mon Sep 17 00:00:00 2001 From: Franz Hempel Date: Tue, 7 Jan 2025 10:49:39 +0100 Subject: [PATCH 1/4] SMB100A -> bugfix set_amplitude and set_frequency --- src/Signal-Rohde&Schwarz_SMB100A/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Signal-Rohde&Schwarz_SMB100A/main.py b/src/Signal-Rohde&Schwarz_SMB100A/main.py index 976cbac5..91f668bd 100644 --- a/src/Signal-Rohde&Schwarz_SMB100A/main.py +++ b/src/Signal-Rohde&Schwarz_SMB100A/main.py @@ -172,7 +172,7 @@ def set_frequency(self, frequency: float) -> None: """Set the frequency of the RF output.""" min_frequency = 100e3 max_frequency = 12.75e6 - if self.value < min_frequency or self.value > max_frequency: + if frequency < min_frequency or frequency > max_frequency: msg = f"Frequency {frequency} out of range. Choose between {min_frequency} and {max_frequency}." raise ValueError(msg) @@ -206,7 +206,7 @@ def set_amplitude(self, high_level: float) -> None: """Set the amplitude of the RF output. The power level will be [min level + offset ... max level + offset].""" if self.amplitude_unit == "V": max_power = 7.071 - if self.value < 0 or self.value > max_power: + if high_level < 0 or high_level > max_power: msg = f"Power {high_level} out of range. Choose between 0 and {max_power} V." raise ValueError(msg) From ec72f84ce075fe89771861bb4d2efb7379dacb3e Mon Sep 17 00:00:00 2001 From: Franz Hempel Date: Wed, 8 Jan 2025 11:36:20 +0100 Subject: [PATCH 2/4] SMB100A -> bugfix power unit, reset in initialize --- src/Signal-Rohde&Schwarz_SMB100A/main.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Signal-Rohde&Schwarz_SMB100A/main.py b/src/Signal-Rohde&Schwarz_SMB100A/main.py index 91f668bd..df52353c 100644 --- a/src/Signal-Rohde&Schwarz_SMB100A/main.py +++ b/src/Signal-Rohde&Schwarz_SMB100A/main.py @@ -77,7 +77,7 @@ def set_GUIparameter(self) -> dict: # noqa: N802 ], "Waveform": ["Sinus"], "PeriodFrequency": ["Frequency in Hz", "Period in s"], - "PeriodFrequencyValue": 2e-6, + "PeriodFrequencyValue": 2e6, "AmplitudeHiLevel": self.amplitude_modes, "AmplitudeHiLevelValue": 1.0, "DelayPhase": ["Delay in s", "Phase in deg"], @@ -100,12 +100,14 @@ def get_GUIparameter(self, parameter: dict) -> None: # noqa: N802 self.variables = [self.period_frequency_mode.split(" ")[0], "RF Power level"] self.units = [self.period_frequency_mode.split(" ")[-1], self.amplitude_unit] - def configure(self) -> None: - """Configure the device.""" + def initialize(self) -> None: + """Initialize the device.""" self.port.write("*RST") # self.port.write("*CLS") self.lock_user_interface(True) + def configure(self) -> None: + """Configure the device.""" # Set power mode to CW self.port.write(":SOUR:POW:MODE CW") @@ -114,6 +116,7 @@ def configure(self) -> None: # Set frequency self.set_frequency_mode("CW") + if self.period_frequency_mode == "Period in s": # else it is "Frequency in Hz" self.period_frequency_value = 1 / self.period_frequency_value self.set_frequency(self.period_frequency_value) @@ -171,7 +174,7 @@ def call(self) -> tuple: def set_frequency(self, frequency: float) -> None: """Set the frequency of the RF output.""" min_frequency = 100e3 - max_frequency = 12.75e6 + max_frequency = 12.75e9 if frequency < min_frequency or frequency > max_frequency: msg = f"Frequency {frequency} out of range. Choose between {min_frequency} and {max_frequency}." raise ValueError(msg) @@ -219,6 +222,7 @@ def get_power_level(self) -> float: def set_power_unit(self, unit: str) -> None: """Set the power unit of the RF output.""" + unit = unit.upper() if unit not in ["V", "DBUV", "DBM"]: msg = "Invalid power unit. Choose from 'V', 'DBUV', 'DBM'." raise ValueError(msg) From d7f4d05788224fe48b3c4e42530ab894b1ec7546 Mon Sep 17 00:00:00 2001 From: Franz Hempel Date: Wed, 22 Jan 2025 14:11:34 +0100 Subject: [PATCH 3/4] SMB100A -> update license, add modulation functions --- src/Signal-Rohde&Schwarz_SMB100A/license.txt | 2 +- src/Signal-Rohde&Schwarz_SMB100A/main.py | 21 +++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Signal-Rohde&Schwarz_SMB100A/license.txt b/src/Signal-Rohde&Schwarz_SMB100A/license.txt index 98ef5718..2de3f93f 100644 --- a/src/Signal-Rohde&Schwarz_SMB100A/license.txt +++ b/src/Signal-Rohde&Schwarz_SMB100A/license.txt @@ -5,7 +5,7 @@ find those in the corresponding folders or contact the maintainer. MIT License -Copyright (c) 2024 SweepMe! GmbH (sweep-me.net) +Copyright (c) 2025 SweepMe! GmbH (sweep-me.net) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Signal-Rohde&Schwarz_SMB100A/main.py b/src/Signal-Rohde&Schwarz_SMB100A/main.py index df52353c..0e22a733 100644 --- a/src/Signal-Rohde&Schwarz_SMB100A/main.py +++ b/src/Signal-Rohde&Schwarz_SMB100A/main.py @@ -5,7 +5,7 @@ # # MIT License # -# Copyright (c) 2024 SweepMe! GmbH (sweep-me.net) +# Copyright (c) 2025 SweepMe! GmbH (sweep-me.net) # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -247,6 +247,25 @@ def lock_user_interface(self, is_locked: bool) -> None: """ Currently not implemented functions """ + def set_amplitude_modulation_state(self, turn_on: bool = False) -> None: + """Set the amplitude modulation on or off.""" + state = "ON" if turn_on else "OFF" + self.port.write(f":SOUR:AM:STAT {state}") + + def set_amplitude_modulation(self, depth_percent: float = 0.0, use_exponential_modulation: bool = False) -> None: + """Set the amplitude modulation to linear or exponential.""" + if depth_percent < 0 or depth_percent > 100: + msg = f"Depth {depth_percent} out of range. Choose between 0 and 100%." + raise ValueError(msg) + + if not use_exponential_modulation: + self.port.write(":SOUR:AM:TYPE LIN") + self.port.write(f":SOUR:AM:DEPT {depth_percent}") + else: + self.port.write(":SOUR:AM:TYPE EXP") + # Test if EXP or LIN in command, manual is ambiguous + self.port.write(f":SOUR:AM:DEPT:EXP {depth_percent}") + def get_impedance(self) -> float: """Get the impedance of the RF output.""" self.port.write(":OUTP:IMP?") From f3a730d5a220b5cfe367388cb0baa2014312ea68 Mon Sep 17 00:00:00 2001 From: Franz Hempel Date: Wed, 15 Jan 2025 16:47:34 +0100 Subject: [PATCH 4/4] Signal SMB 100 -> add reconfigure --- src/Signal-Rohde&Schwarz_SMB100A/main.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Signal-Rohde&Schwarz_SMB100A/main.py b/src/Signal-Rohde&Schwarz_SMB100A/main.py index 0e22a733..6721e5d6 100644 --- a/src/Signal-Rohde&Schwarz_SMB100A/main.py +++ b/src/Signal-Rohde&Schwarz_SMB100A/main.py @@ -103,7 +103,6 @@ def get_GUIparameter(self, parameter: dict) -> None: # noqa: N802 def initialize(self) -> None: """Initialize the device.""" self.port.write("*RST") - # self.port.write("*CLS") self.lock_user_interface(True) def configure(self) -> None: @@ -129,6 +128,28 @@ def configure(self) -> None: self.set_output_state(True) + def reconfigure(self, parameters: dict, keys: list) -> None: + """If the GUI parameters are changed during a measurement this function is called. + + This can happen when using the ParameterSystem in the SweepMe! GUI. Use reconfigure to only update the changed + parameters instead of calling configure which sets all parameters to their default values. + """ + if "PeriodFrequencyValue" in keys: + new_frequency = float(parameters["PeriodFrequencyValue"]) + if parameters["PeriodFrequency"] == "Period in s": + new_frequency = 1 / new_frequency + + self.set_frequency(new_frequency) + + if "AmplitudeHiLevelValue" in keys: + self.set_amplitude(float(parameters["AmplitudeHiLevelValue"])) + + if "DelayPhaseValue" in keys: + if parameters["DelayPhase"] == "Phase in deg": + self.set_phase(float(parameters["DelayPhaseValue"])) + elif parameters["DelayPhase"] == "Delay in s": + self.set_delay(float(parameters["DelayPhaseValue"])) + def unconfigure(self) -> None: """Unconfigure the device.""" self.check_errors()