def status_string(self): """ Status code and human-readable status string for the VISA bus Returns: str: Status string Example: '0x0 VI_SUCCESS Operation completed successfully.' """ result = '{0} {1} {2}' value = self._instr.last_status.value status = VisaIOError(value) return result.format(hex(value), status.abbreviation, status.description)
class AbstractSerialDeviceDriver(AbstractVISADriver): """Abstract Device driver class """ timeouterror = VisaIOError(-1073807339) def __init__(self, timeout=500, read_termination="\r", write_termination="\r", baud_rate=9600, data_bits=8, **kwargs): super().__init__(**kwargs) # self._visa_resource.query_delay = 0. self._visa_resource.timeout = timeout self._visa_resource.read_termination = read_termination self._visa_resource.write_termination = write_termination self._visa_resource.baud_rate = baud_rate self._visa_resource.data_bits = data_bits self._visa_resource.stop_bits = vconst.StopBits.two self._visa_resource.parity = vconst.Parity.none self.delay = 0.1 self.delay_force = 0.1 def clear_buffers(self): # self._visa_resource.timeout = 5 try: # with self._comLock: self.read() except VisaIOError as e_visa: if (isinstance(e_visa, type(self.timeouterror)) and e_visa.args == self.timeouterror.args): pass else: raise e_visa
class OxfordInstrumentsAdapter(VISAAdapter): """Adapter class for the VISA library using PyVISA to communicate with instruments. Checks the replies from instruments for validity. :param resource_name: VISA resource name that identifies the address :param max_attempts: Integer that sets how many attempts at getting a valid response to a query can be made :param kwargs: key-word arguments for constructing a PyVISA Adapter """ timeoutError = VisaIOError(-1073807339) regex_pattern = r"^([a-zA-Z])[\d.+-]*$" def __init__(self, resource_name, max_attempts=5, **kwargs): super().__init__(resource_name, **kwargs) self.max_attempts = max_attempts def ask(self, command): """Write the command to the instrument and return the resulting ASCII response. Also check the validity of the response before returning it; if the response is not valid, another attempt is made at getting a valid response, until the maximum amount of attempts is reached. :param command: ASCII command string to be sent to the instrument :returns: String ASCII response of the instrument :raises: :class:`~.OxfordVISAError` if the maximum number of attempts is surpassed without getting a valid response """ for attempt in range(self.max_attempts): response = super().ask(command) if self.is_valid_response(response, command): return response log.debug("Received invalid response to '%s': %s", command, response) # Clear the buffer and try again try: self.read() except VisaIOError as e_visa: if e_visa.args == self.timeoutError.args: pass else: raise e_visa # No valid response has been received within the maximum allowed number of attempts raise OxfordVISAError( f"Retried {self.max_attempts} times without getting a valid " "response, maybe there is something worse at hand.") def write(self, command): """Write command to instrument and check whether the reply indicates that the given command was not understood. The devices from Oxford Instruments reply with '?xxx' to a command 'xxx' if this command is not known, and replies with 'x' if the command is understood. If the command starts with an "$" the instrument will not reply at all; hence in that case there will be done no checking for a reply. :raises: :class:`~.OxfordVISAError` if the instrument does not recognise the supplied command or if the response of the instrument is not understood """ super().write(command) if not command[0] == "$": response = self.read() log.debug( "Wrote '%s' to instrument; instrument responded with: '%s'", command, response, ) if not self.is_valid_response(response, command): if response[0] == "?": raise OxfordVISAError( "The instrument did not understand this command: " f"{command}") else: raise OxfordVISAError( f"The response of the instrument to command '{command}' " f"is not valid: '{response}'") def is_valid_response(self, response, command): """Check if the response received from the instrument after a command is valid and understood by the instrument. :param response: String ASCII response of the device :param command: command used in the initial query :returns: True if the response is valid and the response indicates the instrument recognised the command """ # Handle special cases # Check if the response indicates that the command is not recognized if response[0] == "?": log.debug("The instrument did not understand this command: %s", command) return False # Handle a special case for when the status is queried if command[0] == "X" and response[0] == "X": return True # Handle a special case for when the version is queried if command[0] == "V": return True # Handle the other, standard cases try: match = re.match(self.regex_pattern, response) except TypeError: match = False if match and not match.groups()[0] == command[0]: match = False return bool(match) def __repr__(self): return "<OxfordInstrumentsAdapter(resource='%s')>" % self.connection.resource_name
class Keithley2182_Updater(AbstractLoopThread): """This is the worker thread, which updates all instrument data of the self.ITC 503. For each self.ITC503 function (except collecting data), there is a wrapping method, which we can call by a signal, from the main thread. This wrapper sends the corresponding value to the device. There is a second method for all wrappers, which accepts the corresponding value, and stores it, so it can be sent upon acknowledgment The information from the device is collected in regular intervals (method "running"), and subsequently sent to the main thread. It is packed in a dict, the keys of which are displayed in the "sensors" dict in this class. """ sig_Infodata = pyqtSignal(dict) # sig_assertion = pyqtSignal(str) sig_visaerror = pyqtSignal(str) sig_visatimeout = pyqtSignal() timeouterror = VisaIOError(-1073807339) sensors = dict(Voltage_DC=None, Temperature_K=None) def __init__(self, InstrumentAddress='', **kwargs): super().__init__(**kwargs) self.Keithley2182 = Keithley2182(InstrumentAddress=InstrumentAddress) # self.delay1 = 1 # self.delay = 0.0 # self.setControl() # self.__isRunning = True # @control_checks def running(self): """Try to extract all current data from the ITC, and emit signal, sending the data self.delay2 should be at at least 0.4 to ensure relatively error-free communication with ITC over serial RS-232 connection. (this worked on Benjamin's PC, to be checked with any other PC, so errors which come back are "caught", or communication is set up in a way no errors occur) """ try: self.sensors['Voltage_DC'] = self.Keithley2182.measureVoltage() self.sensors[ 'Temperature_K'] = self.Keithley2182.measureTemperatre() self.sig_Infodata.emit(deepcopy(sensors)) # time.sleep(self.delay1) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0])
class AbstractSerialDeviceDriver(object): """Abstract Device driver class""" timeouterror = VisaIOError(-1073807339) def __init__(self, InstrumentAddress): super(AbstractSerialDeviceDriver, self).__init__() self._visa_resource = resource_manager.open_resource(InstrumentAddress) # self._visa_resource.query_delay = 0. self._visa_resource.timeout = 500 self._visa_resource.read_termination = '\r' self._visa_resource.write_termination = '\r' self._visa_resource.baud_rate = 9600 self._visa_resource.data_bits = 8 self._visa_resource.stop_bits = vconst.StopBits.two self._visa_resource.parity = vconst.Parity.none self.ComLock = threading.Lock() self.delay = 0.0 # def res_open(self): # self._visa_resource = resource_manager.open_resource(InstrumentAddress) # # self._visa_resource.query_delay = 0. # self._visa_resource.timeout = 500 # self._visa_resource.read_termination = '\r' # self._visa_resource.write_termination = '\r' def res_close(self): self._visa_resource.close() def write(self, command): """ low-level communication wrapper for visa.write with Communication Lock, to prevent multiple writes to serial adapter """ with self.ComLock: self._visa_resource.write(command) time.sleep(self.delay) # @do_check def query(self, command): """ low-level communication wrapper for visa.query with Communication Lock, to prevent multiple writes to serial adapter """ with self.ComLock: answer = self._visa_resource.query(command) time.sleep(self.delay) return answer # def query(self, command): # answer = self.query_wrap(command) # # error handling for itc503 # if answer[0] == 'T': # self.read() # answer = self.query(command) # return answer def read(self): with self.ComLock: answer = self._visa_resource.read() # time.sleep(self.delay) return answer def clear_buffers(self): self._visa_resource.timeout = 5 try: self.read() except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: pass else: raise e_visa self._visa_resource.timeout = 500
class ITC_Updater(AbstractLoopThread): """This is the worker thread, which updates all instrument data of the self.ITC 503. For each self.ITC503 function (except collecting data), there is a wrapping method, which we can call by a signal, from the main thread. This wrapper sends the corresponding value to the device. There is a second method for all wrappers, which accepts the corresponding value, and stores it, so it can be sent upon acknowledgment The information from the device is collected in regular intervals (method "running"), and subsequently sent to the main thread. It is packed in a dict, the keys of which are displayed in the "sensors" dict in this class. """ sig_Infodata = pyqtSignal(dict) # sig_assertion = pyqtSignal(str) sig_visaerror = pyqtSignal(str) sig_visatimeout = pyqtSignal() timeouterror = VisaIOError(-1073807339) sensors = dict( set_temperature = 0, Sensor_1_K = 1, Sensor_2_K = 2, Sensor_3_K = 3, temperature_error = 4, heater_output_as_percent = 5, heater_output_as_voltage = 6, gas_flow_output = 7, proportional_band = 8, integral_action_time = 9, derivative_action_time = 10) def __init__(self, InstrumentAddress='', **kwargs): super().__init__(**kwargs) # here the class instance of the ITC should be handed self.ITC = itc503(InstrumentAddress=InstrumentAddress) self.control_state = 3 self.set_temperature = 0 self.set_prop = 0 self.set_integral = 0 self.set_derivative = 0 self.set_sensor = 1 self.set_heater_output = 0 self.set_gas_output = 0 self.set_auto_manual = 0 self.sweep_parameters = None self.setControl() self.interval = 0.05 # self.__isRunning = True # @control_checks def running(self): """Try to extract all current data from the ITC, and emit signal, sending the data self.delay2 should be at at least 0.4 to ensure relatively error-free communication with ITC over serial RS-232 connection. (this worked on Benjamin's PC, to be checked with any other PC, so errors which come back are "caught", or communication is set up in a way no errors occur) """ data = dict() # get key-value pairs of the sensors dict, # so I can then transmit one single dict for key in self.sensors.keys(): try: value = self.ITC.getValue(self.sensors[key]) data[key] = value except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) data[key] = None except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() self.read_buffer() data[key] = None else: self.sig_visaerror.emit(e_visa.args[0]) self.sig_Infodata.emit(deepcopy(data)) # def control_checks(func): # @functools.wraps(func) # def wrapper_control_checks(*args, **kwargs): # pass def read_buffer(self): try: return self.ITC.read() except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: pass @pyqtSlot(int) def set_delay_sending(self, delay): self.ITC.set_delay_measuring(delay) @pyqtSlot() def setNeedle(self): """class method to be called to set Needle this is necessary, so it can be invoked by a signal self.gasoutput between 0 and 100 % """ value = self.set_GasOutput try: if 0 <= value <= 100: self.ITC.setGasOutput(value) else: raise AssertionError('ITC_control: setNeedle: Gas output setting must be between 0 and 100%!') except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setControl(self): """class method to be called to set Control this is to be invoked by a signal """ try: self.ITC.setControl(self.control_state) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setTemperature(self): """class method to be called to set Temperature this is to be invoked by a signal """ try: self.ITC.setTemperature(self.set_temperature) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setProportional(self): """class method to be called to set Proportional this is to be invoked by a signal prop: Proportional band, in steps of 0.0001K. """ try: self.ITC.setProportional(self.set_prop) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setIntegral(self): """class method to be called to set Integral this is to be invoked by a signal integral: Integral action time, in steps of 0.1 minute. Ranges from 0 to 140 minutes. """ try: self.ITC.setIntegral(self.set_integral) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setDerivative(self): """class method to be called to set Derivative this is to be invoked by a signal derivative: Derivative action time. Ranges from 0 to 273 minutes. """ try: self.ITC.setDerivative(self.set_derivative) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setHeaterSensor(self, value): """class method to be called to set HeaterSensor this is to be invoked by a signal sensor: Should be 1, 2, or 3, corresponding to the heater on the front panel. """ self.set_sensor = value try: self.ITC.setHeaterSensor(self.set_sensor) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setHeaterOutput(self): """class method to be called to set HeaterOutput this is to be invoked by a signal heater_output: Sets the percent of the maximum heater output in units of 0.1%. Min: 0. Max: 999. """ try: self.ITC.setHeaterOutput(self.set_heater_output) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setGasOutput(self): """class method to be called to set GasOutput this is to be invoked by a signal gas_output: Sets the percent of the maximum gas output in units of 1%. Min: 0. Max: 99. """ try: self.ITC.setGasOutput(self.set_gas_output) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setAutoControl(self, value): """class method to be called to set AutoControl this is to be invoked by a signal Value:Status map 0: heater manual, gas manual 1: heater auto , gas manual 2: heater manual, gas auto 3: heater auto , gas auto """ self.set_auto_manual = value try: self.ITC.setAutoControl(self.set_auto_manual) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setSweeps(self): """class method to be called to set Sweeps this is to be invoked by a signal """ try: self.ITC.setSweeps(self.sweep_parameters) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot(int) def gettoset_Control(self, value): """class method to receive and store the value to set the Control status later on, when the command to enforce the value is sent """ self.control_state = value @pyqtSlot(float) def gettoset_Temperature(self, value): """class method to receive and store the value to set the temperature later on, when the command to enforce the value is sent """ self.set_temperature = value @pyqtSlot() def gettoset_Proportional(self, value): """class method to receive and store the value to set the proportional (PID) later on, when the command to enforce the value is sent """ self.set_prop = value @pyqtSlot() def gettoset_Integral(self, value): """class method to receive and store the value to set the integral (PID) later on, when the command to enforce the value is sent """ self.set_integral = value @pyqtSlot() def gettoset_Derivative(self, value): """class method to receive and store the value to set the derivative (PID) later on, when the command to enforce the value is sent """ self.set_derivative = value @pyqtSlot() def gettoset_HeaterOutput(self, value): """class method to receive and store the value to set the heater_output later on, when the command to enforce the value is sent """ self.set_heater_output = value @pyqtSlot() def gettoset_GasOutput(self, value): """class method to receive and store the value to set the gas_output later on, when the command to enforce the value is sent """ self.set_gas_output = value @pyqtSlot() def gettoset_Sweeps(self, value): """class method to receive and store the value to for the sweep_parameters to set them later on, when the command to enforce the value is sent """ self.sweep_parameters = value
class LakeShore350_Updater(AbstractLoopThread): """This is the worker thread, which updates all instrument data of the self.ITC 503. For each self.ITC503 function (except collecting data), there is a wrapping method, which we can call by a signal, from the main thread. This wrapper sends the corresponding value to the device. There is a second method for all wrappers, which accepts the corresponding value, and stores it, so it can be sent upon acknowledgment The information from the device is collected in regular intervals (method "running"), and subsequently sent to the main thread. It is packed in a dict, the keys of which are displayed in the "sensors" dict in this class. """ sig_Infodata = pyqtSignal(dict) # sig_assertion = pyqtSignal(str) sig_visaerror = pyqtSignal(str) sig_visatimeout = pyqtSignal() timeouterror = VisaIOError(-1073807339) sensors = dict(Heater_Output_percentage=None, Heater_Output_mW=None, Temp_K=None, Ramp_Rate_Status=None, Ramp_Rate=None, Input_Sensor=None, Sensor_1_K=None, Sensor_2_K=None, Sensor_3_K=None, Sensor_4_K=None, Loop_P_Param=None, Loop_I_Param=None, Loop_D_Param=None, Heater_Range=None, Sensor_1_Ohm=None, Sensor_2_Ohm=None, Sensor_3_Ohm=None, Sensor_4_Ohm=None, OutputMode=None) def __init__(self, InstrumentAddress='', **kwargs): super().__init__(**kwargs) # here the class instance of the LakeShore should be handed try: self.LakeShore350 = LakeShore350( InstrumentAddress=InstrumentAddress) except VisaIOError as e: self.sig_assertion.emit('running in control: {}'.format(e)) return # need to quit the THREAD!! self.Temp_K_value = 3 # self.Heater_mW_value = 0 self.Ramp_Rate_value = 0 self.Input_value = 1 self.Upper_Bound_value = 300 """proper P, I, D values needed """ # self.ZoneP_value # self.ZoneI_value # self.ZoneD_value self.Mout_value = 50 self.Zone_Range_value = 2 self.Zone_Rate_value = 1 """sets Heater power to 994,05 mW """ self.configHeater() self.configTempLimit() self.initiating_PID() # self.setControlLoopZone() # self.startHeater() # self.delay1 = 1 # self.delay = 0.0 self.interval = 0 # self.setControl() # self.__isRunning = True def initiating_PID(self): temp_list0 = self.LakeShore350.ControlLoopPIDValuesQuery(1) self.LoopP_value = temp_list0[0] self.LoopI_value = temp_list0[1] self.LoopD_value = temp_list0[2] # @control_checks def running(self): """Try to extract all current data from the ITC, and emit signal, sending the data self.delay2 should be at at least 0.4 to ensure relatively error-free communication with ITC over serial RS-232 connection. (this worked on Benjamin's PC, to be checked with any other PC, so errors which come back are "caught", or communication is set up in a way no errors occur) """ try: self.sensors[ 'Heater_Output_percentage'] = self.LakeShore350.HeaterOutputQuery( 1) self.sensors['Heater_Output_mW'] = ( self.sensors['Heater_Output_percentage'] / 100) * 994.5 self.sensors['Temp_K'] = self.LakeShore350.ControlSetpointQuery(1) self.sensors[ 'Ramp_Rate_Status'] = self.LakeShore350.ControlSetpointRampParameterQuery( 1)[0] self.sensors[ 'Ramp_Rate'] = self.LakeShore350.ControlSetpointRampParameterQuery( 1)[1] self.sensors['Input_Sensor'] = self.LakeShore350.OutputModeQuery( 1)[1] temp_list = self.LakeShore350.KelvinReadingQuery(0) self.sensors['Sensor_1_K'] = temp_list[0] self.sensors['Sensor_2_K'] = temp_list[1] self.sensors['Sensor_3_K'] = temp_list[2] self.sensors['Sensor_4_K'] = temp_list[3] temp_list2 = self.LakeShore350.ControlLoopPIDValuesQuery(1) self.sensors['Loop_P_Param'] = temp_list2[0] self.sensors['Loop_I_Param'] = temp_list2[1] self.sensors['Loop_D_Param'] = temp_list2[2] self.sensors['Heater_Range'] = self.LakeShore350.HeaterRangeQuery( 1)[0] temp_list3 = self.LakeShore350.SensorUnitsInputReadingQuery(0) self.sensors['Sensor_1_Ohm'] = temp_list3[0] self.sensors['Sensor_2_Ohm'] = temp_list3[1] self.sensors['Sensor_3_Ohm'] = temp_list3[2] self.sensors['Sensor_4_Ohm'] = temp_list3[3] self.sensors['OutputMode'] = self.LakeShore350.OutputModeQuery( 1)[1] self.sig_Infodata.emit(deepcopy(self.sensors)) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) # def control_checks(func): # @functools.wraps(func) # def wrapper_control_checks(*args, **kwargs): # pass def configSensor(self): """configures sensor inputs to Cerox """ for i in ['A', 'B', 'C', 'D']: self.LakeShore350.InputTypeParameterCommand(i, 3, 1, 0, 1, 1, 0) def configHeater(self): """configures heater output HeaterSetupCommand(1,2,0,0.141,2) sets Output 1, Heater_Resistance to 50 Ohm, enables Custom Maximum Heater Output Current of 0.141 and configures the heater output displays to show in power. """ self.LakeShore350.HeaterSetupCommand(1, 2, 0, 0.141, 2) def configTempLimit(self): """sets temperature limit """ for i in ['A', 'B', 'C', 'D']: self.LakeShore350.TemperatureLimitCommand(i, 400.) @pyqtSlot() def setTemp_K(self): """takes value Temp_K and uses it on function ControlSetpointCommand to set desired temperature. """ try: self.LakeShore350.ControlSetpointCommand(1, self.Temp_K_value) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) # @pyqtSlot() # def setHeater_mW(self): # try: # self.LakeShore350.HeaterSetupCommand # except AssertionError as e_ass: # self.sig_assertion.emit(e_ass.args[0]) # except VisaIOError as e_visa: # if type(e_visa) is type(self.timeouterror) and e_visa.args == self.timeouterror.args: # self.sig_visatimeout.emit() # else: # self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setRamp_Rate_K(self): try: self.LakeShore350.ControlSetpointRampParameterCommand( 1, 1, self.Ramp_Rate_value) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setInput(self, Input_value): """(1,1,value,1) configure Output 1 for Closed Loop PID, using Input "value" and set powerup enable to On. """ try: self.LakeShore350.OutputModeCommand(1, 1, self.Input_value, 1) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setLoopP_Param(self): try: self.LakeShore350.ControlLoopPIDValuesCommand( 1, self.LoopP_value, self.sensors['Loop_I_Param'], self.sensors['Loop_D_Param']) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setLoopI_Param(self): try: self.LakeShore350.ControlLoopPIDValuesCommand( 1, self.sensors['Loop_P_Param'], self.LoopI_value, self.sensors['Loop_D_Param']) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setLoopD_Param(self): try: self.LakeShore350.ControlLoopPIDValuesCommand( 1, self.sensors['Loop_P_Param'], self.sensors['Loop_I_Param'], self.LoopD_value) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def startHeater(self): """start up Heater with Output 1 for Closed Loop PID, using Input "value" and set powerup enable to On. """ try: self.LakeShore.OutputModeCommand(1, 1, self.sensor_values[5], 1) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setHeater_Range(self): """set Heater Range for Output 1 """ try: self.LakeShore350.HeaterRangeCommand(1, self.Heater_Range_value) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setControlLoopZone(self): try: self.LakeShore350.ControlLoopZoneTableParameterCommand( 1, 1, self.Upper_Bound_value, self.ZoneP_value, self.ZoneI_value, self.ZoneD_value, self.Mout_value, self.Zone_Range_value, 1, self.Zone_Rate_value) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def gettoset_Temp_K(self, value): """class method to receive and store the value to set the temperature later on, when the command to enforce the value is sent """ self.Temp_K_value = value # @pyqtSlot() # def gettoset_Heater_mW(self,value): # """class method to receive and store the value to set the temperature # later on, when the command to enforce the value is sent # """ # self.Heater_mW_value = value @pyqtSlot() def gettoset_LoopP_Param(self, value): self.LoopP_value = value @pyqtSlot() def gettoset_LoopI_Param(self, value): self.LoopI_value = value @pyqtSlot() def gettoset_LoopD_Param(self, value): self.LoopD_value = value @pyqtSlot() def gettoset_Ramp_Rate_K(self, value): self.Ramp_Rate_value = value @pyqtSlot() def gettoset_Upper_Bound(self, value): self.Upper_Bound_value = value @pyqtSlot() def gettoset_ZoneP_Param(self, value): self.ZoneP_value = value @pyqtSlot() def gettoset_ZoneI_Param(self, value): self.ZoneI_value = value @pyqtSlot() def gettoset_ZoneD_Param(self, value): self.ZoneD_value = value @pyqtSlot() def gettoset_ZoneMout(self, value): self.Mout_value = value @pyqtSlot() def gettoset_Zone_Range(self, value): self.Zone_Range_value = value @pyqtSlot() def gettoset_Zone_Rate(self, value): self.Zone_Rate_value = value
class ILM_Updater(AbstractLoopThread): """This is the worker thread, which updates all instrument data of the ILM 211. For each ILM211 function (except collecting data), there is a wrapping method, which we can call by a signal, from the main thread. This wrapper sends the corresponding value to the device. There is a second method for all wrappers, which accepts the corresponding value, and stores it, so it can be sent upon acknowledgment The information from the device is collected in regular intervals (method "running"), and subsequently sent to the main thread. It is packed in a dict, the keys of which are displayed in the "sensors" dict in this class. """ sig_Infodata = pyqtSignal(dict) # sig_assertion = pyqtSignal(str) sig_visaerror = pyqtSignal(str) sig_visatimeout = pyqtSignal() timeouterror = VisaIOError(-1073807339) sensors = dict(channel_1_level=1, channel_2_level=2) # channel_3_level=, # channel_1_wire_current=6, # channel_2_wire_current=7, # needle_valve_position=10) def __init__(self, InstrumentAddress=''): super().__init__() # here the class instance of the ITC should be handed self.ILM = ilm211(InstrumentAddress=InstrumentAddress) self.control_state = 3 # self.interval = 60*30# every half hour one measurement lHe is not measured more often by the device anyways self.interval = 3 self.setControl() def running(self): """Try to extract all current data from the ILM, and emit signal, sending the data self.delay2 should be at at least 0.4 to ensure relatively error-free communication with ITC over serial RS-232 connection. (this worked on Benjamin's PC, to be checked with any other PC, so errors which come back are "caught", or communication is set up in a way no errors occur) """ data = dict() for key in self.sensors: try: # get key-value pairs of the sensors dict, # so I can then transmit one single dict # for key, idx_sensor in self.sensors.items(): data[key] = self.ILM.getValue(self.sensors[key]) * 0.1 # data['channel_2_level'] = self.ILM.getValue(2)*0.1 # if data[key] > 100: # data[key] = 100 # if data['channel_1_level'] > 100 # data['channel_1_level'] = 100 # status = self.ILM.getStatus() # data.update(dict( cryogen_channel_1=status[0], # cryogen_channel_2=status[1], # status_channel_1=status[2], # status_channel_2=status[3], # status_channel_3=status[4])) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() self.read_buffer() else: self.sig_visaerror.emit(e_visa.args[0]) self.sig_Infodata.emit(deepcopy(data)) def read_buffer(self): try: return self.ILM.read() except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: pass # @pyqtSlot(int) # def set_delay_sending(self, delay): # self.delay1 = delay @pyqtSlot(int) def set_delay_measuring(self, delay): self.delay2 = delay @pyqtSlot() def setControl(self): """class method to be called to set Control this is to be invoked by a signal """ try: self.ILM.setControl(self.control_state) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot(int) def setProbingSpeed(self, speed, channel=1): """ set probing speed for a specific channel for fast probing, speed = 1 for slow probing, speed = 0 this comes from the order in the comboBox in the GUI """ try: if speed == 1: self.ILM.setFast(channel) elif speed == 0: self.ILM.setSlow(channel) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot(int) def gettoset_Control(self, value): """class method to receive and store the value to set the Control status later on, when the command to enforce the value is sent """ self.control_state = value
class IPS_Updater(AbstractLoopThread): """docstring for PS_Updater""" sig_Infodata = pyqtSignal(dict) # sig_assertion = pyqtSignal(str) sig_visaerror = pyqtSignal(str) sig_visatimeout = pyqtSignal() timeouterror = VisaIOError(-1073807339) sensors = dict( # demand_current_to_psu_= 0,# output_current measured_power_supply_voltage=1, measured_magnet_current=2, # unused = 3, CURRENT_output= 4, # CURRENT output current (duplicate of R0) CURRENT_set_point=5, # CURRENT Target [A] CURRENT_sweep_rate=6, # CURRENT [A/min] FIELD_output=7, # FIELD Output_Field FIELD_set_point=8, # FIELD Target [T] FIELD_sweep_rate=9, # FIELD [T/min] lead_resistance=10, # RESISTANCE [milli_Ohm] # channel_1_Freq4 = 11, # channel_2_Freq4 = 12, # channel_3_Freq4 = 13, # DACZ = 14,# PSU_zero_correction_as_a_hexadecimal_number software_voltage_limit=15, persistent_magnet_current=16, trip_current=17, persistent_magnet_field=18, trip_field=19, # IDAC = 20,# demand_current_as_a_hexadecimal_number safe_current_limit_most_negative=21, safe_current_limit_most_positive=22) statusdict = dict( magnetstatus={ '0': 'normal', '1': 'quenched', '2': 'over heated', '4': 'warming up' }, currentstatus={ '0': 'normal', '1': 'on positive voltage limit', '2': 'on negative voltage limit', '4': 'outside negative current limit', '8': 'outside positive current limit' }, activitystatus={ '0': 'Hold', '1': 'To set point', '2': 'To zero', '4': 'Clamped' }, loc_remstatus={ '0': 'local & locked', '1': 'remote & locked', '2': 'local & unlocked', '3': 'remote & unlocked', '4': 'AUTO RUN DOWN', '5': 'AUTO RUN DOWN', '6': 'AUTO RUN DOWN', '7': 'AUTO RUN DOWN' }, switchHeaterstat={ '0': 'Off (closed) magnet at zero', '1': 'On (open)', '2': 'Off (closed) magnet at field', '8': 'no switch fitted' }, modestatus1={ '0': 'display: Amps, mode: immediate, sweepmode: Fast', '1': 'display: Tesla, mode: immediate, sweepmode: Fast', '2': 'display: Amps, mode: sweep, sweepmode: Fast', '3': 'display: Tesla, mode: sweep, sweepmode: Fast', '4': 'display: Amps, mode: immediate, sweepmode: Train', '5': 'display: Tesla, mode: immediate, sweepmode: Train', '6': 'display: Amps, mode: sweep, sweepmode: Train', '7': 'display: Tesla, mode: sweep, sweepmode: Train' }, modestatus2={ '0': 'at rest (output constant)', '1': 'sweeping (output changing)', '2': 'rate limiting (output changing)', '3': 'sweeping & rate limiting (output changing)' }, polarity1={ '0': 'desired: Forward, magnet: Forward, commanded: Forward', '1': 'desired: Forward, magnet: Forward, commanded: Reverse', '2': 'desired: Forward, magnet: Reverse, commanded: Forward', '3': 'desired: Forward, magnet: Reverse, commanded: Reverse', '4': 'desired: Reverse, magnet: Forward, commanded: Forward', '5': 'desired: Reverse, magnet: Forward, commanded: Reverse', '6': 'desired: Reverse, magnet: Reverse, commanded: Forward', '7': 'desired: Reverse, magnet: Reverse, commanded: Reverse' }, polarity2={ '0': 'output clamped (transition)', '1': 'forward (verification)', '2': 'reverse (verification)', '4': 'output clamped (requested)' }) def __init__(self, InstrumentAddress): super(IPS_Updater, self).__init__() # QThread.__init__(self) self.PS = ips120(InstrumentAddress=InstrumentAddress) self.field_setpoint = 0 self.first = True @pyqtSlot() def running(self): """worker method of the power supply controlling thread""" if self.first: time.sleep(1) self.first = False try: data = dict() # get key-value pairs of the sensors dict, # so I can then transmit one single dict for key, idx_sensor in self.sensors.items(): # key_f_timeout = key data[key] = self.PS.getValue(idx_sensor) data.update(self.getStatus()) self.sig_Infodata.emit(deepcopy(data)) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() # self.readField(nosend=True) self.read_buffer() # data[key_f_timeout] = self.read_buffer() else: self.sig_visaerror.emit(e_visa.args[0]) def read_buffer(self): try: return self.PS.read_buffer() except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: pass @pyqtSlot(int) def set_delay_sending(self, delay): self.PS.set_delay_measuring(delay) def getStatus(self): status = self.PS.getStatus() return dict( status_magnet=self.statusdict['magnetstatus'][status[1]], status_current=self.statusdict['currentstatus'][status[2]], status_activity=self.statusdict['activitystatus'][status[4]], status_locrem=self.statusdict['loc_remstatus'][status[6]], status_switchheater=self.statusdict['switchHeaterstat'][status[8]], status_mode1=self.statusdict['modestatus1'][status[10]], status_mode2=self.statusdict['modestatus2'][status[11]], status_polarity1=self.statusdict['polarity1'][status[13]], status_polarity3=self.statusdict['polarity2'][status[14]]) @pyqtSlot(int) def setControl(self, control_state=3): """method to set the control for local/remote""" try: self.PS.setControl(control_state) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def readField(self, nosend=False): '''method to readField - this can be invoked by a signal''' try: return self.PS.readField() except AssertionError as e_ass: if not nosend: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: if not nosend: self.sig_visatimeout.emit() else: if not nosend: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def readFieldSetpoint(self): '''method to readFieldSetpoint - this can be invoked by a signal''' try: return self.PS.readFieldSetpoint() except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def readFieldSweepRate(self): '''method to readFieldSweepRate - this can be invoked by a signal''' try: return self.PS.readFieldSweepRate() except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setActivity(self, state): '''method to setActivity - this can be invoked by a signal''' try: self.PS.setActivity(state) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setSwitchHeater(self, state): '''method to setHeater - this can be invoked by a signal''' try: self.PS.setSwitchHeater(state) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def setFieldSetpoint(self): '''method to setFieldSetpoint - this can be invoked by a signal''' try: self.PS.setFieldSetpoint(self.field_setpoint) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot(float) def gettoset_FieldSetpoint(self, value): """class method to receive and store the value, to set the Field Setpoint later on, when the command to enforce the value is sent TODO: adjust for units! """ self.field_setpoint = value @pyqtSlot() def setFieldSweepRate(self): '''method to setFieldSweepRate - this can be invoked by a signal''' try: self.PS.setFieldSweepRate(self.field_rate) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot(int) def gettoset_FieldSweepRate(self, value): """class method to receive and store the value to set the Field sweep rate later on, when the command to enforce the value is sent """ self.field_setpoint = value @pyqtSlot() def setDisplay(self, display): '''method to setDisplay - this can be invoked by a signal''' try: self.PS.setDisplay(display) except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0]) @pyqtSlot() def waitForField(self, timeout, error_margin): '''method to waitForField - this can be invoked by a signal''' try: return self.PS.waitForField() except AssertionError as e_ass: self.sig_assertion.emit(e_ass.args[0]) except VisaIOError as e_visa: if type(e_visa) is type( self.timeouterror ) and e_visa.args == self.timeouterror.args: self.sig_visatimeout.emit() else: self.sig_visaerror.emit(e_visa.args[0])
class AbstractVISADriver: """Abstract VISA Device Driver visalib: 'ni' or 'ks' (national instruments/keysight) """ connError = VisaIOError(-1073807194) timeouterror = VisaIOError(-1073807339) visaIOError = VisaIOError(-1073807298) visaNotFoundError = VisaIOError(-1073807343) @HandleVisaException def __init__(self, InstrumentAddress, visalib="ni", **kwargs): super(AbstractVISADriver, self).__init__(**kwargs) self._logger = logging.getLogger( "CryoGUI." + __name__ + "." + self.__class__.__name__ ) self._comLock = threading.Lock() self.delay = 0 self.delay_force = 0 self._instrumentaddress = InstrumentAddress self.visalib_kw = visalib # if visalib.strip() == 'ni' and not ni: # raise NameError('The VISA library was not found!') # if visalib.strip() == 'ks' and not keysight: # raise NameError('The Keysight VISA library was not found!') # self._resource_manager = KEYSIGHT_RESOURCE_MANAGER if visalib.strip( # ) == 'ks' else NI_RESOURCE_MANAGER # self._resource_manager = get_rm(visalib=self.visalib_kw) # resource_manager = NI_RESOURCE_MANAGER # self._visa_resource = self._resource_manager.open_resource(InstrumentAddress) self.res_open() def res_close(self): self._visa_resource.close() time.sleep(0.1) self._resource_manager.close() time.sleep(0.1) self._resource_manager.visalib._registry.clear() time.sleep(0.1) del self._resource_manager.visalib del self._resource_manager del self._visa_resource time.sleep(0.1) def res_open(self): self._resource_manager = get_rm(self.visalib_kw) try: self._visa_resource = self._resource_manager.get_instrument( self._instrumentaddress ) except VisaIOError: self._logger.error("could not open visa resource, trying again") self._visa_resource = self._resource_manager.get_instrument( self._instrumentaddress ) self.initialise_device_specifics(**self._device_specifics) # time.sleep(2) # self._visa_resource.query('*IDN?') def initialise_device_specifics(self, **kwargs): # self._visa_resource.query_delay = 0. if "timeout" in kwargs: self._visa_resource.timeout = kwargs["timeout"] if "read_termination" in kwargs: self._visa_resource.read_termination = kwargs["read_termination"] if "write_termination" in kwargs: self._visa_resource.write_termination = kwargs["write_termination"] if "baud_rate" in kwargs: self._visa_resource.baud_rate = kwargs["baud_rate"] if "data_bits" in kwargs: self._visa_resource.data_bits = kwargs["data_bits"] if "stop_bits" in kwargs: self._visa_resource.stop_bits = kwargs["stop_bits"] # vconst.StopBits.two if "parity" in kwargs: self._visa_resource.parity = kwargs["parity"] # vconst.Parity.none @HandleVisaException def write(self, command, f=False): """ low-level communication wrapper for visa.write with Communication Lock, to prevent multiple writes to serial adapter """ if not f: with self._comLock: self._visa_resource.write(command) time.sleep(self.delay) else: self._visa_resource.write(command) time.sleep(self.delay_force) @HandleVisaException def query(self, command): """Sends commands as strings to the device and receives strings from the device low-level communication wrapper for visa.query with Communication Lock, to prevent multiple writes to serial adapter """ with self._comLock: answer = self._visa_resource.query(command) time.sleep(self.delay) return answer @HandleVisaException def read(self): with self._comLock: answer = self._visa_resource.read() # time.sleep(self.delay) return answer def __del__(self): self.res_close()
Author(s): bklebel (Benjamin Klebel) """ # import sys import threading import logging import time import visa from pyvisa.errors import VisaIOError from visa import constants as vconst import functools from util import ApplicationExit connError = VisaIOError(-1073807194) timeouterror = VisaIOError(-1073807339) visaIOError = VisaIOError(-1073807298) visaNotFoundError = VisaIOError(-1073807343) logger = logging.getLogger("CryoGUI." + __name__) def get_rm(_unused_visalib="ni"): try: # the pyvisa manager we'll use to connect to the GPIB resources NI_RESOURCE_MANAGER = visa.ResourceManager() # 'C:\\Windows\\System32\\visa32.dll') # ni = True # print(' made resource manager') except OSError: