From 95ca85fd9cf3a831331a345f95f1065fe2e6a584 Mon Sep 17 00:00:00 2001 From: Oksana Shliakhtun Date: Tue, 23 Apr 2024 17:20:55 +0200 Subject: [PATCH] Frappy driver for a HP multimeter Change-Id: I2e9dc5131ea9a7317d69c42dd49388216e77f72f --- frappy_psi/HP.py | 78 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/frappy_psi/HP.py b/frappy_psi/HP.py index 2d27223..2477456 100644 --- a/frappy_psi/HP.py +++ b/frappy_psi/HP.py @@ -18,7 +18,7 @@ # Module authors: Oksana Shliakhtun # ***************************************************************************** import re -from frappy.core import HasIO, Readable, Parameter, FloatRange, EnumType, StatusType, Drivable +from frappy.core import HasIO, Readable, Parameter, FloatRange, EnumType, StatusType, IDLE, ERROR, WARN def string_to_value(value): @@ -68,50 +68,83 @@ class HP34401A(HP_IO): self.comm(f'{function}:resolution {resolution}') return self.comm(f'{function}:resolution?') + def read_status(self): + stb = int(self.comm('*STB?')) + esr = int(self.comm('*ESR?')) + + if esr & (1 << 3): + return ERROR, 'self-test/calibration/reading failed' + if esr & (1 << 4): + return ERROR, 'execution error' + if esr & (1 << 5): + return ERROR, 'syntax error' + if esr & (1 << 2): + return ERROR, 'query error' + if stb & (1 << 3): + return WARN, 'questionable data' + if stb & (1 << 5): + return WARN, 'standard event register is not empty' + if stb & (1 << 6): + return WARN, 'requested service' + + if any(stb & (1 << i) for i in range(3) or stb & (1 << 7)): + return IDLE, '' + if esr & (1 << 6): + return IDLE, '' + if esr & (1 << 7): + return IDLE, '' + if stb & (1 << 4): + return IDLE, 'message available' + if esr & (1 << 0): + return IDLE, 'operation complete' + if esr & (1 << 1): + return IDLE, 'not used' + class Voltage(HP34401A, Readable): value = Parameter('voltage', datatype=FloatRange(0.1, 1000), unit='V') range = Parameter('voltage sensitivity value', FloatRange(), unit='V', default=1, readonly=False) resolution = Parameter('resolution') - mode = Parameter('measurement mode: ac/dc', EnumType(AC=1, DC=2), readonly=False) + mode = Parameter('measurement mode: ac/dc', readonly=False) ioClass = HP_IO + MODE_NAMES = {0: 'dc', 1: 'ac'} VOLT_RANGE = ['100mV', '1V', '10V', '100V', '1000V'] v_range = Parameter('voltage range', EnumType('voltage index range', - {name: idx for idx, name in enumerate(VOLT_RANGE)}), readonly=False) + {name: idx for idx, name in enumerate(VOLT_RANGE)}), readonly=False) + + acdc = None def write_mode(self, mode): if mode == 1: self.comm(f'configure:voltage:AC {self.range}, {self.resolution}') else: self.comm(f'configure:voltage:DC {self.range}, {self.resolution}') + self.acdc = self.MODE_NAMES[mode] return self.comm(f'function?') def read_value(self): self.comm(f'measure:voltage:') def write_autorange_acdc(self, function): - mode_pr = {1: f'{function}:ac', 2: f'{function}:dc'} - full_function = mode_pr[self.mode] + full_function = f'{function}:{self.acdc}' return self.write_autorange(full_function) def read_range_voltage(self): - return self.read_range(f'voltage:{"ac" if self.mode == 1 else "dc"}') + return self.read_range(f'voltage:{self.acdc}') def write_range_voltage(self, range): - type = 'ac' if self.mode == 1 else 'dc' - return self.write_range(f'voltage:{type}', range) + return self.write_range(f'voltage:{self.acdc}', range) def write_autorange_voltage(self): return self.write_autorange_acdc('voltage') def read_resolution_voltage(self): - type = 'ac' if self.mode == 1 else 'dc' - return self.read_resolution(f'voltage:{type}') + return self.read_resolution(f'voltage:{self.acdc}') def write_resolution_voltage(self, resolution): - return self.write_resolution(f'voltage:{"ac" if self.mode == 1 else "dc"}', resolution) + return self.write_resolution(f'voltage:{self.acdc}', resolution) class Current(HP34401A, Readable, Voltage): @@ -121,38 +154,42 @@ class Current(HP34401A, Readable, Voltage): CURR_RANGE_DC = ['1A', '3A'] def read_range_current(self): - return self.read_range(f'current:{"ac" if self.mode == 1 else "dc"}') + return self.read_range(f'current:{self.acdc}') def write_autrange_current(self): return self.write_autorange_acdc('current') def write_range_current(self, range): - return self.write_range(f'current:{"ac" if self.mode == 1 else "dc"}', range) + return self.write_range(f'current:{self.acdc}', range) def read_resolution_current(self): - type = 'ac' if self.mode == 1 else 'dc' - return self.read_resolution(f'current:{type}') + return self.read_resolution(f'current:{self.acdc}') def write_resolution_current(self, resolution): - return self.write_resolution(f'current:{"ac" if self.mode == 1 else "dc"}', resolution) + return self.write_resolution(f'current:{self.acdc}', resolution) class Resistance(HP34401A, Readable): value = Parameter('resistance') mode = Parameter('measurement mode: 2-/4-wire ohms', EnumType(two_wire=2, four_wire=4), readonly=False) - resolution = Parameter('resistance resolution') + resolution = Parameter('resistance measurement resolution') + range = Parameter('resistance measurement range') RESIST_RANGE = ['100Om', '1kOm', '10kOm', '100kOm', '1MOm', '10MOm', '100MOm'] FUNCTION_MAP = {2: 'resistance', 4: 'fresistance'} - def write_mode(self, mode): - pass # configure:... - def write_range_resistance(self, range): return self.write_range(f'{self.FUNCTION_MAP[self.mode]}', range) def read_range_resistance(self): return self.read_range(f'{self.FUNCTION_MAP[self.mode]}') + def write_mode(self, mode): + if mode == 2: + self.comm(f'configure:resistance {self.range},{self.resolution}') + elif mode == 4: + self.comm(f'configure:fresistance {self.range}, {self.resolution}') + return self.comm('configure?') + def write_autorange_resistance(self): return self.write_autorange(self.FUNCTION_MAP[self.mode]) @@ -174,4 +211,3 @@ class Frequency(HP34401A, Readable): def write_resolution_frequency(self, resolution): return self.write_resolution('frequency', resolution) -