hitl_tester.modules.bms.load

Provides controls for the Rigol DL3000 Electronic Load.

(c) 2020-2024 TurnAround Factor, Inc.

#

CUI DISTRIBUTION CONTROL

Controlled by: DLA J68 R&D SBIP

CUI Category: Small Business Research and Technology

Distribution/Dissemination Controls: PROTECTED BY SBIR DATA RIGHTS

POC: GOV SBIP Program Manager Denise Price, 571-767-0111

Distribution authorized to U.S. Government Agencies only, to protect information not owned by the

U.S. Government and protected by a contractor’s ‘limited rights’ statement, or received with the understanding that

it is not routinely transmitted outside the U.S. Government (determination made September 14, 2024). Other requests

for this document shall be referred to ACOR DLA Logistics Operations (J-68), 8725 John J. Kingman Rd., Suite 4317,

Fort Belvoir, VA 22060-6221

#

SBIR DATA RIGHTS

Contract No.:SP4701-23-C-0083

Contractor Name: TurnAround Factor, Inc.

Contractor Address: 10365 Wood Park Ct. Suite 313 / Ashland, VA 23005

Expiration of SBIR Data Rights Period: September 24, 2029

The Government's rights to use, modify, reproduce, release, perform, display, or disclose technical data or computer

software marked with this legend are restricted during the period shown as provided in paragraph (b)(4) of the Rights

in Noncommercial Technical Data and Computer Software--Small Business Innovative Research (SBIR) Program clause

contained in the above identified contract. No restrictions apply after the expiration date shown above. Any

reproduction of technical data, computer software, or portions thereof marked with this legend must also reproduce

the markings.

  1"""
  2Provides controls for the Rigol DL3000 Electronic Load.
  3
  4# (c) 2020-2024 TurnAround Factor, Inc.
  5#
  6# CUI DISTRIBUTION CONTROL
  7# Controlled by: DLA J68 R&D SBIP
  8# CUI Category: Small Business Research and Technology
  9# Distribution/Dissemination Controls: PROTECTED BY SBIR DATA RIGHTS
 10# POC: GOV SBIP Program Manager Denise Price, 571-767-0111
 11# Distribution authorized to U.S. Government Agencies only, to protect information not owned by the
 12# U.S. Government and protected by a contractor’s ‘limited rights’ statement, or received with the understanding that
 13# it is not routinely transmitted outside the U.S. Government (determination made September 14, 2024). Other requests
 14# for this document shall be referred to ACOR DLA Logistics Operations (J-68), 8725 John J. Kingman Rd., Suite 4317,
 15# Fort Belvoir, VA 22060-6221
 16#
 17# SBIR DATA RIGHTS
 18# Contract No.:SP4701-23-C-0083
 19# Contractor Name: TurnAround Factor, Inc.
 20# Contractor Address: 10365 Wood Park Ct. Suite 313 / Ashland, VA 23005
 21# Expiration of SBIR Data Rights Period: September 24, 2029
 22# The Government's rights to use, modify, reproduce, release, perform, display, or disclose technical data or computer
 23# software marked with this legend are restricted during the period shown as provided in paragraph (b)(4) of the Rights
 24# in Noncommercial Technical Data and Computer Software--Small Business Innovative Research (SBIR) Program clause
 25# contained in the above identified contract. No restrictions apply after the expiration date shown above. Any
 26# reproduction of technical data, computer software, or portions thereof marked with this legend must also reproduce
 27# the markings.
 28"""
 29
 30from __future__ import annotations
 31
 32import atexit
 33from time import sleep
 34
 35from hitl_tester.modules.bms.plateset import Plateset
 36from hitl_tester.modules.bms_types import SafeResource, DischargeType
 37from hitl_tester.modules.logger import logger
 38
 39
 40class Load:
 41    """Rigol DL3000 Electronic Load command wrapper."""
 42
 43    def __init__(self, resource: SafeResource):
 44        """
 45        Initialize the DL3000 wrapper with a specific PyVISA resource.
 46        This class does NOT open the resource, you have to open it for yourself!
 47        """
 48        self.resource = resource
 49        self.pulse_duration: float = 0
 50        self.target_amps: float = 0
 51        self.reset()
 52
 53        @atexit.register
 54        def __atexit__():
 55            """Configure a safe shut down for when the class instance is destroyed."""
 56            self.disable()
 57
 58    def __call__(self, amps: float, mode=DischargeType.CONSTANT_CURRENT, resistance: float = 0.0):
 59        if mode is DischargeType.CONSTANT_CURRENT:
 60            self.mode_cc()
 61            if amps > 6:
 62                self.amps_range = 60  # if current is > 6A set to high range
 63            self.amps = amps
 64        elif mode is DischargeType.CONSTANT_RESISTANCE:
 65            self.mode_cr()
 66            self.ohms_resistance_range = 15000 if resistance > 15 else 15
 67            self.ohms_voltage_limit = 150
 68            self.ohms_current_limit = 10
 69            self.ohms = resistance
 70        elif mode is DischargeType.CONSTANT_VOLTAGE:
 71            self.mode_cv()
 72        return self
 73
 74    def __enter__(self):
 75        self.enable()
 76        return self
 77
 78    def __exit__(self, exc_type, exc_value, exc_traceback):
 79        self.disable()
 80
 81    def configure_pulse_trigger(self, pulse_current: float = 1.0, base_current: float = 0.0, duration: float = 0.25):
 82        """Set up pulse trigger values."""
 83        self.pulse_duration = duration
 84        self.resource.write(":SOUR:CURR:TRAN:MODE PULS")  # Pulse mode
 85        self.resource.write(f":SOUR:CURR:RANG {6 if max(pulse_current, base_current) <= 6 else 60}")  # Low range
 86        self.resource.write(f":SOUR:CURR:TRAN:ALEV {pulse_current}")  # pulse current
 87        self.resource.write(f":SOUR:CURR:TRAN:BLEV {base_current}")  # base current
 88        self.resource.write(f":SOUR:CURR:TRAN:AWID {duration * 1000:.0f}")  # pulse duration in milliseconds
 89        self.resource.write(":SOUR:CURR:SLEW:POS 0.5")  # 0.5A/us rising slew rate
 90        self.resource.write(":SOUR:CURR:SLEW:NEG 0.5")  # 0.5A/us falling slew rate
 91        self.resource.write(":TRIG:SOUR BUS")  # Allow bus command to fire trigger
 92
 93        # TODO(JA): is it worth using ":CURR:RANG? MAX" and ":CURR:RANG? MIN" instead of 60 and 6?
 94
 95    def configure_frequency_trigger(
 96        self, pulse_current: float = 1.840, base_current: float = 0.340, frequency_khz: float = 0.4
 97    ):
 98        """Set up pulse frequency values."""
 99        self.resource.write(":SOUR:CURR:TRAN:MODE CONT")  # Pulse mode
100        self.resource.write(f":SOUR:CURR:RANG {6 if max(pulse_current, base_current) <= 6 else 60}")  # Low range
101        self.resource.write(f":SOUR:CURR:TRAN:ALEV {pulse_current}")  # pulse current
102        self.resource.write(f":SOUR:CURR:TRAN:BLEV {base_current}")  # base current
103        self.resource.write(f":SOUR:CURR:TRAN:FREQ {frequency_khz}")  # pulse frequency in kHz
104        self.resource.write(":SOUR:CURR:SLEW:POS 0.5")  # 0.5A/us rising slew rate
105        self.resource.write(":SOUR:CURR:SLEW:NEG 0.5")  # 0.5A/us falling slew rate
106        self.resource.write(":TRIG:SOUR BUS")  # Allow bus command to fire trigger
107
108    def change_frequency(self, frequency_khz: float):
109        """Change frequency of pulse."""
110        self.resource.write(f":SOUR:CURR:TRAN:FREQ {frequency_khz}")
111
112    def transient_mode(self, active: bool):
113        """Turn on or off transient generator."""
114        self.resource.write(f":SOUR:TRAN {int(active)}")
115
116    def wait_for_pulse(self):
117        """Wait for load pulse to complete."""
118        sleep(self.pulse_duration * 2)
119
120    def send_trigger(self):
121        """Send a software trigger."""
122        self.resource.write(":TRIG")
123
124    @property
125    def volts(self) -> float:
126        """Measures load voltage."""
127        return float(self.resource.query(":MEAS:VOLT?"))
128
129    @volts.setter
130    def volts(self, new_volts: float):
131        """Sets load voltage."""
132        self.resource.write(f":SOURCE:VOLT:LEV:IMM {new_volts}")
133
134    @property
135    def amps(self) -> float:
136        """Measures load current."""
137        return float(self.resource.query(":MEAS:CURR?"))
138
139    @amps.setter
140    def amps(self, current: float):
141        """Sets load current."""
142        self.target_amps = -current
143        self.resource.write(f":SOURCE:CURRENT:LEV:IMM {current}")
144
145    @property
146    def ohms(self) -> float:
147        """Measures load resistance."""
148        return float(self.resource.query(":MEAS:RES?"))
149
150    @ohms.setter
151    def ohms(self, new_ohms: float):
152        """Sets load resistance."""
153        self.resource.write(f":SOURCE:RES:LEV:IMM {new_ohms}")
154
155    def _amps_range(self, new_amps_range: int):
156        """
157        Sets load current range
158        DL3031/DL3031A: low range (0 to 6 A); high range (0 to 60 A)
159        """
160        self.resource.write(f":SOURCE:CURR:RANG {new_amps_range}")
161
162    # make this function accessible as a write-only attribute
163    amps_range = property(None, _amps_range)
164
165    def _volts_range(self, new_volts_range: int):
166        """
167        Sets load voltage range
168        Two ranges are available: low range (0-15 V) and high range (0-150 V).
169        """
170        self.resource.write(f":SOURCE:VOLT:RANG {new_volts_range}")
171
172    # make this function accessible as a write-only attribute
173    volts_range = property(None, _volts_range)
174
175    def _ohms_resistance_range(self, resistance_range: float):
176        """
177        Working range for the resistance in CR mode.
178        Two resistance ranges are available: low range (0.08 Ω to 15 Ω); high range (2 Ω to 15 kΩ)
179        """
180        self.resource.write(f":SOURCE:RES:RANG {resistance_range}")
181
182    # make this function accessible as a write-only attribute
183    ohms_resistance_range = property(None, _ohms_resistance_range)
184
185    def _ohms_voltage_limit(self, voltage_limit: int):
186        """
187        The upper limit of the voltage working in CR mode.
188        The default unit for V_Limit is V, and it ranges from 0 V to 155 V.
189        """
190        self.resource.write(f":SOURCE:RES:VLIM {voltage_limit}")
191
192    # make this function accessible as a write-only attribute
193    ohms_voltage_limit = property(None, _ohms_voltage_limit)
194
195    def _ohms_current_limit(self, current_limit: int):
196        """
197        The upper limit of the current working in CR mode.
198        The default unit for C_Limit is A, and it ranges from 0 A to 70 A.
199        """
200        self.resource.write(f":SOURCE:RES:ILIM {current_limit}")
201
202    # make this function accessible as a write-only attribute
203    ohms_current_limit = property(None, _ohms_current_limit)
204
205    def mode_cc(self):
206        """Sets load to constant current mode."""
207        self.resource.write(":SOUR:FUNC CURR")
208
209    def mode_cr(self):
210        """Sets load to constant resistance mode."""
211        self.resource.write(":SOUR:FUNC RES")
212
213    def mode_cv(self):
214        """Sets load to constant voltage mode."""
215        self.resource.write(":SOUR:FUNC VOLT")
216
217    def enable(self):
218        """Enables the load input."""
219        logger.write_info_to_report("Enabling load")
220        Plateset().load_switch = True  # Turn on the load switch
221        sleep(1)  # Wait for relay
222        self.resource.write(":SOUR:INPUT:STAT ON")
223        sleep(1)  # This instrument needs time to initialize
224
225    def disable(self):
226        """Disables the load input."""
227        logger.write_info_to_report("Disabling load")
228        Plateset().load_switch = False  # Turn off the load switch
229        self.resource.write(":SOUR:INPUT:STAT OFF")
230        sleep(1)  # This instrument needs time to respond
231
232    def reset(self):
233        """Resets the instrument."""
234        self.resource.write("*RST")
class Load:
 41class Load:
 42    """Rigol DL3000 Electronic Load command wrapper."""
 43
 44    def __init__(self, resource: SafeResource):
 45        """
 46        Initialize the DL3000 wrapper with a specific PyVISA resource.
 47        This class does NOT open the resource, you have to open it for yourself!
 48        """
 49        self.resource = resource
 50        self.pulse_duration: float = 0
 51        self.target_amps: float = 0
 52        self.reset()
 53
 54        @atexit.register
 55        def __atexit__():
 56            """Configure a safe shut down for when the class instance is destroyed."""
 57            self.disable()
 58
 59    def __call__(self, amps: float, mode=DischargeType.CONSTANT_CURRENT, resistance: float = 0.0):
 60        if mode is DischargeType.CONSTANT_CURRENT:
 61            self.mode_cc()
 62            if amps > 6:
 63                self.amps_range = 60  # if current is > 6A set to high range
 64            self.amps = amps
 65        elif mode is DischargeType.CONSTANT_RESISTANCE:
 66            self.mode_cr()
 67            self.ohms_resistance_range = 15000 if resistance > 15 else 15
 68            self.ohms_voltage_limit = 150
 69            self.ohms_current_limit = 10
 70            self.ohms = resistance
 71        elif mode is DischargeType.CONSTANT_VOLTAGE:
 72            self.mode_cv()
 73        return self
 74
 75    def __enter__(self):
 76        self.enable()
 77        return self
 78
 79    def __exit__(self, exc_type, exc_value, exc_traceback):
 80        self.disable()
 81
 82    def configure_pulse_trigger(self, pulse_current: float = 1.0, base_current: float = 0.0, duration: float = 0.25):
 83        """Set up pulse trigger values."""
 84        self.pulse_duration = duration
 85        self.resource.write(":SOUR:CURR:TRAN:MODE PULS")  # Pulse mode
 86        self.resource.write(f":SOUR:CURR:RANG {6 if max(pulse_current, base_current) <= 6 else 60}")  # Low range
 87        self.resource.write(f":SOUR:CURR:TRAN:ALEV {pulse_current}")  # pulse current
 88        self.resource.write(f":SOUR:CURR:TRAN:BLEV {base_current}")  # base current
 89        self.resource.write(f":SOUR:CURR:TRAN:AWID {duration * 1000:.0f}")  # pulse duration in milliseconds
 90        self.resource.write(":SOUR:CURR:SLEW:POS 0.5")  # 0.5A/us rising slew rate
 91        self.resource.write(":SOUR:CURR:SLEW:NEG 0.5")  # 0.5A/us falling slew rate
 92        self.resource.write(":TRIG:SOUR BUS")  # Allow bus command to fire trigger
 93
 94        # TODO(JA): is it worth using ":CURR:RANG? MAX" and ":CURR:RANG? MIN" instead of 60 and 6?
 95
 96    def configure_frequency_trigger(
 97        self, pulse_current: float = 1.840, base_current: float = 0.340, frequency_khz: float = 0.4
 98    ):
 99        """Set up pulse frequency values."""
100        self.resource.write(":SOUR:CURR:TRAN:MODE CONT")  # Pulse mode
101        self.resource.write(f":SOUR:CURR:RANG {6 if max(pulse_current, base_current) <= 6 else 60}")  # Low range
102        self.resource.write(f":SOUR:CURR:TRAN:ALEV {pulse_current}")  # pulse current
103        self.resource.write(f":SOUR:CURR:TRAN:BLEV {base_current}")  # base current
104        self.resource.write(f":SOUR:CURR:TRAN:FREQ {frequency_khz}")  # pulse frequency in kHz
105        self.resource.write(":SOUR:CURR:SLEW:POS 0.5")  # 0.5A/us rising slew rate
106        self.resource.write(":SOUR:CURR:SLEW:NEG 0.5")  # 0.5A/us falling slew rate
107        self.resource.write(":TRIG:SOUR BUS")  # Allow bus command to fire trigger
108
109    def change_frequency(self, frequency_khz: float):
110        """Change frequency of pulse."""
111        self.resource.write(f":SOUR:CURR:TRAN:FREQ {frequency_khz}")
112
113    def transient_mode(self, active: bool):
114        """Turn on or off transient generator."""
115        self.resource.write(f":SOUR:TRAN {int(active)}")
116
117    def wait_for_pulse(self):
118        """Wait for load pulse to complete."""
119        sleep(self.pulse_duration * 2)
120
121    def send_trigger(self):
122        """Send a software trigger."""
123        self.resource.write(":TRIG")
124
125    @property
126    def volts(self) -> float:
127        """Measures load voltage."""
128        return float(self.resource.query(":MEAS:VOLT?"))
129
130    @volts.setter
131    def volts(self, new_volts: float):
132        """Sets load voltage."""
133        self.resource.write(f":SOURCE:VOLT:LEV:IMM {new_volts}")
134
135    @property
136    def amps(self) -> float:
137        """Measures load current."""
138        return float(self.resource.query(":MEAS:CURR?"))
139
140    @amps.setter
141    def amps(self, current: float):
142        """Sets load current."""
143        self.target_amps = -current
144        self.resource.write(f":SOURCE:CURRENT:LEV:IMM {current}")
145
146    @property
147    def ohms(self) -> float:
148        """Measures load resistance."""
149        return float(self.resource.query(":MEAS:RES?"))
150
151    @ohms.setter
152    def ohms(self, new_ohms: float):
153        """Sets load resistance."""
154        self.resource.write(f":SOURCE:RES:LEV:IMM {new_ohms}")
155
156    def _amps_range(self, new_amps_range: int):
157        """
158        Sets load current range
159        DL3031/DL3031A: low range (0 to 6 A); high range (0 to 60 A)
160        """
161        self.resource.write(f":SOURCE:CURR:RANG {new_amps_range}")
162
163    # make this function accessible as a write-only attribute
164    amps_range = property(None, _amps_range)
165
166    def _volts_range(self, new_volts_range: int):
167        """
168        Sets load voltage range
169        Two ranges are available: low range (0-15 V) and high range (0-150 V).
170        """
171        self.resource.write(f":SOURCE:VOLT:RANG {new_volts_range}")
172
173    # make this function accessible as a write-only attribute
174    volts_range = property(None, _volts_range)
175
176    def _ohms_resistance_range(self, resistance_range: float):
177        """
178        Working range for the resistance in CR mode.
179        Two resistance ranges are available: low range (0.08 Ω to 15 Ω); high range (2 Ω to 15 kΩ)
180        """
181        self.resource.write(f":SOURCE:RES:RANG {resistance_range}")
182
183    # make this function accessible as a write-only attribute
184    ohms_resistance_range = property(None, _ohms_resistance_range)
185
186    def _ohms_voltage_limit(self, voltage_limit: int):
187        """
188        The upper limit of the voltage working in CR mode.
189        The default unit for V_Limit is V, and it ranges from 0 V to 155 V.
190        """
191        self.resource.write(f":SOURCE:RES:VLIM {voltage_limit}")
192
193    # make this function accessible as a write-only attribute
194    ohms_voltage_limit = property(None, _ohms_voltage_limit)
195
196    def _ohms_current_limit(self, current_limit: int):
197        """
198        The upper limit of the current working in CR mode.
199        The default unit for C_Limit is A, and it ranges from 0 A to 70 A.
200        """
201        self.resource.write(f":SOURCE:RES:ILIM {current_limit}")
202
203    # make this function accessible as a write-only attribute
204    ohms_current_limit = property(None, _ohms_current_limit)
205
206    def mode_cc(self):
207        """Sets load to constant current mode."""
208        self.resource.write(":SOUR:FUNC CURR")
209
210    def mode_cr(self):
211        """Sets load to constant resistance mode."""
212        self.resource.write(":SOUR:FUNC RES")
213
214    def mode_cv(self):
215        """Sets load to constant voltage mode."""
216        self.resource.write(":SOUR:FUNC VOLT")
217
218    def enable(self):
219        """Enables the load input."""
220        logger.write_info_to_report("Enabling load")
221        Plateset().load_switch = True  # Turn on the load switch
222        sleep(1)  # Wait for relay
223        self.resource.write(":SOUR:INPUT:STAT ON")
224        sleep(1)  # This instrument needs time to initialize
225
226    def disable(self):
227        """Disables the load input."""
228        logger.write_info_to_report("Disabling load")
229        Plateset().load_switch = False  # Turn off the load switch
230        self.resource.write(":SOUR:INPUT:STAT OFF")
231        sleep(1)  # This instrument needs time to respond
232
233    def reset(self):
234        """Resets the instrument."""
235        self.resource.write("*RST")

Rigol DL3000 Electronic Load command wrapper.

Load(resource: hitl_tester.modules.bms_types.SafeResource)
44    def __init__(self, resource: SafeResource):
45        """
46        Initialize the DL3000 wrapper with a specific PyVISA resource.
47        This class does NOT open the resource, you have to open it for yourself!
48        """
49        self.resource = resource
50        self.pulse_duration: float = 0
51        self.target_amps: float = 0
52        self.reset()
53
54        @atexit.register
55        def __atexit__():
56            """Configure a safe shut down for when the class instance is destroyed."""
57            self.disable()

Initialize the DL3000 wrapper with a specific PyVISA resource. This class does NOT open the resource, you have to open it for yourself!

resource
pulse_duration: float
target_amps: float
def configure_pulse_trigger( self, pulse_current: float = 1.0, base_current: float = 0.0, duration: float = 0.25):
82    def configure_pulse_trigger(self, pulse_current: float = 1.0, base_current: float = 0.0, duration: float = 0.25):
83        """Set up pulse trigger values."""
84        self.pulse_duration = duration
85        self.resource.write(":SOUR:CURR:TRAN:MODE PULS")  # Pulse mode
86        self.resource.write(f":SOUR:CURR:RANG {6 if max(pulse_current, base_current) <= 6 else 60}")  # Low range
87        self.resource.write(f":SOUR:CURR:TRAN:ALEV {pulse_current}")  # pulse current
88        self.resource.write(f":SOUR:CURR:TRAN:BLEV {base_current}")  # base current
89        self.resource.write(f":SOUR:CURR:TRAN:AWID {duration * 1000:.0f}")  # pulse duration in milliseconds
90        self.resource.write(":SOUR:CURR:SLEW:POS 0.5")  # 0.5A/us rising slew rate
91        self.resource.write(":SOUR:CURR:SLEW:NEG 0.5")  # 0.5A/us falling slew rate
92        self.resource.write(":TRIG:SOUR BUS")  # Allow bus command to fire trigger
93
94        # TODO(JA): is it worth using ":CURR:RANG? MAX" and ":CURR:RANG? MIN" instead of 60 and 6?

Set up pulse trigger values.

def configure_frequency_trigger( self, pulse_current: float = 1.84, base_current: float = 0.34, frequency_khz: float = 0.4):
 96    def configure_frequency_trigger(
 97        self, pulse_current: float = 1.840, base_current: float = 0.340, frequency_khz: float = 0.4
 98    ):
 99        """Set up pulse frequency values."""
100        self.resource.write(":SOUR:CURR:TRAN:MODE CONT")  # Pulse mode
101        self.resource.write(f":SOUR:CURR:RANG {6 if max(pulse_current, base_current) <= 6 else 60}")  # Low range
102        self.resource.write(f":SOUR:CURR:TRAN:ALEV {pulse_current}")  # pulse current
103        self.resource.write(f":SOUR:CURR:TRAN:BLEV {base_current}")  # base current
104        self.resource.write(f":SOUR:CURR:TRAN:FREQ {frequency_khz}")  # pulse frequency in kHz
105        self.resource.write(":SOUR:CURR:SLEW:POS 0.5")  # 0.5A/us rising slew rate
106        self.resource.write(":SOUR:CURR:SLEW:NEG 0.5")  # 0.5A/us falling slew rate
107        self.resource.write(":TRIG:SOUR BUS")  # Allow bus command to fire trigger

Set up pulse frequency values.

def change_frequency(self, frequency_khz: float):
109    def change_frequency(self, frequency_khz: float):
110        """Change frequency of pulse."""
111        self.resource.write(f":SOUR:CURR:TRAN:FREQ {frequency_khz}")

Change frequency of pulse.

def transient_mode(self, active: bool):
113    def transient_mode(self, active: bool):
114        """Turn on or off transient generator."""
115        self.resource.write(f":SOUR:TRAN {int(active)}")

Turn on or off transient generator.

def wait_for_pulse(self):
117    def wait_for_pulse(self):
118        """Wait for load pulse to complete."""
119        sleep(self.pulse_duration * 2)

Wait for load pulse to complete.

def send_trigger(self):
121    def send_trigger(self):
122        """Send a software trigger."""
123        self.resource.write(":TRIG")

Send a software trigger.

volts: float
125    @property
126    def volts(self) -> float:
127        """Measures load voltage."""
128        return float(self.resource.query(":MEAS:VOLT?"))

Measures load voltage.

amps: float
135    @property
136    def amps(self) -> float:
137        """Measures load current."""
138        return float(self.resource.query(":MEAS:CURR?"))

Measures load current.

ohms: float
146    @property
147    def ohms(self) -> float:
148        """Measures load resistance."""
149        return float(self.resource.query(":MEAS:RES?"))

Measures load resistance.

amps_range
volts_range
ohms_resistance_range
ohms_voltage_limit
ohms_current_limit
def mode_cc(self):
206    def mode_cc(self):
207        """Sets load to constant current mode."""
208        self.resource.write(":SOUR:FUNC CURR")

Sets load to constant current mode.

def mode_cr(self):
210    def mode_cr(self):
211        """Sets load to constant resistance mode."""
212        self.resource.write(":SOUR:FUNC RES")

Sets load to constant resistance mode.

def mode_cv(self):
214    def mode_cv(self):
215        """Sets load to constant voltage mode."""
216        self.resource.write(":SOUR:FUNC VOLT")

Sets load to constant voltage mode.

def enable(self):
218    def enable(self):
219        """Enables the load input."""
220        logger.write_info_to_report("Enabling load")
221        Plateset().load_switch = True  # Turn on the load switch
222        sleep(1)  # Wait for relay
223        self.resource.write(":SOUR:INPUT:STAT ON")
224        sleep(1)  # This instrument needs time to initialize

Enables the load input.

def disable(self):
226    def disable(self):
227        """Disables the load input."""
228        logger.write_info_to_report("Disabling load")
229        Plateset().load_switch = False  # Turn off the load switch
230        self.resource.write(":SOUR:INPUT:STAT OFF")
231        sleep(1)  # This instrument needs time to respond

Disables the load input.

def reset(self):
233    def reset(self):
234        """Resets the instrument."""
235        self.resource.write("*RST")

Resets the instrument.