serial_instruments
unknown
python
2 years ago
12 kB
6
Indexable
import serial
from time import sleep, time
import serial.tools.list_ports
def printCOMports(showIDN=True):
ports = serial.tools.list_ports.comports()
for port, desc, hwid in sorted(ports):
print("{}: {} [{}]".format(port, desc, hwid))
if showIDN:
try:
inst = SerialInstrument(port)
IDN = inst.get_idn()
print('\t' + IDN)
except:
pass
# Set instrument to remote mode to be able to control it
class SerialInstrument:
def __init__(self, COMport, timeout=2, baudrate=9600, EOL='\r\n', removeEOL=True, tsleep=0):
self.serial = serial.Serial()
self.serial.port = COMport
self.serial.timeout = timeout
self.serial.baudrate = baudrate
self.EOL = EOL
self.removeEOL = removeEOL
self.tsleep = tsleep
if not self.serial.is_open:
self.serial.open()
def write(self, command):
self.serial.write((command + self.EOL).encode())
sleep(self.tsleep)
def read(self):
answer = self.serial.readline().decode()
if self.removeEOL:
answer = answer.rstrip(self.EOL)
return answer
def query(self, command):
self.write(command)
return self.read()
def remote_mode(self):
self.write('SYST:REM')
def local_mode(self):
self.write('SYST:LOC')
def get_idn(self):
return self.query('*IDN?')
def get_error(self):
return self.query('SYST:ERR?')
def get_version(self):
return self.query('SYST:VERS?')
def beep(self):
self.write('SYST:BEEP')
def reset(self):
self.write('*RST')
def cls(self): # Clear status (clear errors)
self.write('*CLS')
def display_on(self):
self.write('DISP ON')
def display_off(self):
self.write('DISP OFF')
# Multimeter Hewlett Packard 34401A
class HP34401A(SerialInstrument):
def __init__(self, COMport, timeout=2, baudrate=9600, EOL='\r\n', removeEOL=True, tsleep=0.15):
super().__init__(COMport, timeout, baudrate, EOL, removeEOL, tsleep)
self.__modes = {
'VDC': ['CONF:VOLT:DC DEF, DEF', 'DC Voltage measurement'],
'VAC': ['CONF:VOLT:AC DEF, DEF', 'AC Voltage measurement'],
'IDC': ['CONF:CURR:DC DEF, DEF', 'DC Current measurement'],
'IAC': ['CONF:CURR:AC DEF, DEF', 'AC Current measurement'],
'R': ['CONF:RES DEF, DEF', '2-wire resistance measurement'],
'R4W': ['CONF:FRES DEF, DEF', '4-wire resistance measurement'],
'F': ['CONF:FREQ DEF, DEF', 'Frequency measurement'],
'T': ['CONF:PER DEF, DEF', 'Period measurement']
}
def help_modes(self):
for mode in self.__modes:
comment = self.__modes[mode][1]
print(mode + ': ' + comment)
def meas(self, mode='VDC', num_of_samples=1):
cmd_mode = self.__modes[mode][0]
self.write(cmd_mode)
cmd = 'SAMP:COUN ' + str(num_of_samples)
self.write(cmd)
self.write('READ?')
sleep(0.4*num_of_samples)
data_str = self.read()
data = []
for str_value in data_str.split(','):
if str_value:
data.append(float(str_value))
if len(data) == 1:
return data[0]
else:
return data
def display_text(self, text):
# Display has 12 characters
# It is recommended to use uppercase
self.write('DISP:TEXT "' + text[:12] + '"')
def running_text(self, text):
# Set self.tsleep time to change speed of running text
# Recomended = 0.15
text = ' '*12 + text
tstart = time()
i = 0
text_len = len(text)
while i <= text_len:
self.display_text(text[i:])
i += 1
def display_clear(self):
self.write('DISP:TEXT:CLE')
# Power Supply BK Precision 9129B
class BK9129B(SerialInstrument):
def __init__(self, COMport, timeout=2, baudrate=9600, EOL='\r\n', removeEOL=True, tsleep=0):
super().__init__(COMport, timeout, baudrate, EOL, removeEOL, tsleep)
self.__voltages = [0, 0, 0]
self.__currents = [0, 0, 0]
self.__outputs = [0, 0, 0]
self.__CH_selected = 0
def reset(self):
self.write('*RST')
self.__voltages = [0, 0, 0]
self.__currents = [3.1, 3.1, 3.1]
self.__outputs = [0, 0, 0]
self.__CH_selected = 0
def __select_channel(self, CH_num):
if self.__CH_selected != CH_num:
self.write('INST:NSEL ' + str(CH_num))
self.__CH_selected = CH_num
def __send_channel_command(self, channel, command, value):
self.__select_channel(channel)
self.write(command + ' ' + str(value))
if command == 'VOLT':
self.__voltages[channel - 1] = value
elif command == 'CURR':
self.__currents[channel - 1] = value
elif command == 'CHAN:OUTP':
self.__outputs[channel - 1] = value
def __meas_value(self, channel, value_str):
measured = None
data = ''
if isinstance(channel, int):
ch = 'CH' + str(channel)
data = self.query('MEAS:' + value_str + '? ' + ch)
if data:
measured = float(data)
return measured
def meas_current(self, channel):
return self.__meas_value(channel, 'CURR')
def meas_voltage(self, channel):
return self.__meas_value(channel, 'VOLT')
def meas_power(self, channel):
return self.__meas_value(channel, 'POW')
def __meas_values(self, value_str):
measured = []
data = self.query('MEAS:' + value_str + '? ALL')
if data:
measured = [float(i) for i in data.split(', ')]
return measured
def meas_currents(self):
return self.__meas_values('CURR')
def meas_voltages(self):
return self.__meas_values('VOLT')
def meas_powers(self):
return self.__meas_values('POW')
@property
def voltage1(self):
return self.__voltages[0]
@voltage1.setter
def voltage1(self, value):
self.__send_channel_command(1, 'VOLT', value)
@property
def voltage2(self):
return self.__voltages[1]
@voltage2.setter
def voltage2(self, value):
self.__send_channel_command(2, 'VOLT', value)
@property
def voltage3(self):
return self.__voltages[2]
@voltage3.setter
def voltage3(self, value):
self.__send_channel_command(3, 'VOLT', value)
@property
def current1(self):
return self.__currents[0]
@current1.setter
def current1(self, value):
self.__send_channel_command(1, 'CURR', value)
@property
def current2(self):
return self.__currents[1]
@current2.setter
def current2(self, value):
self.__send_channel_command(2, 'CURR', value)
@property
def current3(self):
return self.__currents[2]
@current3.setter
def current3(self, value):
self.__send_channel_command(3, 'CURR', value)
@property
def output1(self):
return self.__outputs[0]
@output1.setter
def output1(self, value):
self.__send_channel_command(1, 'CHAN:OUTP', value)
@property
def output2(self):
return self.__outputs[1]
@output2.setter
def output2(self, value):
self.__send_channel_command(2, 'CHAN:OUTP', value)
@property
def output3(self):
return self.__outputs[2]
@output3.setter
def output3(self, value):
self.__send_channel_command(3, 'CHAN:OUTP', value)
@property
def voltages(self):
return self.__voltages
@voltages.setter
def voltages(self, values):
self.__voltages = values
self.write('APP:VOLT ' + ','.join(str(value) for value in values))
@property
def currents(self):
return self.__currents
@currents.setter
def currents(self, values):
self.__currents = values
self.write('APP:CURR ' + ','.join(str(value) for value in values))
@property
def outputs(self):
return self.__outputs
@outputs.setter
def outputs(self, values):
self.__outputs = values
self.write('APP:OUT ' + ','.join(str(value) for value in values))
# Power Supply BK Precision 9201B
class BK9201B(SerialInstrument):
def __init__(self, COMport, timeout=2, baudrate=9600, EOL='\r\n', removeEOL=True, tsleep=0):
super().__init__(COMport, timeout, baudrate, EOL, removeEOL, tsleep)
self.__voltage = 0
self.__current = 0
self.__output = 0
def reset(self):
self.write('*RST')
self.__voltage = 0
self.__current = 10.1
self.__output = 0
def __meas_value(self, value_str):
measured = None
data = self.query('MEAS:' + value_str + '? ')
if data:
measured = float(data)
return measured
def meas_current(self):
return self.__meas_value('CURR')
def meas_voltage(self):
return self.__meas_value('VOLT')
def meas_power(self):
return self.__meas_value('POW')
@property
def voltage(self):
return self.__voltage
@voltage.setter
def voltage(self, value):
self.write('VOLT ' + str(value))
self.__voltage = value
@property
def current(self):
return self.__current
@current.setter
def current(self, value):
self.write('CURR ' + str(value))
self.__current = value
@property
def output(self):
return self.__output
@output.setter
def output(self, value):
self.write('OUTP ' + str(value))
self.__output = value
# Universal calibrator Digistant 4420-V001
class DIGISTANT4420(SerialInstrument):
def __init__(self, COMport, timeout=2, baudrate=9600, EOL='\r\n', removeEOL=True, tsleep=0):
super().__init__(COMport, timeout, baudrate, EOL, removeEOL, tsleep)
self._stx = chr(2) # '\x02' - start of text
self._eot = chr(4) # '\x04' - end of transmition
self._etx = chr(3) # '\x03' - end of text
self._enq = chr(5) # '\x05' - enquiry
self._ack = chr(6) # '\x06' - acknowledge
self._nak = chr(21) # '\x15' - negative acknowledge
self._cr = chr(13) # '\x0d' = '\r' - carriage return
self._lf = chr(10) # '\x0a' = '\n' - new line / line feed
self._esc = chr(27) # '\x1b' - escape
self._select = self._eot + '0000SR' + self._enq
self._polling = self._eot + '0000PO' + self._enq
def write(self, command):
self.serial.write(self._select.encode())
sleep(self.tsleep)
self.serial.write((self._stx + command + self.EOL + self._etx).encode())
sleep(self.tsleep)
def read(self):
self.serial.reset_input_buffer()
self.serial.write(self._polling.encode())
sleep(self.tsleep)
answer = self.serial.readline().decode()
while len(answer) > 1 and not answer[0].isalnum():
answer = answer[1:]
if not answer[0].isalnum():
answer = self.serial.readline().decode()
while len(answer) > 1 and not answer[0].isalnum():
answer = answer[1:]
if self.removeEOL:
answer = answer.rstrip(self.EOL)
return answer
def query(self, command):
self.write(command)
return self.read()
"""
# Example code to test class:
bk = BK9129B('COM5')
bk.remote_mode()
bk.voltages = [10, 5, 3]
bk.currents = [2,1,0.2]
bk.outputs = [1,1,0]
bk.voltage1 = 12
print(bk.meas_voltage(1))
print(bk.meas_voltages())
"""
Editor is loading...
Leave a Comment