diff --git a/cfg/mupd_cfg.py b/cfg/mupd_cfg.py index c2665d2e..ae96403d 100644 --- a/cfg/mupd_cfg.py +++ b/cfg/mupd_cfg.py @@ -3,13 +3,13 @@ Node('mupd.psi.ch', interface='tcp://5000', ) -usb_sample = 'serial:///dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.3.4:1.0-port0' -usb_displacement = 'serial:///dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.3.1:1.0-port0' +usb_displacement = 'serial:///dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.3.4:1.0-port0' +usb_pillars = 'serial:///dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.3.1:1.0-port0' usb_load_cell = 'serial:///dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.3.2:1.0-port0' -usb_drv = 'serial:///dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.3.3:1.0-port0?baudrate=38400' +usb_drv = 'serial:///dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.3.3:1.0-port0?baudrate=9600' -if not 'drv': +if 'drv': Mod('drv', 'frappy_psi.trinamic.Motor', 'trinamic motor test', @@ -25,39 +25,56 @@ if not 'drv': power_down_delay=0.1, has_limit_switches=True, has_home=True, + fast_poll = 0.1, ) -Mod('F_sample', - 'frappy_psi.dpm.DPM3', - 'DPM driver to read out the transducer value, write and read the offset and scale factor', - # drive='drv', - value=Param(unit='N'), - uri=usb_sample, - digits=3, - scale_factor=100, - offset=0, -) +if not 'pillars': + Mod('pillars', + 'frappy_psi.dpm.DPM3', + 'DPM driver to read out the transducer value, write and read the offset and scale factor', + drive='drv', + value=Param(unit='N'), + uri=usb_pillars, + digits=1, + scale_factor=100, + offset=0, + alarm_limit=2000, + ) -Mod('F_displacement', - 'frappy_psi.dpm.DPM3', - 'DPM driver to read out the transducer value, write and read the offset and scale factor', - # drive='drv', - value=Param(unit='mV'), - uri=usb_displacement, - digits=3, - scale_factor=100, - offset=0, -) +if not 'displacement': + Mod('displacement', + 'frappy_psi.dpm.DPM3', + 'DPM driver to read out the transducer value, write and read the offset and scale factor', + drive='drv', + value=Param(unit='mV'), + uri=usb_displacement, + digits=3, + scale_factor=100, + offset=0, + alarm_limit=2000, + ) -Mod('F_load_cell', +Mod('load_cell', 'frappy_psi.dpm.DPM3', 'DPM driver to read out the transducer value, write and read the offset and scale factor', - # drive='drv', + drive='drv', value=Param(unit='N'), uri=usb_load_cell, - digits=3, - scale_factor=25696, # value at=s on the device, but without dec.pnt. - offset=64.53, + digits=1, + #scale_factor=25696, # value at=s on the device, but without dec.pnt. + #scale_factor=25696*2*10, + #scale_factor=10000, + scale_factor=-105.775*1000, + offset=65.66, + #offset=0, + alarm_limit=200, ) - +Mod('force', + 'frappy_psi.uniax.Uniax', + 'force control', + motor='drv', + transducer='load_cell', + limit=200, + pollinterval = 0.1, +) diff --git a/frappy_psi/dpm.py b/frappy_psi/dpm.py index 799b9b51..96010fa7 100644 --- a/frappy_psi/dpm.py +++ b/frappy_psi/dpm.py @@ -59,24 +59,16 @@ class DPM3(HasIO, Readable): value = Parameter(datatype=FloatRange(unit='N')) digits = Parameter('number of digits for value', IntRange(0, 5), value=2, 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) scale_factor = Parameter('all shown digits in the device menu, but without dec.pt.', FloatRange(-1e6, 1e6), readonly=False) alarm_limit = Parameter('alarm limit', FloatRange(unit='N'), readonly=False, default=2000) - _offset_done = 0 + _offset_changed = 0 - def doPoll(self): - if time.time() < self._offset_done: - offset = self.query(self.OFFSET) - if offset != self.offset: - self.log.info('offset has changed: %g, set back', offset) - self.query(self.OFFSET, offset) - self._offset_done = 0 - return - super().doPoll() + def initModule(self): + super().initModule() + if self.drive: + self.drive.register_interlock(self) def writeInitParams(self): for param in 'digits', 'offset', 'scale_factor': @@ -119,6 +111,15 @@ class DPM3(HasIO, Readable): return hex2float(hexvalue, self.digits) def read_value(self): + if self._offset_changed: + if time.time() > self._offset_changed: + self._offset_changed = 0 + else: + offset = self.query(self.OFFSET) + if offset != self.offset: + self.log.info('offset has changed: %g, set back to %g', offset, self.offset) + self.query(self.OFFSET, self.offset) + self._offset_changed = 0 value = float(self.communicate('*1B1')) if abs(value) > self.alarm_limit: if self.drive: @@ -132,7 +133,7 @@ class DPM3(HasIO, Readable): self.communicate('*1F135%02X\r*1G135' % (digits + 1)) self.query(self.SCALE, scale * 10 ** (digits - 6)) self.query(self.OFFSET, offset) - self._offset_done = time.time() + 10 + self._offset_changed = time.time() + 30 def read_digits(self): back_value = self.communicate('*1G135') @@ -143,6 +144,8 @@ class DPM3(HasIO, Readable): return digits def read_offset(self): + if self._offset_changed: + return self.offset reply = self.query(self.OFFSET) return reply diff --git a/frappy_psi/trinamic.py b/frappy_psi/trinamic.py index 1d5a1adf..372ae0f8 100644 --- a/frappy_psi/trinamic.py +++ b/frappy_psi/trinamic.py @@ -166,13 +166,14 @@ class Motor(PersistentMixin, HasIO, Drivable): pullup_inputs = Parameter('activate pullup', BoolType(), group='more', default=False) interlock_reason = Parameter('external interlock', StringType(), group='more', readonly=False, default='') + fast_poll = Parameter('poll interval while driving', FloatRange(0), + group='more', readonly=False, default=0.5) pollinterval = Parameter(group='more') target_min = Limit() target_max = Limit() ioClass = BytesIO - fast_poll = 0.5 _run_mode = RUN_IDLE _calc_timeout = True _need_reset = None @@ -181,6 +182,7 @@ class Motor(PersistentMixin, HasIO, Drivable): _drv_try = 0 _limit_error_state = 0 _idle_status = IDLE, '' + _interlock_sensors = None def comm(self, cmd, adr, value=0, bank=0): """set or get a parameter @@ -266,6 +268,11 @@ class Motor(PersistentMixin, HasIO, Drivable): self.status = self._idle_status = ERROR, 'saved encoder value does not match reading' self._write_axispar(adjusted_encoder - self.zero, ENCODER_ADR, ANGLE_SCALE, readback=False) + def register_interlock(self, sensor): + if self._interlock_sensors is None: + self._interlock_sensors = {} + self._interlock_sensors[sensor.name] = sensor + def _read_axispar(self, adr, scale=1): value = self.comm(GET_AXIS_PAR, adr) # do not apply scale when 1 (datatype might not be float) @@ -304,6 +311,8 @@ class Motor(PersistentMixin, HasIO, Drivable): return self._write_axispar(value, *HW_ARGS[pname]) def doPoll(self): + for sensor in self._interlock_sensors.values(): + sensor.doPoll() self.read_status() # read_value is called by read_status def read_value(self): @@ -368,15 +377,11 @@ class Motor(PersistentMixin, HasIO, Drivable): return WARN, LIMITS_PAST[self._limit_error_state] return self._idle_status if self.interlock_reason: + self._run_mode = RUN_IDLE return ERROR, self.interlock_reason now = time.time() if self.steppos != oldpos: self._last_change = now - if now < self._last_change + 0.25 + self.fast_poll: - if not self.read_target_reached(): - if self.status[0] == BUSY: - return self.status - return BUSY, 'moving' if self.has_limit_switches: bits = self.read_input_bits() if self._run_mode == RUN_DRIVE: @@ -388,6 +393,11 @@ class Motor(PersistentMixin, HasIO, Drivable): self._idle_status = ERROR, lim_text self._stop_motor(lim_text) return self.status + if now < self._last_change + 0.25 + self.fast_poll: + if not self.read_target_reached(): + if self.status[0] == BUSY and not self.status[1].startswith('changed'): + return self.status + return BUSY, 'moving' reason = '' if self.read_move_status(): reason = self.move_status.name @@ -462,7 +472,11 @@ class Motor(PersistentMixin, HasIO, Drivable): self._limit_error_state = 0 self._limits_check_mask = LIMITS_MASK if self.interlock_reason: - raise ImpossibleError(self.interlock_reason) + if self.auto_reset: + self.write_interlock_reason('') + self.doPoll() + if self.interlock_reason: + raise ImpossibleError(self.interlock_reason) limit_state = self.read_input_bits() & LIMITS_MASK if limit_state: diff = target - self.steppos @@ -481,7 +495,7 @@ class Motor(PersistentMixin, HasIO, Drivable): self._drv_try = 0 self._stable_since = 0 self.start_motor(target) - self.status = BUSY, 'changed target' + self.status = BUSY, f'changed target {self._limits_check_mask}' def write_zero(self, value): self.zero = value @@ -530,8 +544,13 @@ class Motor(PersistentMixin, HasIO, Drivable): @Command() def reset(self): """set steppos to encoder value, if not within tolerance""" + self.write_interlock_reason('') if self._run_mode: - raise IsBusyError('can not reset while moving') + if self._run_mode == RUN_DRIVE: + raise IsBusyError(f'can not reset while moving {self._run_mode}') + self.doPoll() # read sensors again + if self.interlock_reason: + raise IsBusyError(f'can not reset {self.interlock_reason}') tol = ENCODER_RESOLUTION * 1.1 for itry in range(10): diff = self.read_encoder() - self.read_steppos()