Merge branch 'wip' of gitlab.psi.ch-samenv:samenv/frappy into wip
This commit is contained in:
commit
12cb0cdade
9
cfg/stick/uniax.cfg
Normal file
9
cfg/stick/uniax.cfg
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[NODE]
|
||||||
|
id = uniax stick
|
||||||
|
class = protocol.router.Router
|
||||||
|
description = router forwarding to linse-uniax apu
|
||||||
|
node = linse-uniax:5000
|
||||||
|
|
||||||
|
#[INTERFACE]
|
||||||
|
#uri=tcp://5002
|
||||||
|
|
@ -18,7 +18,7 @@ io = drv_io
|
|||||||
standby_current=0.1
|
standby_current=0.1
|
||||||
maxcurrent=1.4
|
maxcurrent=1.4
|
||||||
acceleration=150.
|
acceleration=150.
|
||||||
movelimit=360
|
move_limit=360
|
||||||
speed=40
|
speed=40
|
||||||
encoder_tolerance=3.6
|
encoder_tolerance=3.6
|
||||||
free_wheeling=0.1
|
free_wheeling=0.1
|
||||||
|
@ -10,6 +10,7 @@ description = force control
|
|||||||
class = secop_psi.uniax.Uniax
|
class = secop_psi.uniax.Uniax
|
||||||
motor = drv
|
motor = drv
|
||||||
transducer = transducer
|
transducer = transducer
|
||||||
|
force_offset = 15
|
||||||
|
|
||||||
#[drv_io]
|
#[drv_io]
|
||||||
#description =
|
#description =
|
||||||
@ -23,10 +24,10 @@ class = secop_psi.trinamic.Motor
|
|||||||
# io = drv_io
|
# io = drv_io
|
||||||
uri = tcp://192.168.127.254:3002
|
uri = tcp://192.168.127.254:3002
|
||||||
standby_current=0.1
|
standby_current=0.1
|
||||||
maxcurrent=0.2
|
maxcurrent=0.3
|
||||||
acceleration=150.
|
acceleration=150.
|
||||||
move_limit=5
|
move_limit=5
|
||||||
safe_current=0.2
|
safe_current=0.3
|
||||||
speed=40
|
speed=40
|
||||||
encoder_tolerance=3.6
|
encoder_tolerance=3.6
|
||||||
free_wheeling=0.1
|
free_wheeling=0.1
|
||||||
@ -39,6 +40,7 @@ class = secop_psi.dpm.DPM3
|
|||||||
uri = tcp://192.168.127.254:3001
|
uri = tcp://192.168.127.254:3001
|
||||||
digits = 2
|
digits = 2
|
||||||
scale_factor = 0.0156
|
scale_factor = 0.0156
|
||||||
|
offset = 15
|
||||||
|
|
||||||
[res]
|
[res]
|
||||||
description = temperature on uniax stick
|
description = temperature on uniax stick
|
||||||
|
@ -47,7 +47,7 @@ class SilentError(CommunicationFailedError):
|
|||||||
|
|
||||||
class HasIO(Module):
|
class HasIO(Module):
|
||||||
"""Mixin for modules using a communicator"""
|
"""Mixin for modules using a communicator"""
|
||||||
io = Attached()
|
io = Attached(mandatory=False)
|
||||||
uri = Property('uri for automatic creation of the attached communication module',
|
uri = Property('uri for automatic creation of the attached communication module',
|
||||||
StringType(), default='')
|
StringType(), default='')
|
||||||
|
|
||||||
|
@ -18,83 +18,86 @@
|
|||||||
# Module authors:
|
# Module authors:
|
||||||
# Daniel Margineda <daniel.margineda@psi.ch>
|
# Daniel Margineda <daniel.margineda@psi.ch>
|
||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
"""WAVE FUNCTION LECROY XX: SIGNAL GENERATOR"""
|
"""WAVE FUNCTION LECROY XX: SIGNAL GENERATOR
|
||||||
|
|
||||||
|
modifications not tested!
|
||||||
|
"""
|
||||||
|
|
||||||
from secop.core import Readable, Parameter, FloatRange, \
|
from secop.core import Readable, Parameter, FloatRange, \
|
||||||
IntRange, BoolType, EnumType, Module, Property
|
IntRange, BoolType, EnumType, Module, Property, HasIO
|
||||||
|
|
||||||
|
|
||||||
class Channel(Module):
|
class Channel(HasIO, Module):
|
||||||
channel = Property('choose channel to manipulate', IntRange(1, 2))
|
channel = Property('choose channel to manipulate', IntRange(1, 2))
|
||||||
freq = Parameter('frequency', FloatRange(1e-6, 20e6, unit='Hz'),
|
freq = Parameter('frequency', FloatRange(1e-6, 20e6, unit='Hz'),
|
||||||
poll=True, initwrite=True, default=1000)
|
initwrite=True, default=1000)
|
||||||
amp = Parameter('exc_volt_int', FloatRange(0.00, 5, unit='Vrms'),
|
amp = Parameter('exc_volt_int', FloatRange(0.00, 5, unit='Vrms'),
|
||||||
poll=True, readonly=False, initwrite=True, default=0.1)
|
readonly=False, initwrite=True, default=0.1)
|
||||||
offset = Parameter('offset_volt_int', FloatRange(0.0, 10, unit='V'),
|
offset = Parameter('offset_volt_int', FloatRange(0.0, 10, unit='V'),
|
||||||
poll=True, readonly=False, initwrite=True, default=0.0)
|
readonly=False, initwrite=True, default=0.0)
|
||||||
wave = Parameter('type of wavefunction',
|
wave = Parameter('type of wavefunction',
|
||||||
EnumType('WaveFunction', SINE=1, SQUARE=2, RAMP=3, PULSE=4, NOISE=5, ARB=6, DC=7),
|
EnumType('WaveFunction', SINE=1, SQUARE=2, RAMP=3, PULSE=4, NOISE=5, ARB=6, DC=7),
|
||||||
poll=True, readonly=False, default='SINE')
|
readonly=False, default='SINE')
|
||||||
phase = Parameter('signal phase', FloatRange(0, 360, unit='deg'),
|
phase = Parameter('signal phase', FloatRange(0, 360, unit='deg'),
|
||||||
poll=True, readonly=False, initwrite=True, default=0)
|
readonly=False, initwrite=True, default=0)
|
||||||
enabled = Parameter('enable output channel', datatype=EnumType('OnOff', OFF=0, ON=1),
|
enabled = Parameter('enable output channel', datatype=EnumType('OnOff', OFF=0, ON=1),
|
||||||
readonly=False, default='OFF')
|
readonly=False, default='OFF')
|
||||||
symm = Parameter('wavefunction symmetry', FloatRange(0, 100, unit=''),
|
symm = Parameter('wavefunction symmetry', FloatRange(0, 100, unit=''),
|
||||||
poll=True, readonly=False, default=0)
|
readonly=False, default=0)
|
||||||
|
|
||||||
def read_value(self):
|
def read_value(self):
|
||||||
return self.sendRecv('C%d:BSWV FRQ?' % self.channel)
|
return self.communicate('C%d:BSWV FRQ?' % self.channel)
|
||||||
|
|
||||||
def write_target(self, value):
|
def write_target(self, value):
|
||||||
self.sendRecv('C%d:BSWV FRQ, %gHz' % (self.channel, value))
|
self.communicate('C%d:BSWV FRQ, %gHz' % (self.channel, value))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
# signal wavefunction parameter
|
# signal wavefunction parameter
|
||||||
def read_wave(self):
|
def read_wave(self):
|
||||||
return self.sendRecv('C%d:BSWV WVTP?' % self.channel)
|
return self.communicate('C%d:BSWV WVTP?' % self.channel)
|
||||||
|
|
||||||
def write_wave(self, value): # string value
|
def write_wave(self, value): # string value
|
||||||
self.sendRecv('C%d:BSWV WVTP, %s' % (self.channel, value.name))
|
self.communicate('C%d:BSWV WVTP, %s' % (self.channel, value.name))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
# signal amplitude parameter
|
# signal amplitude parameter
|
||||||
def read_amp(self):
|
def read_amp(self):
|
||||||
return self.sendRecv('C%d:BSWV AMP?' % self.channel)
|
return self.communicate('C%d:BSWV AMP?' % self.channel)
|
||||||
|
|
||||||
def write_amp(self, value):
|
def write_amp(self, value):
|
||||||
self.sendRecv('C%d:BSWV AMP, %g' % (self.channel, value))
|
self.communicate('C%d:BSWV AMP, %g' % (self.channel, value))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
# offset value parameter
|
# offset value parameter
|
||||||
def read_offset(self):
|
def read_offset(self):
|
||||||
return self.sendRecv('C%d:BSWV OFST?' % self.channel)
|
return self.communicate('C%d:BSWV OFST?' % self.channel)
|
||||||
|
|
||||||
def write_offset(self, value):
|
def write_offset(self, value):
|
||||||
self.sendRecv('C%d:BSWV OFST %g' % (self.channel, value))
|
self.communicate('C%d:BSWV OFST %g' % (self.channel, value))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
# channel symmetry
|
# channel symmetry
|
||||||
def read_symm(self):
|
def read_symm(self):
|
||||||
return self.sendRecv('C%d:BSWV SYM?' % self.channel)
|
return self.communicate('C%d:BSWV SYM?' % self.channel)
|
||||||
|
|
||||||
def write_symm(self, value):
|
def write_symm(self, value):
|
||||||
self.sendRecv('C%d:BSWV SYM %g' % (self.channel, value))
|
self.communicate('C%d:BSWV SYM %g' % (self.channel, value))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
# wave phase parameter
|
# wave phase parameter
|
||||||
def read_phase(self):
|
def read_phase(self):
|
||||||
return self.sendRecv('C%d:BSWV PHSE?' % self.channel)
|
return self.communicate('C%d:BSWV PHSE?' % self.channel)
|
||||||
|
|
||||||
def write_phase(self, value):
|
def write_phase(self, value):
|
||||||
self.sendRecv('C%d:BSWV PHSE %g' % (self.channel, value))
|
self.communicate('C%d:BSWV PHSE %g' % (self.channel, value))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
# dis/enable output channel
|
# dis/enable output channel
|
||||||
def read_enabled(self):
|
def read_enabled(self):
|
||||||
return self.sendRecv('C%d: OUTP?' % self.channel)
|
return self.communicate('C%d: OUTP?' % self.channel)
|
||||||
|
|
||||||
def write_enabled(self, value):
|
def write_enabled(self, value):
|
||||||
self.sendRecv('C%d: OUTP %s' % (self.channel, value.name))
|
self.communicate('C%d: OUTP %s' % (self.channel, value.name))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
"""Signal Recovery SR7270: lockin amplifier for AC susceptibility"""
|
"""Signal Recovery SR7270: lockin amplifier for AC susceptibility"""
|
||||||
|
|
||||||
from secop.core import Readable, Parameter, Command, FloatRange, TupleOf, \
|
from secop.core import Readable, Parameter, Command, FloatRange, TupleOf, \
|
||||||
HasIodev, StringIO, Attached, IntRange, BoolType, EnumType
|
HasIO, StringIO, Attached, IntRange, BoolType, EnumType
|
||||||
|
|
||||||
|
|
||||||
class SR7270(StringIO):
|
class SR7270(StringIO):
|
||||||
@ -33,7 +33,7 @@ class SR7270(StringIO):
|
|||||||
return reply + ';%d;%d' % tuple(status)
|
return reply + ';%d;%d' % tuple(status)
|
||||||
|
|
||||||
|
|
||||||
class XY(HasIodev, Readable):
|
class XY(HasIO, Readable):
|
||||||
x = Attached()
|
x = Attached()
|
||||||
y = Attached()
|
y = Attached()
|
||||||
freq_arg = Attached()
|
freq_arg = Attached()
|
||||||
@ -46,29 +46,29 @@ class XY(HasIodev, Readable):
|
|||||||
value = Parameter('X, Y', datatype=TupleOf(FloatRange(unit='V'), FloatRange(unit='V')))
|
value = Parameter('X, Y', datatype=TupleOf(FloatRange(unit='V'), FloatRange(unit='V')))
|
||||||
freq = Parameter('exc_freq_int',
|
freq = Parameter('exc_freq_int',
|
||||||
FloatRange(0.001, 250e3, unit='Hz'),
|
FloatRange(0.001, 250e3, unit='Hz'),
|
||||||
poll=True, readonly=False, initwrite=True, default=1000)
|
readonly=False, initwrite=True, default=1000)
|
||||||
amp = Parameter('exc_volt_int',
|
amp = Parameter('exc_volt_int',
|
||||||
FloatRange(0.00, 5, unit='Vrms'),
|
FloatRange(0.00, 5, unit='Vrms'),
|
||||||
poll=True, readonly=False, initwrite=True, default=0.1)
|
readonly=False, initwrite=True, default=0.1)
|
||||||
range = Parameter('sensitivity value', FloatRange(0.00, 1, unit='V'), poll=True, default=1)
|
range = Parameter('sensitivity value', FloatRange(0.00, 1, unit='V'), default=1)
|
||||||
irange = Parameter('sensitivity index', IntRange(0, 27), poll=True, readonly=False, default=25)
|
irange = Parameter('sensitivity index', IntRange(0, 27), readonly=False, default=25)
|
||||||
autorange = Parameter('autorange_on', EnumType('autorange', off=0, soft=1, hard=2),
|
autorange = Parameter('autorange_on', EnumType('autorange', off=0, soft=1, hard=2),
|
||||||
readonly=False, default=0, initwrite=True)
|
readonly=False, default=0, initwrite=True)
|
||||||
tc = Parameter('time constant value', FloatRange(10e-6, 100, unit='s'), poll=True, default=0.1)
|
tc = Parameter('time constant value', FloatRange(10e-6, 100, unit='s'), default=0.1)
|
||||||
itc = Parameter('time constant index', IntRange(0, 30), poll=True, readonly=False, initwrite=True, default=14)
|
itc = Parameter('time constant index', IntRange(0, 30), readonly=False, initwrite=True, default=14)
|
||||||
nm = Parameter('noise mode', BoolType(), readonly=False, default=0)
|
nm = Parameter('noise mode', BoolType(), readonly=False, default=0)
|
||||||
phase = Parameter('Reference phase control', FloatRange(-360, 360, unit='deg'),
|
phase = Parameter('Reference phase control', FloatRange(-360, 360, unit='deg'),
|
||||||
poll=True, readonly=False, initwrite=True, default=0)
|
readonly=False, initwrite=True, default=0)
|
||||||
vmode = Parameter('Voltage input configuration', IntRange(0, 3), readonly=False, default=3),
|
vmode = Parameter('Voltage input configuration', IntRange(0, 3), readonly=False, default=3),
|
||||||
# dac = Parameter('output DAC channel value', datatype=TupleOf(IntRange(1, 4), FloatRange(0.0, 5000, unit='mV')),
|
# dac = Parameter('output DAC channel value', datatype=TupleOf(IntRange(1, 4), FloatRange(0.0, 5000, unit='mV')),
|
||||||
# poll=True, readonly=False, initwrite=True, default=(3,0))
|
# readonly=False, initwrite=True, default=(3,0))
|
||||||
dac = Parameter('output DAC channel value', FloatRange(-10000, 10000, unit='mV'),
|
dac = Parameter('output DAC channel value', FloatRange(-10000, 10000, unit='mV'),
|
||||||
poll=True, readonly=False, initwrite=True, default=0)
|
readonly=False, initwrite=True, default=0)
|
||||||
|
|
||||||
iodevClass = SR7270
|
ioClass = SR7270
|
||||||
|
|
||||||
def comm(self, command):
|
def comm(self, command):
|
||||||
reply, status, overload = self.sendRecv(command).split(';')
|
reply, status, overload = self.communicate(command).split(';')
|
||||||
if overload != '0':
|
if overload != '0':
|
||||||
self.status = self.Status.WARN, 'overload %s' % overload
|
self.status = self.Status.WARN, 'overload %s' % overload
|
||||||
else:
|
else:
|
||||||
@ -200,10 +200,10 @@ class XY(HasIodev, Readable):
|
|||||||
|
|
||||||
|
|
||||||
class Comp(Readable):
|
class Comp(Readable):
|
||||||
pollerClass = None
|
enablePoll = False
|
||||||
value = Parameter(datatype=FloatRange(unit='V'))
|
value = Parameter(datatype=FloatRange(unit='V'))
|
||||||
|
|
||||||
|
|
||||||
class arg(Readable):
|
class arg(Readable):
|
||||||
pollerClass = None
|
enablePoll = False
|
||||||
value = Parameter(datatype=FloatRange(unit=''))
|
value = Parameter(datatype=FloatRange(unit=''))
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
"""driver for cryotel stirling cryocooler"""
|
"""driver for cryotel stirling cryocooler"""
|
||||||
|
|
||||||
from secop.core import Command, EnumType, FloatRange, HasIodev, Parameter, Drivable, StringIO, StringType
|
from secop.core import Command, EnumType, FloatRange, HasIO, Parameter, Drivable, StringIO, StringType
|
||||||
from secop.errors import CommunicationFailedError, HardwareError
|
from secop.errors import CommunicationFailedError, HardwareError
|
||||||
|
|
||||||
|
|
||||||
@ -48,27 +48,27 @@ class CryotelIO(StringIO):
|
|||||||
return reply
|
return reply
|
||||||
|
|
||||||
|
|
||||||
class Cryo(HasIodev, Drivable):
|
class Cryo(HasIO, Drivable):
|
||||||
value = Parameter('current temperature', FloatRange(unit='deg'))
|
value = Parameter('current temperature', FloatRange(unit='deg'))
|
||||||
target = Parameter('target temperature', FloatRange(unit='deg'), readonly=False)
|
target = Parameter('target temperature', FloatRange(unit='deg'), readonly=False)
|
||||||
mode = Parameter('control mode', EnumType('mode', off=0, power=1, temperature=2), readonly=False, poll=True)
|
mode = Parameter('control mode', EnumType('mode', off=0, power=1, temperature=2), readonly=False)
|
||||||
power = Parameter('power', FloatRange(unit='W'), poll=True)
|
power = Parameter('power', FloatRange(unit='W'))
|
||||||
setpower = Parameter('requested power', FloatRange(unit='W'), default=0)
|
setpower = Parameter('requested power', FloatRange(unit='W'), default=0)
|
||||||
cool_power = Parameter('power for cooling', FloatRange(unit='W'), default=240, readonly=False)
|
cool_power = Parameter('power for cooling', FloatRange(unit='W'), default=240, readonly=False)
|
||||||
hold_power = Parameter('power for holding T', FloatRange(unit='W'), default=120, readonly=False)
|
hold_power = Parameter('power for holding T', FloatRange(unit='W'), default=120, readonly=False)
|
||||||
cool_threshold = Parameter('switch to cool_power once above this value', FloatRange(unit='K'), default=100, readonly=False)
|
cool_threshold = Parameter('switch to cool_power once above this value', FloatRange(unit='K'), default=100, readonly=False)
|
||||||
hold_threshold = Parameter('switch to hold_power once below this value', FloatRange(unit='K'), default=95, readonly=False)
|
hold_threshold = Parameter('switch to hold_power once below this value', FloatRange(unit='K'), default=95, readonly=False)
|
||||||
|
|
||||||
iodevClass = CryotelIO
|
ioClass = CryotelIO
|
||||||
cnt_inside = 0
|
cnt_inside = 0
|
||||||
|
|
||||||
def get(self, cmd):
|
def get(self, cmd):
|
||||||
return float(self._iodev.communicate(cmd))
|
return float(self.communicate(cmd))
|
||||||
|
|
||||||
def set(self, cmd, value, check=False):
|
def set(self, cmd, value, check=False):
|
||||||
setcmd = '%s=%.2f' % (cmd, value)
|
setcmd = '%s=%.2f' % (cmd, value)
|
||||||
self._iodev.communicate(setcmd)
|
self.communicate(setcmd)
|
||||||
reply = float(self._iodev.communicate(cmd))
|
reply = float(self.communicate(cmd))
|
||||||
if check:
|
if check:
|
||||||
if value != reply:
|
if value != reply:
|
||||||
raise HardwareError('illegal reply from %s: %g' % (cmd, reply))
|
raise HardwareError('illegal reply from %s: %g' % (cmd, reply))
|
||||||
|
@ -21,10 +21,8 @@
|
|||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
"""transducer DPM3 read out"""
|
"""transducer DPM3 read out"""
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
from secop.core import Readable, Parameter, FloatRange, StringIO,\
|
from secop.core import Readable, Parameter, FloatRange, StringIO,\
|
||||||
HasIodev, IntRange, Done
|
HasIO, IntRange, Done
|
||||||
|
|
||||||
|
|
||||||
class DPM3IO(StringIO):
|
class DPM3IO(StringIO):
|
||||||
@ -47,22 +45,22 @@ def float2hex(value, digits):
|
|||||||
return '%06X' % intvalue
|
return '%06X' % intvalue
|
||||||
|
|
||||||
|
|
||||||
class DPM3(HasIodev, Readable):
|
class DPM3(HasIO, Readable):
|
||||||
OFFSET = 0x8f
|
OFFSET = 0x8f
|
||||||
SCALE = 0x8c
|
SCALE = 0x8c
|
||||||
|
|
||||||
MAGNITUDE = {'1': 1, '2': 10, '3': 100, '4': 1e3, '5': 1e4, '6': 1e5,
|
MAGNITUDE = {'1': 1, '2': 10, '3': 100, '4': 1e3, '5': 1e4, '6': 1e5,
|
||||||
'9': -1, 'A': -10, 'B': -100, 'C': -1e3, 'D': -1e4, 'E': -1e5}
|
'9': -1, 'A': -10, 'B': -100, 'C': -1e3, 'D': -1e4, 'E': -1e5}
|
||||||
|
|
||||||
iodevClass = DPM3IO
|
ioClass = DPM3IO
|
||||||
|
|
||||||
value = Parameter(datatype=FloatRange(unit='N'))
|
value = Parameter(datatype=FloatRange(unit='N'))
|
||||||
digits = Parameter('number of digits for value', IntRange(0, 5), initwrite=True, readonly=False)
|
digits = Parameter('number of digits for value', IntRange(0, 5), initwrite=True, readonly=False)
|
||||||
# Note: we have to treat the units properly.
|
# Note: we have to treat the units properly.
|
||||||
# We got an output of 150 for 10N. The maximal force we want to deal with is 100N,
|
# We got an output of 150 for 10N. The maximal force we want to deal with is 100N,
|
||||||
# thus a maximal output of 1500. 10=150/f
|
# thus a maximal output of 1500. 10=150/f
|
||||||
offset = Parameter('', FloatRange(-1e5, 1e5), readonly=False, poll=True)
|
offset = Parameter('', FloatRange(-1e5, 1e5), readonly=False)
|
||||||
scale_factor = Parameter('', FloatRange(-1e5, 1e5, unit='input_units/N'), readonly=False, poll=True)
|
scale_factor = Parameter('', FloatRange(-1e5, 1e5, unit='input_units/N'), readonly=False)
|
||||||
|
|
||||||
def query(self, adr, value=None):
|
def query(self, adr, value=None):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
@ -87,7 +85,7 @@ class DPM3(HasIodev, Readable):
|
|||||||
else:
|
else:
|
||||||
cmd = ""
|
cmd = ""
|
||||||
cmd = cmd + '*1G3%02X' % adr
|
cmd = cmd + '*1G3%02X' % adr
|
||||||
hexvalue = self._iodev.communicate(cmd)
|
hexvalue = self.communicate(cmd)
|
||||||
if adr == self.SCALE:
|
if adr == self.SCALE:
|
||||||
mag = self.MAGNITUDE[hexvalue[0:1]]
|
mag = self.MAGNITUDE[hexvalue[0:1]]
|
||||||
value = int(hexvalue[1:], 16)
|
value = int(hexvalue[1:], 16)
|
||||||
@ -97,7 +95,7 @@ class DPM3(HasIodev, Readable):
|
|||||||
|
|
||||||
def write_digits(self, value):
|
def write_digits(self, value):
|
||||||
# value defines the number of digits
|
# value defines the number of digits
|
||||||
back_value = self._iodev.communicate('*1F135%02X\r*1G135' % (value + 1))
|
back_value = self.communicate('*1F135%02X\r*1G135' % (value + 1))
|
||||||
self.digits = int(back_value, 16) - 1
|
self.digits = int(back_value, 16) - 1
|
||||||
# recalculate proper scale and offset
|
# recalculate proper scale and offset
|
||||||
self.write_scale_factor(self.scale_factor)
|
self.write_scale_factor(self.scale_factor)
|
||||||
@ -105,11 +103,11 @@ class DPM3(HasIodev, Readable):
|
|||||||
return Done
|
return Done
|
||||||
|
|
||||||
def read_digits(self):
|
def read_digits(self):
|
||||||
back_value = self._iodev.communicate('*1G135')
|
back_value = self.communicate('*1G135')
|
||||||
return int(back_value,16) - 1
|
return int(back_value,16) - 1
|
||||||
|
|
||||||
def read_value(self):
|
def read_value(self):
|
||||||
return float(self._iodev.communicate('*1B1'))
|
return float(self.communicate('*1B1'))
|
||||||
|
|
||||||
def read_offset(self):
|
def read_offset(self):
|
||||||
reply = self.query(self.OFFSET)
|
reply = self.query(self.OFFSET)
|
||||||
|
@ -24,7 +24,7 @@ import time
|
|||||||
|
|
||||||
from secop.datatypes import StringType, FloatRange
|
from secop.datatypes import StringType, FloatRange
|
||||||
from secop.modules import Parameter, Property, Readable
|
from secop.modules import Parameter, Property, Readable
|
||||||
from secop.io import HasIodev, StringIO
|
from secop.io import HasIO, StringIO
|
||||||
|
|
||||||
|
|
||||||
class LscIO(StringIO):
|
class LscIO(StringIO):
|
||||||
@ -33,13 +33,13 @@ class LscIO(StringIO):
|
|||||||
wait_before = 0.05
|
wait_before = 0.05
|
||||||
|
|
||||||
|
|
||||||
class ResChannel(HasIodev, Readable):
|
class ResChannel(HasIO, Readable):
|
||||||
"""temperature channel on Lakeshore 340"""
|
"""temperature channel on Lakeshore 340"""
|
||||||
|
|
||||||
iodevClass = LscIO
|
ioClass = LscIO
|
||||||
|
|
||||||
value = Parameter(datatype=FloatRange(unit='Ohm'))
|
value = Parameter(datatype=FloatRange(unit='Ohm'))
|
||||||
channel = Property('the channel A,B,C or D', StringType())
|
channel = Property('the channel A,B,C or D', StringType())
|
||||||
|
|
||||||
def read_value(self):
|
def read_value(self):
|
||||||
return self._iodev.communicate('SRDG?%s' % self.channel)
|
return float(self.communicate('SRDG?%s' % self.channel))
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# *****************************************************************************
|
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of the GNU General Public License as published by the Free Software
|
|
||||||
# Foundation; either version 2 of the License, or (at your option) any later
|
|
||||||
# version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
# details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License along with
|
|
||||||
# this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
# Module authors:
|
|
||||||
# Markus Zolliker <markus.zolliker@psi.ch>
|
|
||||||
# *****************************************************************************
|
|
||||||
"""PPMS mf proxy"""
|
|
||||||
|
|
||||||
import secop_psi.ppms
|
|
||||||
from secop.core import Drivable, Enum, EnumType, FloatRange, Override, Parameter
|
|
||||||
from secop.datatypes import StatusType
|
|
||||||
from secop.proxy import proxy_class
|
|
||||||
|
|
||||||
|
|
||||||
class Field(proxy_class(secop_psi.ppms.Field)):
|
|
||||||
"""magnetic field"""
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
|
||||||
Status = Enum(Drivable.Status,
|
|
||||||
PREPARED = 150,
|
|
||||||
PREPARING = 340,
|
|
||||||
RAMPING = 370,
|
|
||||||
FINALIZING = 390,
|
|
||||||
)
|
|
||||||
# pylint: disable=invalid-name
|
|
||||||
PersistentMode = Enum('PersistentMode', persistent=0, driven=1)
|
|
||||||
ApproachMode = Enum('ApproachMode', linear=0, no_overshoot=1, oscillate=2)
|
|
||||||
|
|
||||||
remoteParameters = {
|
|
||||||
'value':
|
|
||||||
Override(datatype=FloatRange(-1, 1, unit='T'), poll=True),
|
|
||||||
'status':
|
|
||||||
Override(datatype=StatusType(Status), poll=True),
|
|
||||||
'target':
|
|
||||||
Override(datatype=FloatRange(-15, 15, unit='T'), poll=True),
|
|
||||||
'ramp':
|
|
||||||
Parameter('ramping speed', readonly=False,
|
|
||||||
datatype=FloatRange(0.064, 1.19, unit='T/min'), poll=True),
|
|
||||||
'approachmode':
|
|
||||||
Parameter('how to approach target', readonly=False,
|
|
||||||
datatype=EnumType(ApproachMode), poll=True),
|
|
||||||
'persistentmode':
|
|
||||||
Parameter('what to do after changing field', readonly=False,
|
|
||||||
datatype=EnumType(PersistentMode), poll=True),
|
|
||||||
'pollinterval':
|
|
||||||
Override(visibility=3),
|
|
||||||
}
|
|
@ -32,20 +32,20 @@ from secop.core import Attached, BoolType, FloatRange, IntRange, \
|
|||||||
|
|
||||||
|
|
||||||
class Temperature(Readable):
|
class Temperature(Readable):
|
||||||
pollerClass = None
|
enablePoll = False
|
||||||
|
|
||||||
value = Parameter(datatype=FloatRange(unit='degC'))
|
value = Parameter(datatype=FloatRange(unit='degC'))
|
||||||
|
|
||||||
|
|
||||||
class Bcomp(Readable):
|
class Bcomp(Readable):
|
||||||
pollerClass = None
|
enablePoll = False
|
||||||
|
|
||||||
value = Parameter(datatype=FloatRange(unit='T'))
|
value = Parameter(datatype=FloatRange(unit='T'))
|
||||||
range = Parameter('working range', FloatRange(unit='T'), default=0)
|
range = Parameter('working range', FloatRange(unit='T'), default=0)
|
||||||
|
|
||||||
|
|
||||||
class Raw(Readable):
|
class Raw(Readable):
|
||||||
pollerClass = None
|
enablePoll = False
|
||||||
|
|
||||||
value = Parameter(datatype=FloatRange())
|
value = Parameter(datatype=FloatRange())
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ class TeslameterBase(Readable):
|
|||||||
y = Attached()
|
y = Attached()
|
||||||
z = Attached()
|
z = Attached()
|
||||||
|
|
||||||
value = Parameter('B vector', poll=True,
|
value = Parameter('B vector',
|
||||||
datatype=TupleOf(FloatRange(unit='T'), FloatRange(unit='T'), FloatRange(unit='T')))
|
datatype=TupleOf(FloatRange(unit='T'), FloatRange(unit='T'), FloatRange(unit='T')))
|
||||||
usb = Parameter('usb device', StringType(), readonly=False)
|
usb = Parameter('usb device', StringType(), readonly=False)
|
||||||
enabled = Parameter('enable data acq', datatype=BoolType(), readonly=False, default=True)
|
enabled = Parameter('enable data acq', datatype=BoolType(), readonly=False, default=True)
|
||||||
@ -152,7 +152,7 @@ class Teslameter3MH6(TeslameterBase):
|
|||||||
|
|
||||||
range = Parameter('range or 0 for autorange', FloatRange(0, 20, unit='T'), readonly=False, default=0)
|
range = Parameter('range or 0 for autorange', FloatRange(0, 20, unit='T'), readonly=False, default=0)
|
||||||
rate = Parameter('sampling rate', datatype=FloatRange(10, 15000, unit='Hz'),
|
rate = Parameter('sampling rate', datatype=FloatRange(10, 15000, unit='Hz'),
|
||||||
readonly=False, poll=True)
|
readonly=False)
|
||||||
avtime = Parameter('data acquisition time', FloatRange(), default=0)
|
avtime = Parameter('data acquisition time', FloatRange(), default=0)
|
||||||
|
|
||||||
SAMPLING_RATES = {0xe0: 15000, 0xd0: 7500, 0xc0: 3750, 0xb0: 2000, 0xa1: 1000,
|
SAMPLING_RATES = {0xe0: 15000, 0xd0: 7500, 0xc0: 3750, 0xb0: 2000, 0xa1: 1000,
|
||||||
|
@ -22,17 +22,17 @@
|
|||||||
|
|
||||||
from secop.datatypes import FloatRange, IntRange, StringType
|
from secop.datatypes import FloatRange, IntRange, StringType
|
||||||
from secop.modules import Drivable, Parameter, Readable
|
from secop.modules import Drivable, Parameter, Readable
|
||||||
from secop.io import HasIodev
|
from secop.io import HasIO
|
||||||
|
|
||||||
Status = Drivable.Status
|
Status = Drivable.Status
|
||||||
|
|
||||||
|
|
||||||
class TempLoop(HasIodev, Drivable):
|
class TempLoop(HasIO, Drivable):
|
||||||
"""temperature channel on Lakeshore 336"""
|
"""temperature channel on Lakeshore 336"""
|
||||||
|
|
||||||
value = Parameter(datatype=FloatRange(unit='K'), default=0, poll=True)
|
value = Parameter(datatype=FloatRange(unit='K'), default=0)
|
||||||
status = Parameter(poll=False)
|
status = Parameter(poll=False)
|
||||||
target = Parameter(datatype=FloatRange(1.0, 402.0, unit='K'), default=1.3, poll=True)
|
target = Parameter(datatype=FloatRange(1.0, 402.0, unit='K'), default=1.3)
|
||||||
tolerance = Parameter('the tolerance', FloatRange(-400, 400), default=1, readonly=False)
|
tolerance = Parameter('the tolerance', FloatRange(-400, 400), default=1, readonly=False)
|
||||||
pollinterval = Parameter(visibility=3)
|
pollinterval = Parameter(visibility=3)
|
||||||
channel = Parameter('the Lakeshore channel', datatype=StringType(), export=False)
|
channel = Parameter('the Lakeshore channel', datatype=StringType(), export=False)
|
||||||
|
@ -32,7 +32,7 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
value = Parameter(unit='N')
|
value = Parameter(unit='N')
|
||||||
motor = Attached()
|
motor = Attached()
|
||||||
transducer = Attached()
|
transducer = Attached()
|
||||||
limit = Parameter('abs limit of force', FloatRange(0, 150, unit='N'), readonly=False, default=150)
|
limit = Parameter('abs limit of force', FloatRange(0, 190, unit='N'), readonly=False, default=150)
|
||||||
tolerance = Parameter('force tolerance', FloatRange(0, 10, unit='N'), readonly=False, default=0.1)
|
tolerance = Parameter('force tolerance', FloatRange(0, 10, unit='N'), readonly=False, default=0.1)
|
||||||
slope = PersistentParam('spring constant', FloatRange(unit='deg/N'), readonly=False,
|
slope = PersistentParam('spring constant', FloatRange(unit='deg/N'), readonly=False,
|
||||||
default=0.5, persistent='auto')
|
default=0.5, persistent='auto')
|
||||||
@ -41,7 +41,7 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
current_step = Parameter('', FloatRange(unit='deg'), default=0)
|
current_step = Parameter('', FloatRange(unit='deg'), default=0)
|
||||||
force_offset = PersistentParam('transducer offset', FloatRange(unit='N'), readonly=False, default=0,
|
force_offset = PersistentParam('transducer offset', FloatRange(unit='N'), readonly=False, default=0,
|
||||||
initwrite=True, persistent='auto')
|
initwrite=True, persistent='auto')
|
||||||
hysteresis = PersistentParam('force hysteresis', FloatRange(0, 150, unit='N'), readonly=False, default=5,
|
hysteresis = PersistentParam('force hysteresis', FloatRange(0, 190, unit='N'), readonly=False, default=5,
|
||||||
persistent='auto')
|
persistent='auto')
|
||||||
adjusting = Parameter('', BoolType(), readonly=False, default=False, initwrite=True)
|
adjusting = Parameter('', BoolType(), readonly=False, default=False, initwrite=True)
|
||||||
adjusting_current = PersistentParam('current when adjusting force', FloatRange(0, 2.8, unit='A'), readonly=False,
|
adjusting_current = PersistentParam('current when adjusting force', FloatRange(0, 2.8, unit='A'), readonly=False,
|
||||||
@ -71,19 +71,20 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
_find_target = 0
|
_find_target = 0
|
||||||
|
|
||||||
def earlyInit(self):
|
def earlyInit(self):
|
||||||
|
super().earlyInit()
|
||||||
self._zero_pos_tol = {}
|
self._zero_pos_tol = {}
|
||||||
self._action = self.idle
|
self._action = self.idle
|
||||||
|
|
||||||
def drive_relative(self, step, ntry=3):
|
def drive_relative(self, step, ntry=3):
|
||||||
"""drive relative, try 3 times"""
|
"""drive relative, try 3 times"""
|
||||||
mot = self._motor
|
mot = self.motor
|
||||||
mot.read_value() # make sure motor value is fresh
|
mot.read_value() # make sure motor value is fresh
|
||||||
if self.adjusting and abs(step) > self.safe_step:
|
if self.adjusting and abs(step) > self.safe_step:
|
||||||
step = math.copysign(self.safe_step, step)
|
step = math.copysign(self.safe_step, step)
|
||||||
self.current_step = step
|
self.current_step = step
|
||||||
for _ in range(ntry):
|
for _ in range(ntry):
|
||||||
try:
|
try:
|
||||||
self._mot_target = self._motor.write_target(mot.value + step)
|
self._mot_target = self.motor.write_target(mot.value + step)
|
||||||
self._cnt_wrerr = max(0, self._cnt_wrerr - 1)
|
self._cnt_wrerr = max(0, self._cnt_wrerr - 1)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -92,7 +93,7 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
if self._cnt_wrerr > 5:
|
if self._cnt_wrerr > 5:
|
||||||
raise
|
raise
|
||||||
self.log.warning('motor reset')
|
self.log.warning('motor reset')
|
||||||
self._motor.reset()
|
self.motor.reset()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def reset_filter(self, now=0.0):
|
def reset_filter(self, now=0.0):
|
||||||
@ -100,7 +101,7 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
self._filter_start = now or time.time()
|
self._filter_start = now or time.time()
|
||||||
|
|
||||||
def motor_busy(self):
|
def motor_busy(self):
|
||||||
mot = self._motor
|
mot = self.motor
|
||||||
if mot.isBusy():
|
if mot.isBusy():
|
||||||
if mot.target != self._mot_target:
|
if mot.target != self._mot_target:
|
||||||
self.action = self.idle
|
self.action = self.idle
|
||||||
@ -162,12 +163,12 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
if force * sign > self.hysteresis or force * sign > target * sign:
|
if force * sign > self.hysteresis or force * sign > target * sign:
|
||||||
if self.motor_busy():
|
if self.motor_busy():
|
||||||
self.log.info('motor stopped - substantial force detected: %g', force)
|
self.log.info('motor stopped - substantial force detected: %g', force)
|
||||||
self._motor.stop()
|
self.motor.stop()
|
||||||
elif self.init_action():
|
elif self.init_action():
|
||||||
self.next_action(self.adjust)
|
self.next_action(self.adjust)
|
||||||
return
|
return
|
||||||
if abs(force) > self.hysteresis:
|
if abs(force) > self.hysteresis:
|
||||||
self.set_zero_pos(force, self._motor.read_value())
|
self.set_zero_pos(force, self.motor.read_value())
|
||||||
self.next_action(self.adjust)
|
self.next_action(self.adjust)
|
||||||
return
|
return
|
||||||
if force * sign < -self.hysteresis:
|
if force * sign < -self.hysteresis:
|
||||||
@ -176,7 +177,7 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
return
|
return
|
||||||
if self.motor_busy():
|
if self.motor_busy():
|
||||||
if sign * self._find_target < 0: # target sign changed
|
if sign * self._find_target < 0: # target sign changed
|
||||||
self._motor.stop()
|
self.motor.stop()
|
||||||
self.next_action(self.find) # restart find
|
self.next_action(self.find) # restart find
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
@ -184,26 +185,26 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
zero_pos = self.zero_pos(target)
|
zero_pos = self.zero_pos(target)
|
||||||
side_name = 'positive' if target > 0 else 'negative'
|
side_name = 'positive' if target > 0 else 'negative'
|
||||||
if not self.init_action():
|
if not self.init_action():
|
||||||
if abs(self._motor.target - self._motor.value) > self._motor.tolerance:
|
if abs(self.motor.target - self.motor.value) > self.motor.tolerance:
|
||||||
# no success on last find try, try short and strong step
|
# no success on last find try, try short and strong step
|
||||||
self.write_adjusting(True)
|
self.write_adjusting(True)
|
||||||
self.log.info('one step to %g', self._motor.value + self.safe_step)
|
self.log.info('one step to %g', self.motor.value + self.safe_step)
|
||||||
self.drive_relative(sign * self.safe_step)
|
self.drive_relative(sign * self.safe_step)
|
||||||
return
|
return
|
||||||
if zero_pos is not None:
|
if zero_pos is not None:
|
||||||
self.status = 'BUSY', 'change to %s side' % side_name
|
self.status = 'BUSY', 'change to %s side' % side_name
|
||||||
zero_pos += sign * (self.hysteresis * self.slope - self._motor.tolerance)
|
zero_pos += sign * (self.hysteresis * self.slope - self.motor.tolerance)
|
||||||
if (self._motor.value - zero_pos) * sign < -self._motor.tolerance:
|
if (self.motor.value - zero_pos) * sign < -self.motor.tolerance:
|
||||||
self.write_adjusting(False)
|
self.write_adjusting(False)
|
||||||
self.log.info('change side to %g', zero_pos)
|
self.log.info('change side to %g', zero_pos)
|
||||||
self.drive_relative(zero_pos - self._motor.value)
|
self.drive_relative(zero_pos - self.motor.value)
|
||||||
return
|
return
|
||||||
# we are already at or beyond zero_pos
|
# we are already at or beyond zero_pos
|
||||||
self.next_action(self.adjust)
|
self.next_action(self.adjust)
|
||||||
return
|
return
|
||||||
self.write_adjusting(False)
|
self.write_adjusting(False)
|
||||||
self.status = 'BUSY', 'find %s side' % side_name
|
self.status = 'BUSY', 'find %s side' % side_name
|
||||||
self.log.info('one turn to %g', self._motor.value + sign * 360)
|
self.log.info('one turn to %g', self.motor.value + sign * 360)
|
||||||
self.drive_relative(sign * 360)
|
self.drive_relative(sign * 360)
|
||||||
|
|
||||||
def free(self, force, target):
|
def free(self, force, target):
|
||||||
@ -293,7 +294,7 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
|
|
||||||
def read_value(self):
|
def read_value(self):
|
||||||
try:
|
try:
|
||||||
force = self._transducer.read_value()
|
force = self.transducer.read_value()
|
||||||
self._cnt_rderr = max(0, self._cnt_rderr - 1)
|
self._cnt_rderr = max(0, self._cnt_rderr - 1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._cnt_rderr += 1
|
self._cnt_rderr += 1
|
||||||
@ -323,7 +324,7 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
self.log.error(self.status[1])
|
self.log.error(self.status[1])
|
||||||
return Done
|
return Done
|
||||||
if self.zero_pos(force) is None and abs(force) > self.hysteresis and self._filtered:
|
if self.zero_pos(force) is None and abs(force) > self.hysteresis and self._filtered:
|
||||||
self.set_zero_pos(force, self._motor.read_value())
|
self.set_zero_pos(force, self.motor.read_value())
|
||||||
self._action(self.value, self.target)
|
self._action(self.value, self.target)
|
||||||
return Done
|
return Done
|
||||||
|
|
||||||
@ -351,18 +352,18 @@ class Uniax(PersistentMixin, Drivable):
|
|||||||
@Command()
|
@Command()
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self._action = self.idle
|
self._action = self.idle
|
||||||
if self._motor.isBusy():
|
if self.motor.isBusy():
|
||||||
self.log.info('stop motor')
|
self.log.info('stop motor')
|
||||||
self._motor.stop()
|
self.motor.stop()
|
||||||
self.next_action(self.idle)
|
self.next_action(self.idle)
|
||||||
|
|
||||||
def write_force_offset(self, value):
|
def write_force_offset(self, value):
|
||||||
self.force_offset = value
|
self.force_offset = value
|
||||||
self._transducer.write_offset(value)
|
self.transducer.write_offset(value)
|
||||||
return Done
|
return Done
|
||||||
|
|
||||||
def write_adjusting(self, value):
|
def write_adjusting(self, value):
|
||||||
mot = self._motor
|
mot = self.motor
|
||||||
if value:
|
if value:
|
||||||
mot_current = self.adjusting_current
|
mot_current = self.adjusting_current
|
||||||
mot.write_move_limit(self.safe_step)
|
mot.write_move_limit(self.safe_step)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user