Added documentation

Change-Id: Id6e26a4c28fe080a55099cd54d0fa85c15946657
This commit is contained in:
Oksana Shliakhtun 2024-08-19 17:21:40 +02:00 committed by Markus Zolliker
parent c1403763f4
commit f0eb7d95f1
3 changed files with 84 additions and 2 deletions

View File

@ -15,7 +15,7 @@
# #
# Module authors: Oksana Shliakhtun <oksana.shliakhtun@psi.ch> # Module authors: Oksana Shliakhtun <oksana.shliakhtun@psi.ch>
# ***************************************************************************** # *****************************************************************************
"""Stanford Research Systems SIM900 Mainframe"""
import re import re
from frappy.core import StringIO, HasIO, Readable, \ from frappy.core import StringIO, HasIO, Readable, \
@ -24,6 +24,11 @@ from frappy.core import StringIO, HasIO, Readable, \
def string_to_value(value): def string_to_value(value):
"""
Converting the value to float, removing the units, converting the prefix into the number.
:param value: value
:return: float value without units
"""
value_with_unit = re.compile(r'(\d+)([pnumkMG]?)') value_with_unit = re.compile(r'(\d+)([pnumkMG]?)')
value, pfx = value_with_unit.match(value).groups() value, pfx = value_with_unit.match(value).groups()
pfx_dict = {'p': 1e-12, 'n': 1e-9, 'u': 1e-6, 'm': 1e-3, 'k': 1e3, 'M': 1e6, 'G': 1e9} pfx_dict = {'p': 1e-12, 'n': 1e-9, 'u': 1e-6, 'm': 1e-3, 'k': 1e3, 'M': 1e6, 'G': 1e9}
@ -33,6 +38,12 @@ def string_to_value(value):
def find_idx(list_of_values, target): def find_idx(list_of_values, target):
"""
Search for the nearest value and index from the given range for the given target.
:param list_of_values: range of values
:param target: target
:return: closest index and closest value
"""
target = float(target) target = float(target)
cl_idx = None cl_idx = None
cl_value = float('inf') cl_value = float('inf')
@ -49,6 +60,9 @@ def find_idx(list_of_values, target):
class BridgeIO(StringIO): class BridgeIO(StringIO):
"""_\n is placed at the beginning of each command to distinguish
the previous response with a possible asynchronous response from the actual value returned by the method. """
end_of_line = '\n' end_of_line = '\n'
identification = [('_\n*IDN?', r'Stanford_Research_Systems,.*')] identification = [('_\n*IDN?', r'Stanford_Research_Systems,.*')]
@ -57,9 +71,15 @@ class Base(HasIO):
port = Property('modules port', IntRange(0, 15)) port = Property('modules port', IntRange(0, 15))
def communicate(self, command): def communicate(self, command):
"""
Connection to the particular module x.
:param command: command
:return: return
"""
return self.io.communicate(f'_\nconn {self.port:x},"_\n"\n{command}') return self.io.communicate(f'_\nconn {self.port:x},"_\n"\n{command}')
def query(self, command): def query(self, command):
"""converting to float"""
return float(self.communicate(command)) return float(self.communicate(command))
@ -142,6 +162,7 @@ class Resistance(Base, Readable):
return self.query('rval?') return self.query('rval?')
def read_irange(self): def read_irange(self):
"""index of the resistance value according to the range"""
return self.query('rang?') return self.query('rang?')
def write_irange(self, idx): def write_irange(self, idx):
@ -151,6 +172,7 @@ class Resistance(Base, Readable):
return value return value
def read_range(self): def read_range(self):
"""value of the resistance range"""
idx = self.read_irange() idx = self.read_irange()
name = self.RES_RANGE[idx] name = self.RES_RANGE[idx]
return string_to_value(name) return string_to_value(name)
@ -161,12 +183,14 @@ class Resistance(Base, Readable):
return cl_value return cl_value
def read_output_offset(self): def read_output_offset(self):
"""Output offset, can be set by user. This is the value subtracted from the measured value"""
return self.query('rset?') return self.query('rset?')
def write_output_offset(self, output_offset): def write_output_offset(self, output_offset):
self.query(f'rset {output_offset};rset?') self.query(f'rset {output_offset};rset?')
def read_itc(self): def read_itc(self):
"""index of the temperature constant value according to the range"""
return self.query('tcon?') return self.query('tcon?')
def write_itc(self, itc): def write_itc(self, itc):
@ -192,6 +216,7 @@ class Resistance(Base, Readable):
return value return value
def read_iexct(self): def read_iexct(self):
"""index of the excitation value according to the range"""
return int(self.query('exci?')) return int(self.query('exci?'))
def write_iexct(self, iexct): def write_iexct(self, iexct):
@ -221,6 +246,10 @@ class Resistance(Base, Readable):
return string_to_value(name) return string_to_value(name)
def read_phase_hold(self): def read_phase_hold(self):
"""
Set the phase hold mode (if on - phase is assumed to be zero).
:return: 0 - off, 1 - on
"""
return int(self.communicate('phld?')) return int(self.communicate('phld?'))
def write_phase_hold(self, phase_hold): def write_phase_hold(self, phase_hold):

View File

@ -15,6 +15,8 @@
# #
# Module authors: Oksana Shliakhtun <oksana.shliakhtun@psi.ch> # Module authors: Oksana Shliakhtun <oksana.shliakhtun@psi.ch>
# ***************************************************************************** # *****************************************************************************
"""Thermo Haake Phoenix P1 Bath Circulator"""
import re import re
import time import time
from frappy.core import StringIO, HasIO, Parameter, FloatRange, BoolType, \ from frappy.core import StringIO, HasIO, Parameter, FloatRange, BoolType, \
@ -24,6 +26,11 @@ from frappy.errors import CommunicationFailedError
def convert(string): def convert(string):
"""
Converts reply to a number
:param string: reply from the command
:return: number
"""
number = re.sub(r'[^0-9.-]', '', string) number = re.sub(r'[^0-9.-]', '', string)
return float(number) return float(number)
@ -56,11 +63,21 @@ class TemperatureLoop(HasIO, HasConvergence, Drivable):
] ]
def get_values_status(self): def get_values_status(self):
"""
Supplementary command for the operating status method.
Removes the extra symbol and converts each status value into integer.
:return: array of integers
"""
reply = self.communicate('B') reply = self.communicate('B')
string = reply.rstrip('$') string = reply.rstrip('$')
return [int(val) for val in string] return [int(val) for val in string]
def read_status(self): # control_active update def read_status(self): # control_active update
"""
Operating status.
:return: statu type and message
"""
values_str = self.get_values_status() values_str = self.get_values_status()
self.read_control_active() self.read_control_active()
@ -73,6 +90,10 @@ class TemperatureLoop(HasIO, HasConvergence, Drivable):
return IDLE, '' return IDLE, ''
def read_value(self): def read_value(self):
"""
F1 - internal temperature, F2 - external temperature
:return: float temperature value
"""
if self.mode == 1: if self.mode == 1:
value = self.communicate('F1') value = self.communicate('F1')
else: else:
@ -80,6 +101,11 @@ class TemperatureLoop(HasIO, HasConvergence, Drivable):
return convert(value) return convert(value)
def write_control_active(self, value): def write_control_active(self, value):
"""
Turning on/off the heating, pump and regulation
:param value: 0 is OFF, 1 is ON
:return:
"""
if value is True: if value is True:
self.communicate('GO') # heating and pump run self.communicate('GO') # heating and pump run
self.communicate('W SR') # regulation self.communicate('W SR') # regulation
@ -100,6 +126,11 @@ class TemperatureLoop(HasIO, HasConvergence, Drivable):
return convert(string) return convert(string)
def write_target(self, target): def write_target(self, target):
"""
Selecting Celsius, setting the target
:param target: target
:return: target
"""
self.write_control_active(True) self.write_control_active(True)
self.read_status() self.read_status()
self.communicate('W TE C') self.communicate('W TE C')
@ -107,6 +138,11 @@ class TemperatureLoop(HasIO, HasConvergence, Drivable):
return target return target
def write_mode(self, mode): def write_mode(self, mode):
"""
Switching to internal or external control
:param mode: internal/external
:return: selected mode
"""
if mode == 1: if mode == 1:
self.communicate('W IN') self.communicate('W IN')
self.communicate('W EX') self.communicate('W EX')

View File

@ -16,7 +16,7 @@
# Module authors: # Module authors:
# Oksana Shliakhtun <oksana.shliakhtun@psi.ch> # Oksana Shliakhtun <oksana.shliakhtun@psi.ch>
# ***************************************************************************** # *****************************************************************************
"""Temperature Controller TC1 Quantum NorthWest"""
from frappy.core import Readable, Parameter, FloatRange, IDLE, ERROR, BoolType,\ from frappy.core import Readable, Parameter, FloatRange, IDLE, ERROR, BoolType,\
StringIO, HasIO, Property, WARN, Drivable, BUSY, StringType, Done StringIO, HasIO, Property, WARN, Drivable, BUSY, StringType, Done
@ -35,6 +35,13 @@ class SensorTC1(HasIO, Readable):
channel = Property('channel name', StringType()) channel = Property('channel name', StringType())
def set_param(self, adr, value=None): def set_param(self, adr, value=None):
"""
Set parameter.
Every command starts with "[F1", and the end of line is "]".
:param adr: second part of the command
:param value: value to set
:return: value converted to float
"""
short = adr.split()[0] short = adr.split()[0]
# try 3 times in case we got an asynchronous message # try 3 times in case we got an asynchronous message
for _ in range(3): for _ in range(3):
@ -80,6 +87,16 @@ class TemperatureLoopTC1(SensorTC1, Drivable):
return self.get_param('MT') return self.get_param('MT')
def read_status(self): def read_status(self):
"""
the device returns 4 symbols according to the current status. These symbols are:
0 or 1 - number of unreported errors
+ or - - stirrer is on/off
+ or - - temperature control is on/off
S or C - current sample holder tempeerature is stable/changing
There could be the fifth status symbol:
+ or - or W - rampping is on/off/waiting
:return: status messages
"""
status = super().read_status() status = super().read_status()
if status[0] == ERROR: if status[0] == ERROR:
return status return status