81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
![]() |
import serial
|
||
|
import serial.tools.list_ports
|
||
|
from enum import Enum
|
||
|
|
||
|
class libreCAL:
|
||
|
def __init__(self, serialnum = ''):
|
||
|
self.ser = None
|
||
|
for p in serial.tools.list_ports.comports():
|
||
|
if p.vid == 0x0483 and p.pid == 0x4122:
|
||
|
self.ser = serial.Serial(p.device, timeout = 1)
|
||
|
idn = self.SCPICommand("*IDN?").split("_")
|
||
|
if idn[0] != "LibreCAL":
|
||
|
continue
|
||
|
self.serial = idn[1]
|
||
|
if len(serialnum) > 0:
|
||
|
# serial number specified, compare
|
||
|
if self.serial != serialnum:
|
||
|
self.ser = None
|
||
|
continue
|
||
|
break
|
||
|
if self.ser == None:
|
||
|
if len(serialnum) > 0:
|
||
|
raise Exception("LibreCAL with serial number '"+serialnum+"' not detected")
|
||
|
else:
|
||
|
raise Exception("No LibreCAL device detected")
|
||
|
|
||
|
def getSerial(self) -> str:
|
||
|
return self.serial
|
||
|
|
||
|
class Standard(Enum):
|
||
|
NONE = 0,
|
||
|
OPEN = 1,
|
||
|
SHORT = 2,
|
||
|
LOAD = 3,
|
||
|
THROUGH = 4
|
||
|
|
||
|
def reset(self):
|
||
|
self.SCPICommand(":PORT 1 NONE")
|
||
|
self.SCPICommand(":PORT 2 NONE")
|
||
|
self.SCPICommand(":PORT 3 NONE")
|
||
|
self.SCPICommand(":PORT 4 NONE")
|
||
|
|
||
|
def setPort(self, s : Standard, port, port2 = -1):
|
||
|
if s == self.Standard.THROUGH and port2 == -1:
|
||
|
raise Exception("When setting a port to THROUGH, the destination port must also be specified")
|
||
|
cmd = ":PORT "+str(port)+" "+s.name
|
||
|
if s == self.Standard.THROUGH:
|
||
|
cmd += " "+str(port2)
|
||
|
if len(self.SCPICommand(cmd)) == 0:
|
||
|
return True
|
||
|
else:
|
||
|
return False
|
||
|
|
||
|
def getPort(self, port):
|
||
|
resp = self.SCPICommand(":PORT? "+str(port)).split(" ")[0]
|
||
|
try:
|
||
|
s = self.Standard[resp]
|
||
|
return s
|
||
|
except:
|
||
|
raise Exception("LibreCAL reported unknown standard '"+resp+"'")
|
||
|
|
||
|
def getTemperature(self):
|
||
|
return float(self.SCPICommand(":TEMP?"))
|
||
|
|
||
|
def isStable(self) -> bool:
|
||
|
if self.SCPICommand(":TEMP:STABLE?") == "TRUE":
|
||
|
return True
|
||
|
else:
|
||
|
return False
|
||
|
|
||
|
def getHeaterPower(self):
|
||
|
return float(self.SCPICommand(":HEAT:POW?"))
|
||
|
|
||
|
def SCPICommand(self, cmd: str) -> str:
|
||
|
self.ser.write((cmd+"\r\n").encode())
|
||
|
resp = self.ser.readline().decode("ascii")
|
||
|
if len(resp) == 0:
|
||
|
raise Exception("Timeout occurred in communication with LibreCAL")
|
||
|
if resp.strip() == "ERROR":
|
||
|
raise Exception("LibreCAL returned 'ERROR' for command '"+cmd+"'")
|
||
|
return resp.strip()
|