uniax: added force control as seperate module

Change-Id: I8b14fc90f5885834e342f6bc5e5dd0ea711b27ea
This commit is contained in:
2021-10-06 13:33:34 +02:00
parent 70b9c88f82
commit 29226a1062
4 changed files with 230 additions and 61 deletions

View File

@ -21,8 +21,10 @@
# *****************************************************************************
"""transducer DPM3 read out"""
from secop.core import Drivable, Parameter, FloatRange, BoolType, StringIO,\
HasIodev, IntRange, Done, Attached, Command
import time
from secop.core import Readable, Parameter, FloatRange, StringIO,\
HasIodev, IntRange, Done
class DPM3IO(StringIO):
@ -45,30 +47,22 @@ def float2hex(value, digits):
return '%06X' % intvalue
class DPM3(HasIodev, Drivable):
class DPM3(HasIodev, Readable):
OFFSET = 0x8f
SCALE = 0x8c
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}
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}
iodevClass = DPM3IO
motor = Attached()
digits = Parameter('number of digits for value', IntRange(0, 5), initwrite=True, readonly=False)
value = Parameter(datatype=FloatRange(unit='N'))
target = Parameter(datatype=FloatRange(unit='N'))
step = Parameter('maximum motor step', FloatRange(unit='deg'), default=5, readonly=False)
digits = Parameter('number of digits for value', IntRange(0, 5), initwrite=True, readonly=False)
# 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,
# thus a maximal output of 1500. 10=150/f
offset = Parameter('', FloatRange(-1e5, 1e5), readonly=False, poll=True)
#Note: we have tro treat the units properly.
""" We got an output of 150 for 10N. The maximal force we want to deal with is 100N,
thus a maximl output of 1500. 10=150/f
"""
scale_factor = Parameter('', FloatRange(-1e5, 1e5, unit='input_units/N'), readonly=False, poll=True)
_target = None
fast_pollfactor = 0.01
scale_factor = Parameter('', FloatRange(-1e5, 1e5, unit='input_units/N'), readonly=False, poll=True)
def query(self, adr, value=None):
if value is not None:
@ -78,11 +72,11 @@ class DPM3(HasIodev, Drivable):
if 10000 <= round(value * mag, 0) <= 99999:
break
else:
# not suitable range found
# no suitable range found
if absval >= 99999.5: # overrange
raise ValueError('%s is out of range' % value)
# underrange: take lowest
nibble = '9' if value < 0 else '1'
nibble = '9' if value < 0 else '1'
mag = self.MAGNITUDE[nibble]
hex_val = nibble + '%05X' % int(round(value * mag, 0))
if hex_val[1:] == '00000':
@ -103,9 +97,9 @@ class DPM3(HasIodev, Drivable):
def write_digits(self, value):
# value defines the number of digits
back_value=self._iodev.communicate('*1F135%02X\r*1G135' % (value + 1))
self.digits = int(back_value,16) - 1
# realculate proper scale and offset
back_value = self._iodev.communicate('*1F135%02X\r*1G135' % (value + 1))
self.digits = int(back_value, 16) - 1
# recalculate proper scale and offset
self.write_scale_factor(self.scale_factor)
self.write_offset(self.offset)
return Done
@ -115,44 +109,7 @@ class DPM3(HasIodev, Drivable):
return int(back_value,16) - 1
def read_value(self):
value = float(self._iodev.communicate('*1B1'))
mot = self._motor
if self._target is None:
if mot.isBusy():
self.status = self.Status.IDLE, 'stopping'
else:
self.status = self.Status.IDLE, ''
else:
if self._direction * (self._target - value) > 0:
if self._mot_target != mot.target:
self.stop()
self.status = self.Status.IDLE, 'motor was stopped'
elif not mot.isBusy():
step = self.step * self._direction
mot_target = mot.value + step
self._mot_target = mot.write_target(mot_target)
else:
self.stop()
self.status = self.Status.IDLE, 'target reached'
return value
def write_target(self, target):
self._target = target
if target - self.value > 0:
self._direction = 1
else:
self._direction = -1
self.status = self.Status.BUSY, 'moving motor'
if self._motor.status[0] == self.Status.ERROR:
self._motor.reset()
self._mot_target = self._motor.target
return target
@Command()
def stop(self):
self._target = None
self._motor.stop()
self.status = self.Status.IDLE, 'stopped'
return float(self._iodev.communicate('*1B1'))
def read_offset(self):
reply = self.query(self.OFFSET)