Example #1
0
 def _check_start_status(self):
     if hasattr(self, '_HW_readStatusWord'):
         self.log.debug('_check_start_status')
         stat = self._HW_readStatusWord()
         if stat & (1 << 10):
             raise MoveError('Limit switch hit by HW')
         if stat & (1 << 11):
             raise MoveError('stop issued')
         if stat & (1 << 12):
             raise MoveError('Target ignored by HW')
Example #2
0
    def doStart(self, target):
        self.log.debug('SingleMotorOfADoubleMotorNOK for %s to %s', self.name,
                       target)
        if self._seq_is_running():
            raise MoveError(self, 'Cannot start device, it is still moving!')
        incmin, incmax = self._attached_both.inclinationlimits
        both = self._attached_both
        port = self._attached_both._attached_device

        if self.index == 1:
            code = 0x204
            inclination = both.read(0)[0]
        else:
            code = 0x104
            inclination = both.read(0)[1]
        self.log.debug('code 0x%03X d%d', code, code)

        inclination = target - inclination
        if incmin > inclination:
            brother = target - incmin / 2
        elif incmax < inclination:
            brother = target - incmax / 2
        else:
            self.log.debug('legal driving range')
            port._startSequence(
                port._generateSequence([target + both.masks[both.mode]],
                                       [self.index], code))
            return

        self.log.debug('brother move %.2f', brother)
        if self.index == 1:
            both.move([brother, target])
        else:
            both.move([target, brother])
Example #3
0
    def _checkDragerror(self):
        """Check if a "drag error" occurred.

        The values of motor and coder deviate too much.  This indicates that
        the movement is blocked.

        This method sets the error state and returns False if a drag error
        occurs, and returns True otherwise.
        """
        if self._maxdiff <= 0:
            return True
        diff = abs(self._attached_motor.read() - self._attached_coder.read())
        self.log.debug('motor/coder diff: %s', diff)
        if diff > self._maxdiff:
            self._errorstate = MoveError(
                self, 'drag error (primary coder): '
                'difference %.4g, maximum %.4g' % (diff, self._maxdiff))
            return False
        for obs in self._attached_obs:
            diff = abs(self._attached_motor.read() - obs.read())
            if diff > self._maxdiff:
                self._errorstate = PositionError(
                    self, 'drag error (%s): difference %.4g, maximum %.4g' %
                    (obs.name, diff, self._maxdiff))
                return False
        return True
Example #4
0
    def _startRaw(self, pos):
        if self._seq_is_running():
            if self._mode == SIMULATION:
                self._seq_thread.join()
                self._seq_thread = None
            else:
                raise MoveError(
                    self, 'Cannot start device, sequence is still '
                    'running (at %s)!' % self._seq_status[1])

        # switch det_img alias synchronously, the chopper sets its mode param!
        det_img_alias = session.getDevice('det_img')
        if pos[3]:
            det_img_alias.alias = 'det_img_jum'
        else:
            det_img_alias.alias = 'det_img_ge'

        seq = []
        seq.append(SeqDev(self._attached_attenuator, pos[4]))
        if pos[3]:
            seq.append(
                SeqDev(self._attached_det_z, self.detbackpos, stoppable=True))
            seq.append(SeqDev(self._attached_psd_y, pos[1], stoppable=True))
            seq.append(SeqDev(self._attached_psd_x, pos[0], stoppable=True))
        else:
            seq.append(SeqDev(self._attached_psd_x, 0, stoppable=True))
            seq.append(
                SeqDev(self._attached_psd_y, self.psdtoppos, stoppable=True))
            seq.append(SeqDev(self._attached_bs_y, pos[1], stoppable=True))
            seq.append(SeqDev(self._attached_bs_x, pos[0], stoppable=True))
            seq.append(SeqDev(self._attached_det_z, pos[2], stoppable=True))
            # maybe reposition beamstop Y axis to counter jitter.
            seq.append(SeqCall(self._check_bsy, pos[1]))

        self._startSequence(seq)
Example #5
0
    def _checkMoveToTarget(self, target, pos):
        """Check that the axis actually moves towards the target position.

        This method sets the error state and returns False if a drag error
        occurs, and returns True otherwise.
        """
        delta_last = self._lastdiff
        delta_curr = abs(pos - target)
        self.log.debug('position delta: %s, was %s', delta_curr, delta_last)
        # at the end of the move, the motor can slightly overshoot during
        # movement we also allow for small jitter, since airpads usually wiggle
        # a little resulting in non monotonic movement!
        ok = (delta_last >= (delta_curr - self.jitter)) or \
            delta_curr < self.precision
        # since we allow to move away a little, we want to remember the
        # smallest distance so far so that we can detect a slow crawl away from
        # the target which we would otherwise miss
        self._lastdiff = min(delta_last, delta_curr)
        if not ok:
            self._errorstate = MoveError(
                self, 'not moving to target: '
                'last delta %.4g, current delta %.4g' %
                (delta_last, delta_curr))
            return False
        return True
Example #6
0
    def _startRaw(self, pos):
        if self._seq_is_running():
            if self._mode == SIMULATION:
                self._seq_thread.join()
                self._seq_thread = None
            else:
                raise MoveError(
                    self, 'Cannot start device, sequence is still '
                    'running (at %s)!' % self._seq_status[1])

        det_z = self._attached_det_z
        seq = []
        seq.append(SeqDev(self._attached_bs_y, pos[1], stoppable=True))
        seq.append(SeqDev(self._attached_bs_x, pos[0], stoppable=True))
        seq.append(SeqDev(det_z, pos[2], stoppable=True))

        # if z has to move, reposition beamstop y afterwards by going to
        # some other value (damping vibrations) and back
        if self.beamstopsettlepos is not None and \
           abs(det_z.read(0) - pos[2]) > det_z.precision:
            seq.append(
                SeqDev(self._attached_bs_y,
                       self.beamstopsettlepos,
                       stoppable=True))
            seq.append(SeqSleep(30))
            seq.append(SeqDev(self._attached_bs_y, pos[1], stoppable=True))

        self._startSequence(seq)
Example #7
0
    def _checkTargetPosition(self, target, pos, error=True):
        """Check if the axis is at the target position.

        This method returns False if not arrived at target, or True otherwise.
        """
        diff = abs(pos - target)
        prec = self.precision
        if (0 < prec <= diff) or (prec == 0 and diff):
            msg = 'precision error: difference %.4g, precision %.4g' % \
                  (diff, self.precision)
            if error:
                self._errorstate = MoveError(msg)
            else:
                self.log.debug(msg)
            return False
        maxdiff = self.dragerror
        for obs in self._attached_obs:
            diff = abs(target - (obs.read() - self.offset))
            if 0 < maxdiff < diff:
                msg = 'precision error (%s): difference %.4g, maximum %.4g' % \
                      (obs, diff, maxdiff)
                if error:
                    self._errorstate = PositionError(msg)
                else:
                    self.log.debug(msg)
                return False
        return True
Example #8
0
 def doStart(self, target):
     if target == 'open' and not self._attached_data_in.read(0) & 0b100:
         raise MoveError(self, 'cannot open shutter: set to local mode')
     # bit 0: data valid, bit 1: open, bit 2: close (inverted)
     self._attached_data_out.start(0)
     time.sleep(0.1)
     self._attached_data_out.start(0b111 if target == 'open' else 0b001)
Example #9
0
 def doFinish(self):
     pos = self.read(0)
     if not self.isAtTarget(pos):
         raise MoveError(
             self, 'did not arrive at requested volume, '
             'check end switches!')
     return False  # don't check again
Example #10
0
 def doReference(self):
     if self._seq_is_running():
         raise MoveError(self, 'Cannot reference a moving device!')
     seq = self._gen_ref_sequence()
     if self.autopower == 'on':
         # disable if requested.
         seq.append(SeqMethod(self, '_HW_disable'))
     self._startSequence(seq)
Example #11
0
 def doStart(self, target):
     if self._seq_is_running():
         if self._mode == SIMULATION:
             self._seq_thread.join()
             self._seq_thread = None
         else:
             raise MoveError(self, 'Cannot start device, sequence is still '
                                   'running (at %s)!' % self._seq_status[1])
     self._startSequence(self._generateSequence(target))
Example #12
0
    def doReference(self):
        """Reference the NOK in a sophisticated way.

        First we try to reach the lowest point ever needed for referencing,
        then we reference the lower refpoint first, and the higher later.
        After referencing is done, we go to (0, 0).
        """
        # XXX: EXTRA BIG TODO !!!
        if self._seq_is_running():
            raise MoveError(self, 'Cannot reference device, it is still '
                            'moving!')

        devices = self._devices
        refpos = [d.refpos for d in devices]

        # referencing is easier if device[0].refpos is always lower than
        #  device[1].refpos
        if refpos[1] < refpos[0]:
            # wrong order: flip oder of entries
            devices.reverse()
            refpos.reverse()

        # go below lowest interesting point
        minpos = min(self.read() + refpos +
                     [t + self.backlash for t in refpos])

        # build a referencing sequence
        sequence = []

        # go to lowest position first
        sequence.append([SeqDevMin(d, minpos) for d in devices])

        # if one of the motors should have triggered the low-level-switch
        # move them up a little and wait until the movement has finished
        sequence.append([
            SeqMoveOffLimitSwitch(d, backoffby=self.backlash / 4.)
            for d in devices
        ])

        # ref lowest position, should finish at refpos[0]
        # The move should be first, as the referencing may block!
        sequence.append([
            SeqDev(devices[1], refpos[0]),
            SeqMethod(devices[0], 'reference')
        ])

        # ref highest position, should finish at refpos[1]
        sequence.append([
            SeqDev(devices[0], refpos[1]),
            SeqMethod(devices[1], 'reference')
        ])

        # fun: move both to 0
        sequence.append([SeqDev(d, 0) for d in devices])

        # GO
        self._startSequence(sequence)
Example #13
0
 def doStart(self, pos):
     if pos == 'out':
         self._attached_moveable.start(self.outpos)
         return
     respos = self._attached_resolution.target
     if respos != 'unknown':
         inpos = self._attached_resolution.presets[respos]['beamstop_x_in']
         self._attached_moveable.start(inpos)
     else:
         raise MoveError('no position for beamstop, resolution is unknown')
Example #14
0
 def doStart(self, value, fromvarcheck=False):
     self._taco_guard(self._dev.write, value + self.offset)
     session.delay(0.5)  # wait until server goes into "moving" status
     if self.variance > 0:
         newvalue = self.wait()
         maxdelta = value * (self.variance/100.) + 0.1
         if abs(newvalue - value) > maxdelta:
             if not fromvarcheck:
                 self.log.warning('value %s instead of %s exceeds variance',
                                  newvalue, value)
                 self.doStart(value, fromvarcheck=True)
             else:
                 raise MoveError(self,
                                 'power supply failed to set correct value')
Example #15
0
 def doStart(self, pos):
     # do not start moving if already there, since the stability check in
     # the SPS always waits
     if pos == self.target and abs(self.read(0) - pos) < self.precision:
         return
     stbits = self._attached_status.read(0)
     if not stbits & 1:
         raise MoveError(self, 'selector is in local mode')
     # valid bit needs a rising edge
     self._attached_valid.move(0)
     self._attached_speed.maw(pos)
     time.sleep(0.2)
     self._attached_valid.move(1)
     time.sleep(0.2)
Example #16
0
 def doStart(self, pos):
     if self.curstatus[0] == status.DISABLED:
         raise MoveError(self, 'cannot move, motor is disabled')
     pos = float(pos) + self.offset
     if self._thread:
         self._setROParam('curstatus', (status.BUSY, 'waiting for stop'))
         self._stop = True
         self._thread.join()
     if self.speed != 0:
         self._setROParam('curstatus', (status.BUSY, 'virtual moving'))
         self._thread = createThread('virtual motor %s' % self,
                                     self.__moving, (pos, ))
     else:
         self.log.debug('moving to %s', pos)
         self._setROParam('curvalue', pos)
         self._setROParam('curstatus', (status.OK, 'idle'))
Example #17
0
    def doReference(self):
        """Reference the NOK.

        Just set the do_reference bit and wait for completion
        """
        if self._seq_is_running():
            raise MoveError(self, 'Cannot reference device, it is still '
                            'moving!')

        # according to docu it is sufficient to set the ref bit of one of the
        # coupled motors
        for dev in self._devices:
            dev._HW_reference()

        for dev in self._devices:
            dev.wait()
Example #18
0
 def doStatus(self, maxage=0):
     st = TimerChannel.doStatus(self, maxage)
     # Normal mode: Gate is active
     if st[0] == status.BUSY:
         if self.extmode and self.extwait and self._mode == MASTER:
             self.log.info('external signal arrived, counting...')
             self.extwait = 0
         return st
     elif self.extmode and self.extwait > 0:
         # External mode: there is no status indication of "waiting",
         # so use the time as an indication of wait/done
         if self._dev.value > 0:
             return (status.OK, '')
         elif currenttime() > self.extwait + self.exttimeout:
             raise MoveError(self, 'timeout waiting for external start')
         return (status.BUSY, 'waiting for external start')
     else:
         return (status.OK, '')
Example #19
0
    def _doStartPositions(self, positions):
        if self._seq_is_running():
            if self._mode == SIMULATION:
                self._seq_thread.join()
                self._seq_thread = None
            else:
                raise MoveError(
                    self, 'Cannot start device, sequence is still '
                    'running (at %s)!' % self._seq_status[1])

        f = self.coordinates == 'opposite' and -1 or +1
        tl, tr, tb, tt = positions
        # determine which axes to move first, so that the blades can
        # not touch when one moves first
        cl, cr, cb, ct = [d.read(0) for d in self._axes]
        cl *= f
        cb *= f
        al, ar, ab, at = self._axes
        seq = []
        if tr < cr and tl < cl:
            # both move to smaller values, need to start right blade first
            seq.append(SeqDev(al, tl * f))
            seq.append(SeqDev(ar, tr))
        elif tr > cr and tl > cl:
            # both move to larger values, need to start left blade first
            seq.append(SeqDev(ar, tr))
            seq.append(SeqDev(al, tl * f))
        else:
            # don't care
            seq.append(SeqDev(ar, tr))
            seq.append(SeqDev(al, tl * f))
        if tb < cb and tt < ct:
            seq.append(SeqDev(ab, tb * f))
            seq.append(SeqDev(at, tt))
        elif tb > cb and tt > ct:
            seq.append(SeqDev(at, tt))
            seq.append(SeqDev(ab, tb * f))
        else:
            seq.append(SeqDev(at, tt))
            seq.append(SeqDev(ab, tb * f))

        self._startSequence(seq)
Example #20
0
    def doStart(self, targets):
        """Generate and start a sequence if none is running.

        The sequence is optimised for negative backlash.
        It will first move both motors to the lowest value of
        (target + backlash, current_position) and then
        to the final target.
        So, inbetween, the NOK should be parallel to the beam.
        MP 12.12.2017 09:16:05
        """
        if self._seq_is_running():
            raise MoveError(self, 'Cannot start device, it is still moving!')

        # check precision, only move if needed!
        traveldists = [
            target - dev.read(0) - ofs
            for target, dev, ofs in zip(targets, self._devices, self.offsets)
        ]
        if max(abs(v) for v in traveldists) <= self.precision:
            return

        devices = self._devices

        # XXX: backlash correction and repositioning later

        # build a moving sequence
        sequence = []

        # now go to target
        sequence.append([
            SeqDev(d, t + ofs, stoppable=True)
            for d, t, ofs in zip(devices, targets, self.offsets)
        ])

        # now go to target again
        sequence.append([
            SeqDev(d, t + ofs, stoppable=True)
            for d, t, ofs in zip(devices, targets, self.offsets)
        ])

        self.log.debug('Seq: %r', sequence)
        self._startSequence(sequence)
Example #21
0
 def doStart(self, target):
     if self._seq_is_running():
         raise MoveError(self, 'Cannot start device, it is still moving!')
     self._startSequence(self._gen_move_sequence(target))
Example #22
0
 def _check_speed(self):
     if self._attached_selector.read(0) > self.maxtiltspeed + 50:
         raise MoveError(self, 'selector not in safe speed range')
Example #23
0
 def doStart(self, pos):
     if self._attached_is_enabled.read():
         return MappedMoveable.doStart(self, pos)
     raise MoveError(self, 'Device is disabled')
Example #24
0
 def doStart(self, target):
     self.log.debug('DoubleMotorBeckhoff move to %s', target)
     if self._seq_is_running():
         raise MoveError(self, 'Cannot start device, it is still moving!')
     self._startSequence(self._generateSequence(target, [0, 1], 0x304))
Example #25
0
    def doStart(self, value):
        if self._get_pv('drivepv') != 1:
            raise MoveError('Chopper drive must be active to change phase')

        self._put_pv('writepv', value)
Example #26
0
 def doStart(self, pos):
     """go to a absolute postition"""
     if self.doStatus(0)[0] != status.OK:
         raise MoveError('Can not start, please check status!')
     pos = int(pos * self.slope * self.microstep)
     self.comm('XE%d' % pos)