The thermostat is a laboratory device that is designed for temperature control applications with liquid in a bath tank. An external loop circuit can be connected to the pump connectors so that the temperature of the bath can remain constant.
As discussed previously the thermostats job is to bring both plates to a base temperature. The thermostats reports to the PC after the installation of the driver with the identifier “STMicroelectronics virtual COM port” in Device Manager and to operate the device there are a list of commands that can be send to the device using any serial connection with the device.
The IN
commands purpose is to retrieve parameters the command structure is command + TR
. The OUT
commands purpose is to set parameters (only in remote control mode) the command structure is command + space + Parameter + TR
.
In order to make the drivers for the device, the commands above are divided into smaller functions of getters and setters, with input validation, output validation and error translation implemented on the driver class level as it can been seen below so the driver can be reused in future development and automation of lab devices.
Code
import pyvisa, time, logging
class ThermostatDriver():
def __init__(self, base):
self.logger = logging.getLogger('logger')
try:
rm = pyvisa.ResourceManager()
self.ser = rm.open_resource(str(base.thermostat_port))
except Exception as e:
self.logger.critical("Failed to establish connection
to Thermostat " + str(e))
def getStatus(self):
"""current operating status"""
self.ser.write('STATUS')
time.sleep(0.2)
answer = self.ser.read_bytes(self.ser.bytes_in_buffer).decode('latin-1')
if answer == "E01":
data = ( "The device is being operated with no or too little bath
fluid or the level is below the minimum level."
"Top up the bath fluid. A hose has burst
(bath fluid level too low because it has been pumped out)."
"Replace the hose and top up the bath fluid." )
if answer == "E05":
data = ( "The cable for the working temperature
sensor has been interrupted or short-circuited." )
if answer == "E06":
data = ( "Defect of the working or excess temperature sensor."
"The working and excess temperature sensors report
a temperature difference of more than 20 K")
if answer == "E14":
data = ( "The cut-out value of the excessive temperature
protector is below the defined working temperature."
"Set the safety temperature to a higher value." )
if answer == "E33":
data = ( "The cable for the over temperature safety
sensor has been broken or short-circuited." )
if answer == "E60" or "E63" or "E70" or "E72" or "E80":
data = ( "Internal error. Contact JULABO Service Department." )
if answer == "E61":
data = ( "Connection error between Corio CD and refrigeration unit" )
if answer == "E82":
data = ( "Warning: Update error (incorrect hex file).
Contact JULABO Service Department." )
if answer == "E83":
data = ( "Warning: Excessive power consumption via USB
interface (<300 mA)." )
if answer == "E108":
data = ( "The self-locking alarm is still active. Switch off
the device at the main switch. Wait for approx.
4 seconds and then switch it on again." )
if answer == "E116":
data = ( "The cut-out value of the excessive temperature protector
is below the defined working temperature.
Set the safety temperature to a higher value" )
if answer == "E118":
data = ( "The internal AD converter is defective" )
if answer == "E431":
data = ( "Maximum compressor current exceeded" )
if answer == "E1431":
data = ( "Warning: No compressor current detected." )
if answer == "E401":
data = ( "Temperature sensor evaporator outlet defective (short circuit)." )
if answer == "E402":
data = ( "Temperature sensor evaporator outlet defective (break)." )
if answer == "E413":
data = ( "Evaporation pressure sensor defective (short circuit)." )
if answer == "E414":
data = ( "Evaporation pressure sensor defective (break)." )
if answer == "E417":
data = ( "Condensation pressure sensor
defective (short circuit)." )
if answer == "E418":
data = ( "Condensation pressure sensor defective (break)." )
if answer == "E425" or "E426" or "E427" or "E432" or "E433":
data = ( "Error in refrigeration system" )
if answer == "E1427":
data = ( "Warning: Error in refrigeration system" )
if answer == "E431":
data = ( "Maximum compressor current exceeded." )
else:
data = ( "Error Unkonwen" )
def getVersion(self):
"""device name + voltage variant + software version"""
self.ser.write('VERSION')
time.sleep(0.2)
data = ''
while not data:
data = self.ser.read_bytes(self.ser.bytes_in_buffer).decode('latin-1')
return data
def setTargetTemperature(self, value):
"""set setpoint"""
self.ser.write(('OUT_SP_00 '+ str(value)))
def getTargetTemperature(self):
"""query Setpoint"""
self.ser.write('IN_SP_00')
time.sleep(1)
data = ''
while not data:
data = self.ser.read_bytes(self.ser.bytes_in_buffer).decode('latin-1')
return data
def getTemperatureValue(self):
"""query current temperature value"""
self.ser.write('IN_PV_00')
time.sleep(0.2)
data = ''
while not data:
data = self.ser.read_bytes(self.ser.bytes_in_buffer).decode('latin-1')
data = float(str.strip(data))
return data
def getVar(self):
"""query Variable"""
self.ser.write('IN_PV_01')
data = ''
while not data:
data = self.ser.read_bytes(self.ser.bytes_in_buffer).decode('latin-1')
return data
def getSafetySensor(self):
"""query Safety sensor"""
self.ser.write('IN_PV_03')
data = ''
while not data:
data = self.ser.read_bytes(self.ser.bytes_in_buffer).decode('latin-1')
return data
def getSafetyPotentiometer(self):
"""query Safety potentiometer"""
self.ser.write('IN_PV_04')
time.sleep(0.2)
data = ''
while not data:
data = self.ser.read_bytes(self.ser.bytes_in_buffer).decode('latin-1')
return data
def getStartStop(self):
"""query Start/Stopp"""
self.ser.write('IN_MODE_05')
time.sleep(0.2)
data = ''
while not data:
data = self.ser.read_bytes(self.ser.bytes_in_buffer).decode('latin-1')
return data
def sendSetpoint(self):
"""send setpoint"""
self.ser.write('OUT_SP_01')
def startDevice(self):
self.ser.write('OUT_MODE_05 1')
time.sleep(0.2)
data = self.ser.read_bytes(self.ser.bytes_in_buffer).decode('latin-1')
def stopDevice(self):
self.ser.write('OUT_MODE_05 0')
time.sleep(0.2)
data = self.ser.read_bytes(self.ser.bytes_in_buffer).decode('latin-1')