main ls370 module is now drivable

the value is the current channel, when the target (=channel) is changed,
the value changes to 0, until the switching has finished, including pause time
This commit is contained in:
l_samenv 2020-10-20 14:17:24 +02:00
parent 1b4865c608
commit 880327c544
2 changed files with 69 additions and 18 deletions

View File

@ -21,8 +21,9 @@
"""LakeShore Model 370 resistance channel""" """LakeShore Model 370 resistance channel"""
import time import time
import json
from secop.modules import Module, Readable, Drivable, Parameter, Override, Property, Attached from secop.modules import Readable, Drivable, Parameter, Override, Property, Attached
from secop.metaclass import Done from secop.metaclass import Done
from secop.datatypes import FloatRange, IntRange, EnumType, BoolType from secop.datatypes import FloatRange, IntRange, EnumType, BoolType
from secop.stringio import HasIodev from secop.stringio import HasIodev
@ -58,27 +59,66 @@ class StringIO(secop.stringio.StringIO):
wait_before = 0.05 wait_before = 0.05
class Main(HasIodev, Module): class Main(HasIodev, Drivable):
parameters = { parameters = {
'channel': 'value': Override('the current channel', poll=REGULAR, datatype=IntRange(0, 17)),
Parameter('the current channel', poll=REGULAR, datatype=IntRange(), readonly=False, handler=scan), 'target': Override('channel to select', datatype=IntRange(0, 17)),
'autoscan': 'autoscan':
Parameter('whether to scan automatically', datatype=BoolType(), readonly=False, handler=scan), Parameter('whether to scan automatically', datatype=BoolType(), readonly=False, default=False),
'pollinterval': Parameter('sleeptime between polls', default=5, 'pollinterval': Override('sleeptime between polls', default=1),
readonly=False,
datatype=FloatRange(0.1, 120),
),
} }
pollerClass = Poller pollerClass = Poller
iodevClass = StringIO iodevClass = StringIO
def analyze_scan(self, channel, autoscan): def earlyInit(self):
return dict(channel=channel, autoscan=autoscan) self._channel_changed = 0
self._channels = {}
def change_scan(self, change): def register_channel(self, modobj):
change.readValues() self._channels[modobj.channel] = modobj
return change.channel, change.autoscan
def startModule(self, started_callback):
started_callback()
for ch in range(1, 16):
if ch not in self._channels:
self.sendRecv('INSET %d,0,0,0,0,0;INSET?%d' % (ch, ch))
def read_value(self):
channel, auto = json.loads('[%s]' % self.sendRecv('SCAN?'))
if not self._channels[channel].enabled:
# channel was disabled recently, but still selected
nextchannel = 0
for ch, mobj in self._channels.items():
if mobj.enabled:
if ch > channel:
nextchannel = ch
break
if nextchannel == 0:
nextchannel = ch
if not nextchannel:
self.write_target(nextchannel)
return 0
now = time.time()
if channel != self.target:
print('changed' , channel, self.target)
self._channel_changed = now
self.target = channel
self.autoscan = int(auto)
if now < self._channel_changed + self._channels[channel].pause + self._channels[channel].filter:
self.status = [Status.BUSY, 'switching']
return 0
self.status = [Status.IDLE, '']
return channel
def write_target(self, channel):
self.sendRecv('SCAN %d,%d;SCAN?' % (channel, self.autoscan))
if channel != self.value:
self.value = 0
self._channel_changed = time.time()
self.status = [Status.BUSY, 'switching']
return channel
class ResChannel(HasIodev, Readable): class ResChannel(HasIodev, Readable):
@ -133,13 +173,16 @@ class ResChannel(HasIodev, Readable):
Parameter('filter time', datatype=FloatRange(1, 200), readonly=False, handler=filterhdl), Parameter('filter time', datatype=FloatRange(1, 200), readonly=False, handler=filterhdl),
} }
def initModule(self):
self._main = self.DISPATCHER.get_module(self.main)
self._main.register_channel(self)
def startModule(self, started_callback): def startModule(self, started_callback):
self._last_range_change = 0 self._last_range_change = 0
self._main = self.DISPATCHER.get_module(self.main)
super().startModule(started_callback) super().startModule(started_callback)
def read_value(self): def read_value(self):
if self.channel != self._main.channel: if self.channel != self._main.value:
return Done return Done
if not self.enabled: if not self.enabled:
self.status = [self.Status.DISABLED, 'disabled'] self.status = [self.Status.DISABLED, 'disabled']
@ -177,7 +220,7 @@ class ResChannel(HasIodev, Readable):
def read_status(self): def read_status(self):
if not self.enabled: if not self.enabled:
return [self.Status.DISABLED, 'disabled'] return [self.Status.DISABLED, 'disabled']
if self.channel != self._main.channel: if self.channel != self._main.value:
return Done return Done
result = int(self.sendRecv('RDGST?%d' % self.channel)) result = int(self.sendRecv('RDGST?%d' % self.channel))
result &= 0x37 # mask T_OVER and T_UNDER (change this when implementing temperatures instead of resistivities) result &= 0x37 # mask T_OVER and T_UNDER (change this when implementing temperatures instead of resistivities)
@ -242,3 +285,9 @@ class ResChannel(HasIodev, Readable):
if change.filter: if change.filter:
return 1, change.filter, 80 # always use 80% filter return 1, change.filter, 80 # always use 80% filter
return 0, settle, window return 0, settle, window
def write_enabled(self, value):
inset.write(self, 'enabled', value)
if value:
self._main.write_target(self.channel)
return Done

View File

@ -32,8 +32,10 @@ class Ls370Sim(Communicator):
] ]
OTHER_COMMANDS = [ OTHER_COMMANDS = [
('*IDN?', 'LSCI,MODEL370,370184,05302003'), ('*IDN?', 'LSCI,MODEL370,370184,05302003'),
('SCAN?', '3,1'), ('SCAN?', '1,1'),
] ]
channel = [None]
def earlyInit(self): def earlyInit(self):
self._data = dict(self.OTHER_COMMANDS) self._data = dict(self.OTHER_COMMANDS)
for fmt, v in self.CHANNEL_COMMANDS: for fmt, v in self.CHANNEL_COMMANDS: