Beispiel #1
0
    def _handleNewChunk(self, chunk):
        self._cumBuf = np.concatenate((self._cumBuf, chunk))

        while len(self._cumBuf) >= self.chunkSize:
            properChunk = self._cumBuf[:self.chunkSize].copy()
            self._cumBuf = self._cumBuf[self.chunkSize:].copy()

            if self._axis is None:
                axis = Q_(np.arange(len(properChunk)))
            else:
                axis = self._axis.copy()

            properChunk = Q_(properChunk, 'V')
            dataSet = DataSet(properChunk, [axis])
            self.set_trait('currentDataSet', dataSet)

            cur = time.perf_counter()
            rate = 1.0 / (cur - self._lastTime)
            self.set_trait('dataRate', Q_(rate, 'Hz'))
            self._lastTime = cur

            self._chunkReady(dataSet)

            for fut in self.__pendingFutures:
                if not fut.done():
                    fut.set_result(dataSet)

            self.__pendingFutures = []
Beispiel #2
0
    def __init__(self,
                 connection=None,
                 axis=1,
                 pitch=Q_(1),
                 objectName=None,
                 loop=None):
        """ Axis `axis` at connection `connection`. Has pitch `pitch` in units
        of 'full step count/length'."""
        super().__init__(objectName=objectName, loop=loop)
        self.connection = connection
        self.axis = axis
        self._status = '?'
        self.set_trait('statusMessage', self._StatusMap[self._status])
        self._isMovingFuture = asyncio.Future()
        self._isMovingFuture.set_result(None)

        self.prefPosUnit = (ureg.count / pitch).units
        self.prefVelocUnit = (ureg.count / ureg.s / pitch).units
        self.setPreferredUnits(self.prefPosUnit, self.prefVelocUnit)

        self._microstepResolution = 50
        self._pitch = pitch
        self.define_context()

        if not pitch.dimensionless:
            self.velocity = Q_(1, 'mm/s')
        else:
            self.velocity = Q_(2000, 'count/s')
Beispiel #3
0
    async def initialize(self):
        self.clearStack()
        self.set_trait('identification', await self._raw.nidentify(type=str))

        limits = await self._raw.getnlimit(type=float)
        self._hardwareMinimum = Q_(limits[0], 'mm')
        self._hardwareMaximum = Q_(limits[1], 'mm')
        self.velocity = Q_(await self._raw.gnv(type=float), 'mm/s')

        # 500 mm/s accelleration should be good enough
        self._raw.sna(500)
Beispiel #4
0
    def __init__(self, objectName=None, loop=None):
        super().__init__(objectName='PI tabular measurements', loop=loop)

        self.dataSaver = DataSaver(objectName="Data Saver")

        self.pi_conn = PI.Connection(PI_port)
        #self.mani_conn2 = PI.Connection(Manip2_comport)

        pi_stage = PI.AxisAtController(self.pi_conn)
        pi_stage.objectName = "PI C-867 DLine"
        pi_stage.setPreferredUnits(ureg.ps, ureg.ps / ureg.s)

        self.TimeDomainScan = Scan(objectName='TimeDomainScan')
        self.TimeDomainScan.manipulator = pi_stage
        resource = rm.open_resource(SR7230_LAN_Port)
        self.TimeDomainScan.dataSource = SR7230(resource, ethernet=True)
        self.TimeDomainScan.dataSource.objectName = "SR7230"

        self.TimeDomainScan.continuousScan = True
        self.TimeDomainScan.minimumValue = Q_(840, 'ps')
        self.TimeDomainScan.maximumValue = Q_(910, 'ps')
        self.TimeDomainScan.overscan = Q_(1, 'ps')
        self.TimeDomainScan.step = Q_(0.05, 'ps')
        self.TimeDomainScan.positioningVelocity = Q_(40, 'ps/s')
        self.TimeDomainScan.scanVelocity = Q_(1, 'ps/s')
        self.TimeDomainScan.retractAtEnd = True

        self.dataSource = self.TimeDomainScan

        self.mani_conn1 = PI.Connection(Manip1_comport)
        manipulator1 = PI.AxisAtController(self.mani_conn1)
        manipulator1.setPreferredUnits(ureg.mm, ureg.mm / ureg.s)
        manipulator1.objectName = "PI C-863 Manip"
        self.manipulator1 = manipulator1
        self.positioningVelocityM1 = Q_(4, 'mm/s')
        self.scanVelocity = Q_(4, 'mm/s')

        manipulator2 = DummyManipulator(
        )  # PI.AxisAtController(self.mani_conn2)
        manipulator2.setPreferredUnits(ureg.mm, ureg.mm / ureg.s)
        manipulator2.objectName = 'DummyManipulator 2'
        self.manipulator2 = manipulator2
        self.positioningVelocityM1 = Q_(4, 'mm/s')
        self.scanVelocity = Q_(4, 'mm/s')

        self.dataSaver.registerManipulator(self.manipulator1, 'Position1')
        self.dataSaver.registerManipulator(self.manipulator2, 'Position2')
        self.dataSaver.registerObjectAttribute(self, 'currentMeasurementName',
                                               'currentTableEntry')
        self.dataSaver.fileNameTemplate = '{date}-{name}-{currentTableEntry}-{Position1}-{Position2}'
        self.dataSaver.set_trait('path', Path(r''))
        self.TimeDomainScan.addDataSetReadyCallback(self.dataSaver.process)
        self.TimeDomainScan.addDataSetReadyCallback(self.setCurrentData)
        self._backAndForth = True
Beispiel #5
0
 async def readDataSet(self):
     if self.samplingMode == SR7230.SamplingMode.SingleShot:
         data = np.array(await self.readCurrentOutput())
         dataSet = DataSet(Q_(data), [])
         self._dataSetReady(dataSet)
         return dataSet
     elif self.samplingMode == SR7230.SamplingMode.Buffered:
         data = await self.readDataBuffer()
         data = np.array(data)
         dataSet = DataSet(Q_(data), [Q_(np.arange(0, len(data)))])
         self._dataSetReady(dataSet)
         return dataSet
Beispiel #6
0
    def __init__(self, objectName=None, loop=None):
        super().__init__(objectName='PI tabular measurements', loop=loop)

        self.dataSaver = DataSaver(objectName="Data Saver")

        self.pi_conn = PI.Connection(PI_Comport)
        self.mani_conn = PI.Connection(PI_Manipulator)

        pi_stage = PI.AxisAtController(
            self.pi_conn,
            ignore216=True)  # ignore216 implemented by JanO Warning!
        pi_stage.objectName = "PI C-863 DLine"
        pi_stage.setPreferredUnits(ureg.ps, ureg.ps / ureg.s)

        self.TimeDomainScan = Scan(objectName='TimeDomainScan')
        self.TimeDomainScan.manipulator = pi_stage
        self.TimeDomainScan.dataSource = SR830(rm.open_resource(SR800_Port))
        self.TimeDomainScan.dataSource.objectName = "SR830"

        self.TimeDomainScan.continuousScan = True
        self.TimeDomainScan.minimumValue = Q_(1250, 'ps')
        self.TimeDomainScan.maximumValue = Q_(1315, 'ps')
        self.TimeDomainScan.overscan = Q_(3, 'ps')
        self.TimeDomainScan.step = Q_(0.05, 'ps')
        self.TimeDomainScan.positioningVelocity = Q_(30, 'ps/s')
        self.TimeDomainScan.scanVelocity = Q_(1.6, 'ps/s')
        self.TimeDomainScan.retractAtEnd = True

        self.dataSource = self.TimeDomainScan

        manipulator1 = PI.AxisAtController(
            self.mani_conn,
            ignore216=True)  # ignore216 implemented by JanO Warning!
        # ignore216 = True means that the error 216 (driven into end switch) will be ignored. There is a problem with the
        # PI stage being used as a manipulator. It is showing this error despite being far away form the end siwtch or even not moving
        manipulator1.setPreferredUnits(ureg.mm, ureg.mm /
                                       ureg.s)  # added JanO 22.1.2019
        manipulator1.objectName = 'PI C-863'
        self.manipulator1 = manipulator1
        self.positioningVelocityM1 = Q_(4, 'mm/s')
        self.scanVelocity = Q_(4, 'mm/s')

        manipulator2 = TMCL(objectName="TMCL Rotator", port=tmcl_port)
        manipulator2.setPreferredUnits(
            ureg.deg,
            ureg.dimensionless)  # ureg.dimensionless, ureg.mm / ureg.s
        self.manipulator2 = manipulator2

        self.dataSaver.registerManipulator(self.manipulator1, 'Position')
        self.dataSaver.registerManipulator(self.manipulator2, 'Rotation')
        self.dataSaver.registerObjectAttribute(self, 'currentMeasurementName',
                                               'currentTableEntry')
        self.dataSaver.fileNameTemplate = '{date}-{name}-{currentTableEntry}-{Position}-{Rotation}'
        self.dataSaver.set_trait('path', Path(
            'E:/Messdaten/test/'))  #added by Cornelius as standard savepath
        self.TimeDomainScan.addDataSetReadyCallback(self.dataSaver.process)
        self.TimeDomainScan.addDataSetReadyCallback(self.setCurrentData)
        self._backAndForth = True
Beispiel #7
0
    async def singleUpdate(self):
        movFut = self._isMovingFuture

        self._status = await self.send("SRG?", 1)

        self.set_trait('value', Q_(await self.send(b'POS?'), 'mm'))

        self.set_trait('isReferenced', bool(await self.send(b'FRF?')))
        self.set_trait('isReferencing',
                       bool(self._status & self.StatusBits.Referencing.value))
        self.set_trait('isOnTarget',
                       bool(self._status & self.StatusBits.OnTarget.value))
        self.set_trait('isServoOn',
                       bool(self._status & self.StatusBits.ServoMode.value))
        self.set_trait(
            'isMoving',
            bool(self._status & self.StatusBits.Moving.value)
            or self.isReferencing)

        if self.isMoving:
            self.set_trait('status', self.Status.Moving)
        else:
            self.set_trait('status', self.Status.Idle)

        if not movFut.done() and not self.isMoving:
            movFut.set_result(None)
Beispiel #8
0
    async def singleUpdate(self):
        val = IselStage.cdll.stagedriver_current_position(self.handle)
        self.set_trait('value', Q_(val, 'microm'))

        self._updateDigitalInputFlags()
        self._updateStatusWord()
        self._updateErrorByte()

        hm = bool(IselStage.cdll.stagedriver_homing_complete(self.handle))
        tr = bool(IselStage.cdll.stagedriver_target_reached(self.handle))
        mv = bool(IselStage.cdll.stagedriver_movement_active(self.handle))
        self.set_trait('homingComplete', hm)
        self.set_trait('isOnTarget', tr)
        self.set_trait('isMoving', mv)

        if not self.isMoving:
            self.set_trait('status', self.Status.Idle)
            if not self._isMovingFuture.done():
                self._isMovingFuture.set_result(None)
        else:
            self.set_trait('status', self.Status.Moving)

        self._isOpen = bool(IselStage.cdll.stagedriver_is_open(self.handle))
        if not self._isOpen:
            logging.info('Connection To IselStage at ' + self.comport +
                         ' Lost')
Beispiel #9
0
class ThorlabsPM100(DataSource):

    power = Quantity(Q_(0, 'mW'), read_only=True).tag(name='Power')

    def __init__(self, resource=None, objectName=None, loop=None):
        super().__init__(objectName, loop)
        self._lock = Lock()
        self.resource = resource

    async def __aenter__(self):
        await super().__aenter__()
        self._continuousUpdateFut = \
            ensure_weakly_binding_future(self._continuousRead)
        return self

    async def __aexit__(self, *args):
        await super().__aexit__(*args)
        self._continuousUpdateFut.cancel()

    async def _continuousRead(self):
        while True:
            await self.readDataSet()
            await asyncio.sleep(0.1)

    @threaded_async
    def _guardedRead(self):
        with self._lock:
            return float(self.resource.ask('READ?'))

    async def readDataSet(self):
        val = await self._guardedRead() * 1000
        dset = DataSet(Q_(np.array(val), 'mW'))
        self.set_trait('power', Q_(val, 'mW'))
        self._dataSetReady(dset)
Beispiel #10
0
    async def readAllParameters(self):
        self._traitChangesDueToStatusUpdate = True

        for name, trait in self.traits().items():
            command = trait.metadata.get('command')

            if command is None:
                continue
            else:
                auxs = ''
                if command.find('AUX') >= 0:
                    auxs = ' ' + name[-1]
                result = await self.query(command + '?' + auxs)

            if isinstance(trait, traitlets.Enum):
                val = int(result)
                val = [item for item in trait.values if item.value == val][0]
            elif isinstance(trait, Quantity):
                val = Q_(float(result), trait.default_value.units)
            elif isinstance(trait, traitlets.Integer):
                val = int(result)

            self.set_trait(name, val)

        self._traitChangesDueToStatusUpdate = False
        logging.info('SR830: Lockin-Parameter read')
Beispiel #11
0
 async def getVelocity(self):
     #seems not to work ?
     #vel = self.send(str(self.axis) +  'R4000074010')[4:]
     vel = await self.connection.send(self.axis + b'R4000004040')
     vel = vel[4:]
     vel = Q_(int(vel, 16) / 300.0 * self._leadpitch, 'mm/s')
     return vel
Beispiel #12
0
    async def readAllParameters(self):
        """
        Reads all parameters from the device and updates the attributes of this class accordingly.
        """

        self._traitChangesDueToStatusUpdate = True

        for name, trait in self.traits().items():
            command = trait.metadata.get('command')

            if command is None:
                continue
            else:
                answer = await self.query(command)

            if len(answer) == 1:
                result = answer[0]
            else:
                result = answer

            if isinstance(trait, traitlets.Enum):
                if len(answer) == 1:
                    val = int(result)
                    val = [item for item in trait.values
                           if item.value == val][0]
                else:
                    res = []
                    for i in answer:
                        ival = int(i)
                        res.append(ival)
                    # if first element is 0, (like [0, 1]) then LF is off
                    if res[0] != 0:
                        val = [
                            item for item in trait.values if item.value == res
                        ][0]
                    else:
                        val = list(trait.values)[0]
            elif isinstance(trait, Quantity):
                val = Q_(float(result), trait.default_value.units)
            elif isinstance(trait, traitlets.Int):
                val = int(result)
            elif isinstance(trait, traitlets.Bool):
                result_int = 0
                try:
                    result_int = int(result)
                except ValueError:
                    print('Failed to read answer from ' + command +
                          " answer was " + str(result))
                    logging.info('Failed to read answer from ' + command +
                                 " answer was " + str(result))

                val = True if result_int == 1 else False
            else:
                val = result

            self.set_trait(name, val)

        self._traitChangesDueToStatusUpdate = False
        logging.info('SR7230: Lockin-Parameter read')
Beispiel #13
0
    def __init__(self, port, baud=9600, axis=0, objectName=None, loop=None):
        super().__init__(objectName=objectName, loop=loop)

        self.comm_lock = Lock()
        self.comm = TMCLCommunicator(port, 1, 4, 0, float('inf'), float('inf'),
                                     float('inf'))
        self.comm._ser.baudrate = baud
        self.axis = axis

        self.setPreferredUnits(ureg.deg, ureg.dimensionless)

        self.velocity = Q_(20)
        self.set_trait('value', Q_(0, 'deg'))

        self.set_trait('status', self.Status.Idle)
        self._isMovingFuture = asyncio.Future()
        self._isMovingFuture.set_result(None)
Beispiel #14
0
    def _handleNewDataSet(self):
        read = mx.int32()
        buf = np.zeros((self.dataPoints, ))
        self.currentTask.ReadAnalogF64(
            mx.DAQmx_Val_Auto,
            0,  # timeout
            mx.DAQmx_Val_GroupByScanNumber,
            buf,
            buf.size,
            mx.byref(read),
            None)

        dset = DataSet(Q_(buf, 'V'), [self._axis.copy()])
        self._currentFuture.set_result(dset)
        self.set_trait('dataSet', dset)
        cur = time.perf_counter()
        rate = 1.0 / (cur - self._lastTime)
        self.set_trait('dataRate', Q_(rate, 'Hz'))
        self._loop.create_task(self.stop())
        return 0
Beispiel #15
0
    async def _singleUpdate(self):
        stepPos = await self._get_param(1)
        self.set_trait('value', Q_(self._steps2angle(stepPos), 'deg'))

        movFut = self._isMovingFuture

        if not movFut.done():
            # check for target reached
            reached = await self._get_param(8)
            if reached and not movFut.done():
                movFut.set_result(None)
Beispiel #16
0
    def __init__(self, objectName=None, loop=None):
        super().__init__(objectName='Goniometer Scan', loop=loop)

        self.dataSaver = DataSaver(objectName="Data Saver")
        self.pi_conn = PI.Connection(PI_Comport)

        pi_stage = PI.AxisAtController(self.pi_conn)
        pi_stage.objectName = "PI C-863"
        pi_stage.setPreferredUnits(ureg.ps, ureg.ps / ureg.s)

        self.manipulator = pi_stage
        self.dataSource = SR830(rm.open_resource(SR800_Port))
        self.dataSource.objectName = "SR830"

        self.continuousScan = True
        self.minimumValue = Q_(1180, 'ps')
        self.maximumValue = Q_(1250, 'ps')
        self.overscan = Q_(3, 'ps')
        self.step = Q_(0.05, 'ps')
        self.positioningVelocity = Q_(30, 'ps/s')
        self.scanVelocity = Q_(1, 'ps/s')

        self.dataSaver.fileNameTemplate = '{date}-{name}'
        self.addDataSetReadyCallback(self.dataSaver.process)
        self._backAndForth = True
Beispiel #17
0
    async def configureTrigger(self, axis, triggerId=1):
        axis = axis.to('mm').magnitude

        step = np.mean(np.diff(axis))
        start = axis[0]

        N = len(axis)
        # let the trigger output end half a step after the last position
        stop = start + (N - 1) * step + step / 2

        # enable trig output on axis
        await self.send(b"CTO", triggerId, 2, self.axis, includeAxis=False)

        # set trig output to pos+offset mode
        await self.send(b"CTO", triggerId, 3, 7, includeAxis=False)

        # set trig distance to ``step``
        await self.send(b"CTO", triggerId, 1, step, includeAxis=False)

        # trigger start position
        await self.send(b"CTO", triggerId, 10, start, includeAxis=False)

        # trigger stop position
        await self.send(b"CTO", triggerId, 9, stop, includeAxis=False)

        # enable trigger output
        await self.send(b"TRO", triggerId, 1, includeAxis=False)

        # ask for the actually set start, stop and step parameters
        self._trigStep = Q_(
            await self.send(b"CTO?", triggerId, 1, includeAxis=False), 'mm')
        self._trigStart = Q_(
            await self.send(b"CTO?", triggerId, 10, includeAxis=False), 'mm')
        self._trigStop = Q_(
            await self.send(b"CTO?", triggerId, 9, includeAxis=False), 'mm')

        return np.arange(self._trigStart.magnitude, self._trigStop.magnitude,
                         self._trigStep.magnitude) * ureg.mm
Beispiel #18
0
    async def statusUpdate(self):
        """
        Performs a status update and updates the class attributes according to answers from the device.
        """

        if self.status != Manipulator.Status.Moving and self.status != Manipulator.Status.Error:  # and not self.stopped:
            currentPosition = (await self.query("@0P"))[0]
            # print("pos answer: " + str(currentPosition))
            currentPosition = int(currentPosition, 16)

            self.set_trait('value', Q_(currentPosition / self.stepsPerRev,
                                       'cm'))

            self._isMovingFuture.set_result(None)
Beispiel #19
0
    async def singleUpdate(self):
        movFut = self._isMovingFuture

        self._status = await self._raw.nst(type=int)
        self.set_trait('value', Q_(await self._raw.np(type=float), 'mm'))
        self.set_trait('numberParamStack', await
                       self._raw.gsp(includeAxis=False, type=int))

        self.set_trait(
            'status', self.Status.Moving
            if bool(self._status
                    & self.StatusBits.AxisMoving.value) else self.Status.Idle)

        if self.status != self.Status.Moving and not movFut.done():
            movFut.set_result(None)
Beispiel #20
0
    async def __aenter__(self):
        await super().__aenter__()

        self._identification = await self.send(b'*IDN?', includeAxis=False)
        self._hardwareMinimum = await self.send(b'TMN?')
        self._hardwareMaximum = await self.send(b'TMX?')
        self.velocity = Q_(await self.send(b'VEL?'), 'mm/s')
        self._isReferenced = bool(await self.send(b'FRF?'))

        await self.send("RON", 1)
        await self.send("SVO", 1)

        self._updateFuture = ensure_weakly_binding_future(self.updateStatus)

        return self
Beispiel #21
0
    async def setVelocity(self, velocity=Q_(10, 'mm/s'), acceleration=0.1):

        velocity = int(velocity.to('mm/s').magnitude * 300 / self._leadpitch)
        velocity = b'%04X' % velocity
        if len(velocity) > 4:
            logging.info('IAI {}: velocity too high'.format(self.axis))
            velocity = b'02EE'

        acceleration = int(acceleration * 5883.99 / self._leadpitch)
        acceleration = b'%04X' % acceleration
        if len(acceleration) > 4:
            logging.info('IAI {}: acceleration too high'.format(self.axis))
            acceleration = b'0093'

        sendstr = self.axis + b'v2' + velocity + acceleration + b'0'
        await self.connection.send(sendstr)
Beispiel #22
0
    async def run():
        transport, hydra = await loop.create_connection(
            Hydra, 'localhost', 4000)

        async with hydra:
            print("Moving to start...")
            await hydra.moveTo(Q_(20, 'mm'), Q_(10, 'mm/s'))
            await hydra.configureTrigger(Q_(0.05, 'mm'), Q_(21, 'mm'),
                                         Q_(29, 'mm'))
            print("Moving to end...")
            fut = loop.create_task(hydra.moveTo(Q_(30, 'mm'), Q_(5, 'mm/s')))
            while not fut.done():
                print("Position:", hydra.value)
                await asyncio.sleep(0.5)
            print("Done.")
Beispiel #23
0
    async def reference(self):
        if self.isMoving:
            logging.info('{} {}: Please finish'.format(self, self.axis) +
                         'movement before searching Limit Switch')
            return False

        self._setSpeedProfile(Q_(5, 'deg/s'))
        self.cdll.SetRunFreeFrq(self.axis, 100)
        self.cdll.SetRunFreeSteps(self.axis, 32000)

        self.cdll.SearchLS(self.axis, ord('-'))

        self._isMovingFuture = asyncio.Future()
        await self._isMovingFuture

        self.cdll.FindLS(self.axis, ord('-'))
        self.cdll.RunLSFree(self.axis, ord('-'))

        self._isMovingFuture = asyncio.Future()
        await self._isMovingFuture

        self.cdll.SetPosition(self.axis, 0)
Beispiel #24
0
    def __init__(self, axis=0, encoderMode=EncoderMode.A_BSignal4fold,
                 objectName=None, loop=None):
        super().__init__(objectName, loop)
        self.setPreferredUnits(ureg.deg, ureg.deg / ureg.s)
        if Goniometer.connection is None:
            Goniometer.connection = GonioConn()
        self.cdll = Goniometer.connection.dll

        self.axis = axis
        self.cdll.InitEncoder(self.axis, encoderMode.value)
        self.cdll.SetEncoder(self.axis, 0)
        self.cdll.SetRunFreeFrq(self.axis, 100)
        self.cdll.SetRunFreeSteps(self.axis, 32000)

        # don't know if important
        self.cdll.SetPosition(self.axis, 0)
        self.set_trait('value', self._stepToDeg(
                                             self.cdll.GetPosition(self.axis)))
        self.velocity = Q_(5, 'deg/s')

        self._statusRefresh = 0.1
        self._isMovingFuture = asyncio.Future()
        self._isMovingFuture.set_result(None)
        self._updateFuture = ensure_weakly_binding_future(self.updateStatus)
Beispiel #25
0
async def run(loop):
    async with Goniometer(1, objectName='Detektor') as detector:
        async with Goniometer(0, objectName='Emitter') as emitter:
            async with TimeDomainScan(loop=loop) as tdscan:

                detector.calibrate(Q_(180.0, 'deg'))
                emitter.calibrate(Q_(180.0, 'deg'))

                for angle in np.arange(10, 80, 1):
                    emitterpos = 90 + angle
                    detectorpos = 270 - angle

                    await asyncio.wait([
                        detector.moveTo(Q_(detectorpos, 'deg')),
                        emitter.moveTo(Q_(emitterpos, 'deg'))
                    ])
                    print('angle: {}'.format(angle))
                    tdscan.dataSaver.mainFileName = 'Referenz-{}'.format(angle)
                    await tdscan.readDataSet()

                await asyncio.wait([
                    detector.moveTo(Q_(180, 'deg')),
                    emitter.moveTo(Q_(180, 'deg'))
                ])
Beispiel #26
0
class IselIT116(Manipulator):
    class AxisDirection(enum.Enum):
        Normal = 0
        Inverse = 1

    class ReferenceDirection(enum.Enum):
        Normal = 0
        Inverse = 1

    class LimitSwitch1(enum.Enum):
        Disabled = 0
        Enabled = 1

    class LimitSwitch2(enum.Enum):
        Disabled = 0
        Enabled = 1

    class ActiveLevelLimitSwitch1(enum.Enum):
        LowActive = 0
        HighActive = 1

    class ActiveLevelLimitSwitch2(enum.Enum):
        LowActive = 0
        HighActive = 1

    DEFAULT_TIMEOUT = 1000
    MOVEMENT_TIMEOUT = 100000
    STATUS_UPDATE_RATE = 3

    # Instrument Info Traitlets

    controlUnitInfo = traitlets.Unicode(read_only=True,
                                        name="Control Unit Info",
                                        group="Instrument Info")

    # Parameters

    # Todo: find correct default value
    referenceSpeed = traitlets.Int(name="Reference Speed",
                                   group="Parameters",
                                   default_value=900,
                                   max=2500,
                                   command="@0d")

    acceleration = Quantity(name="Acceleration",
                            group="Parameters",
                            default_value=Q_(100, "Hz/ms"),
                            min=Q_(1, "Hz/ms"),
                            max=Q_(1000, "Hz/ms"),
                            command="@0g")

    startStopFrequency = Quantity(name="Start Stop Frequency",
                                  group="Parameters",
                                  default_value=Q_(300, "Hz"),
                                  min=Q_(20, "Hz"),
                                  max=Q_(40000, "Hz"),
                                  command="@0j")

    axisDirection = traitlets.Enum(AxisDirection,
                                   name="Axis Direction",
                                   group="Parameters",
                                   default_value=AxisDirection.Normal,
                                   command="@0ID")

    referenceDirection = traitlets.Enum(
        ReferenceDirection,
        name="Reference Direction",
        group="Parameters",
        default_value=ReferenceDirection.Normal)

    # Relative Movement

    relativeMovementPath = traitlets.Int(name="Movement Path",
                                         group="Relative Movement",
                                         default_value=0)
    relativeMovementSpeed = traitlets.Int(name="Speed",
                                          group="Relative Movement",
                                          default_value=900)

    # Absolute Movement

    absoluteMovementPosition = traitlets.Int(name="Target Position",
                                             group="Absolute Movement",
                                             default_value=0)
    absoluteMovementSpeed = traitlets.Int(name="Speed",
                                          group="Absolute Movement",
                                          default_value=900)

    stopped = traitlets.Bool(name="Stopped",
                             default_value=False,
                             read_only=True)

    parameterTraits = [
        "referenceSpeed", "acceleration", "startStopFrequency",
        "axisDirection", "referenceDirection"
    ]

    def __init__(self,
                 comport,
                 baudRate=19200,
                 stepsPerRev=800,
                 objectName=None,
                 loop=None):
        """
        Parameters
        ----------

        """

        super().__init__(objectName, loop)

        self._lock = Lock()

        self.comport = comport
        self.stepsPerRev = 2 * stepsPerRev  # not sure if correct (@0P gives correct distance)

        if os.name == 'posix':
            rm = visa.ResourceManager('@py')
        elif os.name == 'nt':
            rm = visa.ResourceManager()

        try:
            self.resource = rm.open_resource(comport)
        except visa.errors.VisaIOError:
            raise Exception('Failed to open Isel IT116 stage at comport: ' +
                            comport)
        self.resource.read_termination = ''
        self.resource.write_termination = chr(13)  # CR
        self.resource.baud_rate = baudRate
        self.resource.timeout = self.DEFAULT_TIMEOUT

        self.setPreferredUnits(ureg.mm, ureg.mm / ureg.s)

        self.observe(self.setParameterOnDevice, self.parameterTraits)

        self.set_trait('status', self.Status.Idle)
        self._isMovingFuture = asyncio.Future()
        self._isMovingFuture.set_result(None)

    async def __aenter__(self):
        await super().__aenter__()
        await self.initializeControlUnit()
        await self.getControlUnitInfo()
        await self.statusUpdate()
        self._statusUpdateFuture = ensure_weakly_binding_future(
            self.continuousStatusUpdate)
        return self

    async def __aexit__(self, *args):
        await super().__aexit__(*args)
        self._statusUpdateFuture.cancel()

    @action("Stop")
    def stop(self):
        self.resource.write_raw(bytes([253]))
        asyncio.ensure_future(self.stopImplementation())

    async def stopImplementation(self):
        result = await self.read()
        self.set_trait("stopped", True)
        if result is None:
            return

        result = result[0:-2]
        if result == "STOP":
            self.set_trait("stopped", False)

        if not self._isMovingFuture.done():
            self._isMovingFuture.cancel()

    @action("Start")
    async def start(self):
        """
        Sends a start command to the device after it has been stopped.

        Due to weird behavior of the device, this function first executes a break command causing the device to forget
        the last movement command.
        """

        await self.softwareBreak()

        result = (await self.query("@0S"))[0]
        print("start result: " + result)
        if result == "0" or result == "G":
            self.set_trait("stopped", False)

        # await asyncio.sleep(0.1)
        await self.read()

        self.set_trait("status", self.Status.Idle)

    @action("Break")
    async def softwareBreak(self):
        self.resource.write_raw(bytes([255]))
        await self.read()

    @action("Software Reset")
    async def softwareReset(self):
        self.resource.write_raw(bytes([254]))
        await self.read()

    @action("Load Parameters from Flash", group="Parameters")
    async def loadParametersFromFlash(self):
        await self.write("@0IL")

    @action("Save Parameters to Flash", group="Parameters")
    async def saveParametersToFlash(self):
        await self.write("@0IW")

    @action("Load Default Parameters", group="Parameters")
    async def loadDefaultParameters(self):
        await self.write("@0IX")

    @action("Reference Run")
    async def referenceRun(self):
        await self.executeMovementCommand("@0R1")

    @action("Simulate Reference Run")
    async def simulateReferenceRun(self):
        await self.write("@0N1")

    @action("Set Zero Point")
    async def setZeroPointCurrentLocation(self):
        await self.write("@0n1")

    @action("Move", group="Absolute Movement")
    async def moveAbsolute(self):
        await self.moveTo(self.absoluteMovementPosition,
                          self.absoluteMovementSpeed)

    @action("Move", group="Relative Movement")
    async def moveRelative(self):
        command = "@0A" + str(self.relativeMovementPath) + "," + str(
            self.relativeMovementSpeed)
        await self.executeMovementCommand(command)

    @threaded_async
    def query(self, command, timeout=None):
        """
        Sends a command to the device and reads the answer.

        Parameters
        ----------
        command : str
            The command to send to the device.
        timeout : int
            Custom timeout in ms.

        Returns
        -------
        list
            A list of answer strings from the device.
        """

        with self._lock:
            # remove parameter placeholders from command
            paramIndex = command.find(" {}")
            if paramIndex != -1:
                command = command[:paramIndex]

            print('IselIT116: query ' + str(command))
            logging.info('{}: {}'.format(self, command))

            if timeout is not None:
                prevTimeout = self.resource.timeout
                self.resource.timeout = timeout

            self.resource.write(command)
            answerBytes = self.readAllBytes()
            answerString = b''.join(answerBytes).decode("utf-8")

            print('IselIT116: answer: ' + answerString)

            if timeout is not None:
                self.resource.timeout = prevTimeout

            result = []
            for s in str.split(answerString, ','):
                result.append(s)

            return result

    @threaded_async
    def write(self, command, lock=True):
        """
        Sends a command to the device.

        Parameters
        ----------
        command : str
            The command to send to the device.
        lock : bool
            Use the lock if true. Prevents simultaneous access on the instrument.
        """

        logging.info('{}: {}'.format(self, command))
        if lock:
            with self._lock:
                self.resource.write(command)
                self.readAllBytes()
        else:
            self.resource.write(command)
            self.readAllBytes()

    @threaded_async
    def read(self):
        """
        Reads the current content of the receive buffer

        Returns
        -------
        result : str
            The read content of the receive buffer.
        """

        with self._lock:
            readBytes = self.readAllBytes()
            if len(readBytes) > 0:
                result = b''.join(readBytes).decode("utf-8")
                print("read(): result: " + result)
                return result

    def readAllBytes(self):
        """
        Reads all bytes from the receive buffer.

        Returns
        -------
        allBytes : list
            All bytes read from the receive buffer.
        """
        time.sleep(
            0.05
        )  # self.resource.bytes_in_buffer gives wrong result if called right after write
        allBytes = []
        try:
            allBytes.append(self.resource.read_bytes(1))
        except:
            print("readAllBytes: no bytes in buffer")

        while self.resource.bytes_in_buffer > 0:
            allBytes.append(self.resource.read_bytes(1))

        # some commands return "0" "handshake" before actual value
        # this is probably the wrong way to handle it
        if (allBytes[0] == b'0' and len(allBytes) != 1):
            allBytes = allBytes[1:]

        return allBytes

    def setParameterOnDevice(self, change):
        """
        Sets parameter on the device.

        This is the function that is called by all traits that get observed. Tries to update the changed attribute on
        the device by sending the corresponding command.

        Parameters
        ----------
        change : list
            change object of the observed trait.
        """

        trait = self.traits().get(change['name'])
        command = trait.metadata.get('command')
        value = change['new']

        if command is None:
            return

        self.set_trait(trait.name, value)

        if isinstance(value, enum.Enum):
            value = value.value
        elif isinstance(value, Q_):
            value = value.magnitude
        elif isinstance(value, bool):
            value = 1 if value else 0

        commandString = str()
        paramIndex = command.find("{}")
        if paramIndex == -1:
            commandString = command + '{}'.format(value)
        elif command.find("{},{}") != -1:
            commandString = command.format(value[0], value[1])
        elif paramIndex != -1:
            commandString = command.format(value)

        asyncio.ensure_future(self.write(commandString))

    async def continuousStatusUpdate(self):
        """
        Requests a status update every STATUS_UPDATE_RATE seconds.
        """

        while True:
            await asyncio.sleep(self.STATUS_UPDATE_RATE)
            await self.statusUpdate()

    async def statusUpdate(self):
        """
        Performs a status update and updates the class attributes according to answers from the device.
        """

        if self.status != Manipulator.Status.Moving and self.status != Manipulator.Status.Error:  # and not self.stopped:
            currentPosition = (await self.query("@0P"))[0]
            # print("pos answer: " + str(currentPosition))
            currentPosition = int(currentPosition, 16)

            self.set_trait('value', Q_(currentPosition / self.stepsPerRev,
                                       'cm'))

            self._isMovingFuture.set_result(None)

    async def initializeControlUnit(self):
        """
        Initialisation, setting number of axes.
        """

        await self.write("@01")

    async def getControlUnitInfo(self):
        """
        Queries info of the control unit.
        """

        info = await self.query("@0V")
        info = info[0]
        self.set_trait("controlUnitInfo", info[0:-2])

    async def moveTo(self, val: float, velocity=None):
        if self.stopped:
            print("Device is stopped. Can't process commands until started")
            return

        self.__blockTargetValueUpdate = True

        if velocity is None:
            velocity = self.velocity

        if not isinstance(val, int) and not isinstance(val, float):
            val = val.to("cm").magnitude
            val *= self.stepsPerRev

        val = int(val)

        if not isinstance(velocity, int) and not isinstance(velocity, float):
            velocity = velocity.to('cm/s').magnitude
            velocity *= 1600  # self.stepsPerRev ?
            velocity = int(velocity)
            # print("speed: " + str(velocity))

        command = "@0M" + str(val) + "," + str(velocity)
        await self.executeMovementCommand(command)

        self.__blockTargetValueUpdate = False

    async def executeMovementCommand(self, command):
        """
        Sends a command to the instrument that results in a movement of the axis.

        Since the IT116 can't process any other commands until the movement is completed, this function waits for the
        device's response that the movement was completed. Also sets the status to moving while the stage is moving.

        Parameters
        ----------
        command : str
            Movement command to send to the device.
        """

        self.set_trait("status", self.Status.Moving)
        result = (await self.query(command, self.MOVEMENT_TIMEOUT))[0]
        self._isMovingFuture = asyncio.Future()
        print("movement result: " + result)
        if result == "0":
            self.set_trait("status", self.Status.Idle)
            await self.statusUpdate()
        elif result == "F":
            print("movement stopped")
            logging.info('{}: {}'.format(self,
                                         "movement stopped. Press start"))
            self.set_trait("status", self.Status.Error)
        else:
            self.set_trait("status", self.Status.Error)

    async def waitForTargetReached(self):
        return await self._isMovingFuture
Beispiel #27
0
class SR7230(DataSource):
    """
    Implementation of the Lock-In SR7230 as a DataSource

    This class implements the Lock-In Amplifier SR7230 as a DataSource using PyVisa for the connection to the device.
    Most attributes of this class represent attributes of the device. Refer to the official manual of the SR7230 for
    more details.
    """
    class SamplingMode(enum.Enum):
        SingleShot = 0
        Buffered = 1

    # Signal Channel

    class InputMode(enum.Enum):
        VoltageInputMode = 0
        CurrentModeHighBandwidth = 1
        CurrentModeLowNoise = 2

    class VoltageInputMode(enum.Enum):
        BothInputsGrounded = 0
        AInputOnly = 1
        BInputOnly = 2
        ABDifferentialMode = 3

    class InputConnectorShieldControl(enum.Enum):
        Ground = 0
        Float = 1

    class InputDevice(enum.Enum):
        Bipolar = 0
        FET = 1

    class InputCoupling(enum.Enum):
        AC = 0
        DC = 1

    class SensitivityIMode0(enum.Enum):
        Sens_10nV = 3
        Sens_20nV = 4
        Sens_50nV = 5
        Sens_100nV = 6
        Sens_200nV = 7
        Sens_500nV = 8
        Sens_1muV = 9
        Sens_2muV = 10
        Sens_5muV = 11
        Sens_10muV = 12
        Sens_20muV = 13
        Sens_50muV = 14
        Sens_100muV = 15
        Sens_200muV = 16
        Sens_500muV = 17
        Sens_1mV = 18
        Sens_2mV = 19
        Sens_5mV = 20
        Sens_10mV = 21
        Sens_20mV = 22
        Sens_50mV = 23
        Sens_100mV = 24
        Sens_200mV = 25
        Sens_500mV = 26
        Sens_1V = 27

    class ACGain(enum.Enum):
        Gain_0dB = 0
        Gain_6dB = 1
        Gain_12dB = 2
        Gain_18dB = 3
        Gain_24dB = 4
        Gain_30dB = 5
        Gain_36dB = 6
        Gain_42dB = 7
        Gain_48dB = 8
        Gain_54dB = 9
        Gain_60dB = 10
        Gain_66dB = 11
        Gain_72dB = 12
        Gain_78dB = 13
        Gain_84dB = 14
        Gain_90dB = 15

    class ACGainControl(enum.Enum):
        Manual = 0
        Automatic = 1

    class NotchFilter(enum.Enum):
        Off = [0, 0]
        NotchFilter_50Hz = [1, 0]
        NotchFilter_60Hz = [1, 1]
        NotchFilter_100Hz = [2, 0]
        NotchFilter_120Hz = [2, 1]
        NotchFilter_50Hz_100Hz = [3, 0]
        NotchFilter_60Hz_120Hz = [3, 1]

    class NotchFilters(enum.Enum):
        Off = 0
        NotchFilter50or60Hz = 1
        NotchFilter100or120Hz = 2
        Both = 3

    class NotchFilterCenterFrequencies(enum.Enum):
        Freq_60_120_Hz = 0
        Freq_50_100_Hz = 1

    # Reference Channel

    class ReferenceMode(enum.Enum):
        SingleReference = 0
        DualHarmonic = 1
        DualReference = 2

    class ReferenceSource(enum.Enum):
        Internal = 0
        ExternalTTL = 1
        ExternalAnalog = 2

    class ReferenceChannelSelection(enum.Enum):
        CH1_Internal_CH2_External = 0
        CH2_Internal_CH1_External = 1

    class ReferenceMonitorControl(enum.Enum):
        TrigOutByCurveBuffer = 0
        TrigOutTTLAtReferenceFreq = 1

    # Signal Channel Output Filters

    class FilterTimeConstant(enum.Enum):
        TimeConstant_10mus = 0
        TimeConstant_20mus = 1
        TimeConstant_50mus = 2
        TimeConstant_100mus = 3
        TimeConstant_200mus = 4
        TimeConstant_500mus = 5
        TimeConstant_1ms = 6
        TimeConstant_2ms = 7
        TimeConstant_5ms = 8
        TimeConstant_10ms = 9
        TimeConstant_20ms = 10
        TimeConstant_50ms = 11
        TimeConstant_100ms = 12
        TimeConstant_200ms = 13
        TimeConstant_500ms = 14
        TimeConstant_1s = 15
        TimeConstant_2s = 16
        TimeConstant_5s = 17
        TimeConstant_10s = 18
        TimeConstant_20s = 19
        TimeConstant_50s = 20
        TimeConstant_100s = 21
        TimeConstant_200s = 22
        TimeConstant_500s = 23
        TimeConstant_1ks = 24
        TimeConstant_2ks = 25
        TimeConstant_5ks = 26
        TimeConstant_10ks = 27
        TimeConstant_20ks = 28
        TimeConstant_50ks = 29
        TimeConstant_100ks = 30

    class LowPassFilterSlope(enum.Enum):
        FilterSlope_6db_octave = 0
        FilterSlope_12db_octave = 1
        FilterSlope_18db_octave = 2
        FilterSlope_24db_octave = 3

    # Curve Buffer

    class CurveBufferMode(enum.Enum):
        Standard = 0
        Fast = 1

    class CurveBufferTriggerOutput(enum.Enum):
        PerCurve = 0
        PerPoint = 1

    class CurveBufferTriggerOutputPolarity(enum.Enum):
        RisingEdge = 0
        FallingEdge = 1

    class TakeDataMode(enum.Enum):
        TakeData = 0
        TakeDataTriggered = 1
        TakeDataContinuously = 2

    class TakeDataTriggeredTriggerMode(enum.Enum):
        Start_ExtRising_Sample_NA_Stop_LEN = 0
        Start_Cmd_Sample_ExtRising_Stop_LEN = 1
        Start_ExtFalling_Sample_NA_Stop_LEN = 2
        Start_Cmd_Sample_ExtFalling_Stop_LEN = 3
        Start_ExtRising_Sample_NA_Stop_Cmd = 4
        Start_Cmd_Sample_ExtRising_Stop_Cmd = 5
        Start_ExtFalling_Sample_NA_Stop_Cmd = 6
        Start_Cmd_Sample_ExtFalling_Stop_Cmd = 7
        Start_ExtRising_Sample_NA_Stop_ExtFalling = 8
        Start_ExtFalling_Sample_NA_Stop_ExtRising = 9

    class StatusBits(enum.Enum):
        CommandComplete = 0x1
        InvalidCommand = 0x2
        CommandParameterError = 0x4
        ReferenceUnlock = 0x8
        OutputOverload = 0x10
        NewADCValues = 0x20
        InputOverload = 0x40
        DataAvailable = 0x80

    class OverloadBits(enum.Enum):
        X = 0x1
        Y = 0x2
        X2 = 0x4
        Y2 = 0x8
        CH1 = 0x10
        CH2 = 0x20
        CH3 = 0x40
        CH4 = 0x80

    class CurveAcquisitionStatusInts(enum.Enum):
        NoCurveActivity = 0
        AcquisitionTD = 1
        AcquisitionTDC = 2
        AcquisitionHaltedTD = 5
        AcquisitionHaltedTDC = 6

    statusMessages = {
        'overload': {
            0x1: 'X channel output overload',
            0x2: 'Y channel output overload',
            0x4: 'X2 channel output overload',
            0x8: 'Y2 channel output overload',
            0x10: 'CH1 channel output overload',
            0x20: 'CH2 channel output overload',
            0x40: 'CH3 channel output overload',
            0x80: 'CH4 channel output overload'
        }
    }

    STATUS_UPDATE_RATE = 5

    # Instrument Info Traitlets

    identification = traitlets.Unicode(read_only=True,
                                       name="Identification",
                                       group="Instrument Info")
    instrumentName = traitlets.Unicode(name="Instrument Name",
                                       group="Instrument Info",
                                       command="NAME")
    firmwareVersion = traitlets.Unicode(read_only=True,
                                        name="Firmware Version",
                                        group="Instrument Info")

    # General Traitlets Traitlets

    samplingMode = traitlets.Enum(
        SamplingMode, SamplingMode.Buffered).tag(name="Sampling mode")

    # Signal Channel Traitlets

    inputMode = traitlets.Enum(InputMode,
                               default_value=InputMode.VoltageInputMode).tag(
                                   group="Signal Channel", command="IMODE")
    voltageInputMode = traitlets.Enum(VoltageInputMode).tag(
        group="Signal Channel", command="VMODE")
    inputConnectorShieldControl = traitlets.Enum(InputConnectorShieldControl,
                                                 default_value=InputConnectorShieldControl.Ground) \
        .tag(group="Signal Channel", command="FLOAT")
    inputDevice = traitlets.Enum(
        InputDevice, default_value=InputDevice.FET).tag(group="Signal Channel",
                                                        command="FET")
    inputCoupling = traitlets.Enum(InputCoupling,
                                   default_value=InputCoupling.AC).tag(
                                       group="Signal Channel",
                                       command="DCCOUPLE")
    sensitivity = traitlets.Enum(
        SensitivityIMode0,
        default_value=SensitivityIMode0.Sens_200mV).tag(group="Signal Channel",
                                                        command="SEN")
    acGain = traitlets.Enum(ACGain, default_value=ACGain.Gain_0dB).tag(
        group="Signal Channel", command="ACGAIN")
    acAutomaticGainControl = traitlets.Bool(default_value=False,
                                            group="Signal Channel",
                                            command="AUTOMATIC")
    notchFilter = traitlets.Enum(NotchFilter,
                                 default_value=NotchFilter.Off,
                                 group="Signal Channel",
                                 command="LF {} {}")

    # Reference Channel Traitlets

    referenceMode = traitlets.Enum(ReferenceMode,
                                   default_value=ReferenceMode.SingleReference,
                                   group="Reference Channel",
                                   command="REFMODE")
    referenceSource = traitlets.Enum(ReferenceSource,
                                     default_value=ReferenceSource.Internal,
                                     group="Reference Channel",
                                     command="IE")
    referenceChannelSelection = traitlets.Enum(ReferenceChannelSelection,
                                               group="Reference Channel",
                                               command="INT")
    referenceHarmonicMode = traitlets.Int(default_value=1,
                                          min=1,
                                          max=127,
                                          group="Reference Channel",
                                          command="REFN")
    referenceMonitorControl = traitlets.Enum(ReferenceMonitorControl,
                                             group="Reference Channel",
                                             command="REFMON")
    referencePhase = Quantity(default_value=Q_(0, "mdeg"),
                              min=Q_(-360000, "mdeg"),
                              max=Q_(360000, "mdeg"))
    referencePhase.tag(group="Reference Channel", command="REFP")
    referenceFrequencyMeter = Quantity(default_value=Q_(0, 'mHz'),
                                       read_only=True)
    referenceFrequencyMeter.tag(group="Reference Channel", command="FRQ")
    enterVirtualReferenceMode = traitlets.Bool(group="Reference Channel",
                                               command="VRLOCK")

    # Signal Channel Output Filters

    noiseMode = traitlets.Bool(default_value=False,
                               read_only=True,
                               group="Signal Channel Output Filters",
                               command="NOISEMODE")
    fastMode = traitlets.Bool(default_value=True,
                              read_only=False,
                              group="Signal Channel Output Filters",
                              command="FASTMODE")
    filterTimeConstant = traitlets.Enum(FilterTimeConstant,
                                        group="Signal Channel Output Filters",
                                        command="TC")
    synchronousTimeConstantControl = traitlets.Bool(
        default_value=True,
        group="Signal Channel Output Filters",
        command="SYNC")
    lowPassFilterSlope = traitlets.Enum(
        LowPassFilterSlope,
        default_value=LowPassFilterSlope.FilterSlope_12db_octave,
        group="Signal Channel Output Filters",
        command="SLOPE")

    # Data Curve Buffer Traitlets

    bufferMode = traitlets.Enum(CurveBufferMode,
                                default_value=CurveBufferMode.Standard,
                                read_only=True,
                                command="CMODE",
                                group="Data Curve Buffer")
    bufferTriggerOutput = traitlets.Enum(CurveBufferTriggerOutput,
                                         command="TRIGOUT",
                                         group="Data Curve Buffer")
    bufferTriggerOutputPolarity = traitlets.Enum(
        CurveBufferTriggerOutputPolarity,
        command="TRIGOUTPOL",
        group="Data Curve Buffer")
    storageTimeInterval = traitlets.Int(default_value=10).tag(
        name="Storage Time Interval", command="STR", group="Data Curve Buffer")
    bufferLength = traitlets.Int(default_value=100000).tag(
        name="Buffer Length", command="LEN", group="Data Curve Buffer")
    takeDataMode = traitlets.Enum(TakeDataMode,
                                  TakeDataMode.TakeDataTriggered).tag(
                                      name="Take Data Mode",
                                      group="Data Curve Buffer")
    takeDataTriggeredTriggerMode = traitlets.Enum(
        TakeDataTriggeredTriggerMode,
        default_value=TakeDataTriggeredTriggerMode.
        Start_Cmd_Sample_ExtRising_Stop_Cmd,
        group="Data Curve Buffer")
    curveAcquisitionInProgressTD = traitlets.Bool(
        default_value=False,
        read_only=True).tag(name="Acquisition in Progress by TD",
                            group='Data Curve Buffer')
    curveAcquisitionInProgressTDC = traitlets.Bool(
        default_value=False,
        read_only=True).tag(name="Continuous Acquisition in Progress",
                            group='Data Curve Buffer')
    curveAcquisitionHaltedTD = traitlets.Bool(
        default_value=False,
        read_only=True).tag(name="Acquisition by TD Halted",
                            group='Data Curve Buffer')
    curveAcquisitionHaltedTDC = traitlets.Bool(
        default_value=False,
        read_only=True).tag(name="Continuous Acquisition by TD Halted",
                            group='Data Curve Buffer')
    pointsAcquired = traitlets.Int(default_value=0, read_only=True).tag(
        name="Points Acquired", group='Data Curve Buffer')

    # Status Traitlets

    curveAcquisitionInProgress = traitlets.Bool(
        default_value=False,
        read_only=True).tag(name="Curve Acquisition in Progress",
                            group='Status')
    commandComplete = traitlets.Bool(default_value=False, read_only=True).tag(
        name="Command Complete", group="Status")
    invalidCommand = traitlets.Bool(default_value=False,
                                    read_only=True).tag(name="Invalid Command",
                                                        group="Status")
    commandParameterError = traitlets.Bool(default_value=False,
                                           read_only=True).tag(
                                               name="Command Parameter Error",
                                               group="Status")
    referenceUnlock = traitlets.Bool(default_value=False, read_only=True).tag(
        name="Reference Unlock", group="Status")
    outputOverload = traitlets.Bool(default_value=False,
                                    read_only=True).tag(name="Output Overload",
                                                        group="Status")
    newADCValues = traitlets.Bool(default_value=False,
                                  read_only=True).tag(name="New ADC Values",
                                                      group="Status")
    inputOverload = traitlets.Bool(default_value=False,
                                   read_only=True).tag(name="Input Overload",
                                                       group="Status")
    dataAvailable = traitlets.Bool(default_value=False,
                                   read_only=True).tag(name="Data Available",
                                                       group="Status")

    def __init__(self, resource, ethernet=False):
        """
        Parameters
        ----------
        resource : Resource
            PyVisa Resource object of the connected device.
        ethernet : bool
            Indicates if the connection to the device is an ethernet connection.
        """

        super().__init__(objectName=None, loop=None)
        self.resource = resource
        self.ethernet = ethernet
        self.resource.timeout = 1000
        #self.resource.set_visa_attribute(pyvisa_consts.VI_ATTR_SUPPRESS_END_EN, pyvisa_consts.VI_FALSE)

        if ethernet:
            self.resource.read_termination = chr(0)
        else:
            self.resource.read_termination = ''

        self.resource.write_termination = chr(0)

        self.observe(self.setParameter, traitlets.All)

        self._traitChangesDueToStatusUpdate = True
        self._lock = Lock()

        self._statusUpdateFuture = ensure_weakly_binding_future(
            self.contStatusUpdate)

    async def __aenter__(self):
        await super().__aenter__()
        self.set_trait("identification", (await self.query("ID"))[0])
        self.set_trait("instrumentName", (await self.query("NAME"))[0])
        self.set_trait("firmwareVersion", (await self.query("VER"))[0])
        await self.readAllParameters()
        await self.statusUpdate()
        return self

    async def __aexit__(self, *args):
        await super().__aexit__(*args)
        self._statusUpdateFuture.cancel()

    @threaded_async
    def query(self, command):
        """
        Sends a command to the device and reads the answer.

        Parameters
        ----------
        command : str
            The command to send to the device.

        Returns
        -------
        list
            a list of answer strings from the device.
        """

        with self._lock:
            # remove parameter placeholders from command
            paramIndex = command.find(" {}")
            if paramIndex != -1:
                command = command[:paramIndex]

            print('SR7230: query ' + str(command))
            logging.info('{}: {}'.format(self, command))

            answer = self.resource.query(command)

            if self.ethernet:
                self.resource.read_raw()
            else:
                end = answer.find(chr(0))
                answer = answer[:end]

            print('SR7230: answer: ' + answer)

            result = []
            for s in str.split(answer, ','):
                result.append(s)

            return result

    @threaded_async
    def write(self, command, lock=True):
        """
        Sends a command to the device.

        Parameters
        ----------
        command : str
            The command to send to the device.
        """

        logging.info('{}: {}'.format(self, command))
        if lock:
            with self._lock:
                ret = self.resource.query(command)
                if self.ethernet:
                    self.resource.read_raw()
                return ret
        else:
            ret = self.resource.query(command)
            if self.ethernet:
                self.resource.read_raw()
            return ret

    async def getCurveAcquisitionStatusMonitor(self):
        """
        Gets the current curve acquisition status.

        Returns
        -------
        list
            a list of the curve acquisition status monitor values.
        """

        answer = await self.query('M')
        # if answer[-1] == '\n':
        #     answer = answer[:-1]
        # result = []
        # for s in str.split(answer, ','):
        #     result.append(int(s))

        return answer

    async def getNumberOfPointsAcquired(self):
        """
        Gets the current number of acquired points from the device.

        Returns
        -------
        int
            the number of points acquired.
        """

        result = await self.getCurveAcquisitionStatusMonitor()
        return result[3]

    @action("Start")
    async def start(self):
        print('start sr7230')
        await self.write('NC')  # new curve
        await self.write('CBD 1')  # select channel x
        if self.takeDataMode == self.TakeDataMode.TakeData:
            await self.write('TD')
        elif self.takeDataMode == self.TakeDataMode.TakeDataContinuously:
            await self.write('TDC 0')
        elif self.takeDataMode == self.TakeDataMode.TakeDataTriggered:
            await self.write("TDT {}".format(
                self.takeDataTriggeredTriggerMode.value))

        await self.statusUpdate()

    @action("Stop")
    async def stop(self):
        print('stop sr7230')
        await self.write('HC')

    @action("Clear Buffer", group="Data Curve Buffer")
    async def clear(self):
        """
        Clears the buffer of the device.
        """

        await self.write("NC")

    async def readAllParameters(self):
        """
        Reads all parameters from the device and updates the attributes of this class accordingly.
        """

        self._traitChangesDueToStatusUpdate = True

        for name, trait in self.traits().items():
            command = trait.metadata.get('command')

            if command is None:
                continue
            else:
                answer = await self.query(command)

            if len(answer) == 1:
                result = answer[0]
            else:
                result = answer

            if isinstance(trait, traitlets.Enum):
                if len(answer) == 1:
                    val = int(result)
                    val = [item for item in trait.values
                           if item.value == val][0]
                else:
                    res = []
                    for i in answer:
                        ival = int(i)
                        res.append(ival)
                    # if first element is 0, (like [0, 1]) then LF is off
                    if res[0] != 0:
                        val = [
                            item for item in trait.values if item.value == res
                        ][0]
                    else:
                        val = list(trait.values)[0]
            elif isinstance(trait, Quantity):
                val = Q_(float(result), trait.default_value.units)
            elif isinstance(trait, traitlets.Int):
                val = int(result)
            elif isinstance(trait, traitlets.Bool):
                result_int = 0
                try:
                    result_int = int(result)
                except ValueError:
                    print('Failed to read answer from ' + command +
                          " answer was " + str(result))
                    logging.info('Failed to read answer from ' + command +
                                 " answer was " + str(result))

                val = True if result_int == 1 else False
            else:
                val = result

            self.set_trait(name, val)

        self._traitChangesDueToStatusUpdate = False
        logging.info('SR7230: Lockin-Parameter read')

    def setParameter(self, change):
        """
        Sets parameter on the device.

        This is the function that is called by all traits that get observed. Tries to update the changed attribute on
        the device by sending the corresponding command.

        Parameters
        ----------
        change : list
            change object of the observed trait.
        """

        if self._traitChangesDueToStatusUpdate:
            return

        trait = self.traits().get(change['name'])
        command = trait.metadata.get('command')
        value = change['new']

        if command is None:
            return

        self.set_trait(trait.name, value)

        if isinstance(value, enum.Enum):
            value = value.value
        elif isinstance(value, Q_):
            if 'REFP' in command:
                value = int(value.magnitude)
            else:
                value = value.magnitude
        elif isinstance(value, bool):
            value = 1 if value else 0

        commandString = str()
        paramIndex = command.find(" {}")
        if paramIndex == -1:
            commandString = command + ' {}'.format(value)
        elif command.find("{} {}") != -1:
            commandString = command.format(value[0], value[1])
        elif paramIndex != -1:
            commandString = command.format(value)

        asyncio.ensure_future(self.write(commandString))

    # Auto Functions
    @action('Readout Settings', group='Auto Functions')
    def readSettings(self):
        asyncio.ensure_future(self.readAllParameters())

    @action('Auto Sensitivity', group='Auto Functions')
    def autoSensitivity(self):
        asyncio.ensure_future(self.write('AS'))
        asyncio.ensure_future(self.readAllParameters())

    @action('Auto Measure Operation', group='Auto Functions')
    def autoMeasureOperation(self):
        asyncio.ensure_future(self.write('ASM'))
        asyncio.ensure_future(self.readAllParameters())

    @action('Auto Phase', group='Auto Functions')
    def autoPhase(self):
        asyncio.ensure_future(self.write('AQN'))
        asyncio.ensure_future(self.readAllParameters())

    @action('Auto Offset', group='Auto Functions')
    def autoOffset(self):
        asyncio.ensure_future(self.write('AXO'))
        asyncio.ensure_future(self.readAllParameters())

    @action('Update Gain and Phase Correction Parameters',
            group='Reference Channel')
    def systemLockControl(self):
        asyncio.ensure_future(self.write('LOCK'))
        asyncio.ensure_future(self.readAllParameters())

    async def contStatusUpdate(self):
        """
        Requests a status update every STATUS_UPDATE_RATE seconds.
        """

        while True:
            await asyncio.sleep(self.STATUS_UPDATE_RATE)
            await self.statusUpdate()

    async def statusUpdate(self):
        """
        Performs a status update and updates the class attributes according to answers from the device.
        """

        curveAcquisitionStatusMonitor = await self.getCurveAcquisitionStatusMonitor(
        )
        try:
            curveAcquisitionStatus = int(curveAcquisitionStatusMonitor[0])
        except Exception as e:
            logging.info(e)
            await self.statusUpdate()
        status = int(curveAcquisitionStatusMonitor[2])

        self.set_trait(
            "curveAcquisitionInProgressTD", curveAcquisitionStatus ==
            SR7230.CurveAcquisitionStatusInts.AcquisitionTD.value)
        self.set_trait(
            "curveAcquisitionInProgressTDC", curveAcquisitionStatus ==
            SR7230.CurveAcquisitionStatusInts.AcquisitionTDC.value)
        self.set_trait(
            "curveAcquisitionHaltedTD", curveAcquisitionStatus ==
            SR7230.CurveAcquisitionStatusInts.AcquisitionHaltedTD.value)
        self.set_trait(
            "curveAcquisitionHaltedTDC", curveAcquisitionStatus ==
            SR7230.CurveAcquisitionStatusInts.AcquisitionHaltedTDC.value)
        self.set_trait("pointsAcquired", int(curveAcquisitionStatusMonitor[3]))

        self.set_trait(
            "curveAcquisitionInProgress", curveAcquisitionStatus !=
            SR7230.CurveAcquisitionStatusInts.NoCurveActivity.value)
        self.set_trait("commandComplete",
                       bool(status & SR7230.StatusBits.CommandComplete.value))
        self.set_trait("invalidCommand",
                       bool(status & SR7230.StatusBits.InvalidCommand.value))
        self.set_trait(
            "commandParameterError",
            bool(status & SR7230.StatusBits.CommandParameterError.value))
        self.set_trait("referenceUnlock",
                       bool(status & SR7230.StatusBits.ReferenceUnlock.value))
        self.set_trait("outputOverload",
                       bool(status & SR7230.StatusBits.OutputOverload.value))
        self.set_trait("newADCValues",
                       bool(status & SR7230.StatusBits.NewADCValues.value))
        self.set_trait("inputOverload",
                       bool(status & SR7230.StatusBits.InputOverload.value))
        self.set_trait("dataAvailable",
                       bool(status & SR7230.StatusBits.DataAvailable.value))

        if self.outputOverload:
            overloadByte = await self.query("N")
            logging.info(SR7230.statusMessages['overload'][overloadByte])

    async def readCurrentOutput(self, channel='X'):
        """
        Reads the current output of a channel from the device.

        Parameters
        ----------
        channel : str
            the channel to read from.

        Returns
        -------
        float
            the current output.
        """

        return float(await self.query(channel))

    async def readDataBuffer(self):
        """
        Reads the data buffer of the device

        Returns
        -------
        list
            a list of the read data points from the device's data buffer.
        """

        numberOfPoints = await self.getNumberOfPointsAcquired()
        print('number of points: ' + str(numberOfPoints))
        if numberOfPoints == 0:
            return []
        data = await self.query('DC 0')
        data = data[0]

        result = []
        for s in str.split(data, '\n'):
            try:
                dataPoint = float(s)
                result.append(dataPoint)
            except ValueError:
                pass

        return result

    async def readDataSet(self):
        if self.samplingMode == SR7230.SamplingMode.SingleShot:
            data = np.array(await self.readCurrentOutput())
            dataSet = DataSet(Q_(data), [])
            self._dataSetReady(dataSet)
            return dataSet
        elif self.samplingMode == SR7230.SamplingMode.Buffered:
            data = await self.readDataBuffer()
            data = np.array(data)
            dataSet = DataSet(Q_(data), [Q_(np.arange(0, len(data)))])
            self._dataSetReady(dataSet)
            return dataSet
Beispiel #28
0
    def __init__(self, objectName=None, loop=None):
        super().__init__(objectName="Y Scan", loop=loop)
        self.title = "Taipan - Schweißgüte 2"

        self.dataSaver = DataSaver(objectName="Data Saver")

        self.tem_fs = TEMFiberStretcher(tem_serial1,
                                        tem_serial2,
                                        objectName="TEM FiberStretcher",
                                        loop=loop)

        self.tem_fs.rec_Start = Q_(4, 'ps')
        self.tem_fs.rec_Stop = Q_(190, 'ps')
        self.tem_fs_av = AverageDataSource(self.tem_fs, objectName="Averager")
        """
        self.manipulatorX = IselStage(monsterstage_x,
                                objectName="Manipulator x",
                                loop=loop)
        """
        self.manipulatorX = DummyManipulator()
        """
        self.manipulatorY = IselStage(monsterstage_y,
                                objectName="Manipulator y",
                                loop=loop)
        """
        self.manipulatorY = DummyManipulator()
        #define the x scan
        self.scanx = Scan(self.manipulatorX, self.tem_fs_av)
        self.scanx.minimumValue = Q_(0, 'mm')
        self.scanx.maximumValue = Q_(10, 'mm')
        self.scanx.step = Q_(1, 'mm')
        self.scanx.scanVelocity = Q_(10, 'mm/s')
        self.scanx.positioningVelocity = Q_(100, 'mm/s')
        self.scanx.objectName = "X Scan"
        self.scanx.retractAtEnd = True
        #define the y scan
        self.dataSource = self.scanx
        self._oldScanXStart = self.dataSource.start
        self._oldScanXStop = self.dataSource.stop
        self.dataSource.start = self.startMotorScan
        self.dataSource.stop = self.stopMotorScan
        self.manipulator = self.manipulatorY
        self.retractAtEnd = True
        self.minimumValue = Q_(0, 'mm')
        self.maximumValue = Q_(10, 'mm')
        self.step = Q_(2.5, 'mm')
        self.positioningVelocity = Q_(100, 'mm/s')
        self.scanVelocity = Q_(10, 'mm/s')
        #register the manipulators in the dataSaver
        self.dataSaver.registerManipulator(self.manipulatorX, 'X')
        self.dataSaver.registerManipulator(self.manipulatorY, 'Y')
        self.dataSaver.fileNameTemplate = '{date}-{name}-{X}-{Y}'
        self.tem_fs_av.addDataSetReadyCallback(self.dataSaver.process)
        self.resetCounter(self.resetCounterRow)
Beispiel #29
0
class Goniometer(Manipulator):

    class EncoderMode(enum.Enum):
        A_BSignal1fold = 0xC0
        A_BSignal2fold = 0xE0
        A_BSignal4fold = 0xF0

    class Ramping(enum.Enum):
        Ramping = 0
        NoRamping = 1

    Errors = {
        170: 'Maximum relative positioning Distance Exceeded',
        175: 'Minimum relative positioning Distance Exceeded',
        1200: 'Acceleration too steep',
        1201: 'deceleration too steep',
        1250: 'acceleration too flat',
        1251: 'deceleration too flat',
        1300: 'speed value too high',
        1350: 'speed value too low',
        9000: 'Axis not ready'
    }

    connection = None
    positiveLimitSwitch = traitlets.Bool(False,
                                         read_only=True).tag(group='Status')
    negativeLimitSwitch = traitlets.Bool(False,
                                         read_only=True).tag(group='Status')
    calibrateToDegree = Quantity(Q_(0, 'deg'), read_only=False)
    calibrateToDegree.tag(group='Status')

    isMoving = traitlets.Bool(False, read_only=True).tag(group='Status')
    startSpeed = Quantity(Q_(0.25, 'deg/s')).tag(group='Velocity Settings')
    acceleration = Quantity(Q_(0.0125, 'deg/s**2'))
    acceleration.tag(group='Velocity Settings')
    deceleration = Quantity(Q_(0.0125, 'deg/s**2'))
    deceleration.tag(group='Velocity Settings')

    def __init__(self, axis=0, encoderMode=EncoderMode.A_BSignal4fold,
                 objectName=None, loop=None):
        super().__init__(objectName, loop)
        self.setPreferredUnits(ureg.deg, ureg.deg / ureg.s)
        if Goniometer.connection is None:
            Goniometer.connection = GonioConn()
        self.cdll = Goniometer.connection.dll

        self.axis = axis
        self.cdll.InitEncoder(self.axis, encoderMode.value)
        self.cdll.SetEncoder(self.axis, 0)
        self.cdll.SetRunFreeFrq(self.axis, 100)
        self.cdll.SetRunFreeSteps(self.axis, 32000)

        # don't know if important
        self.cdll.SetPosition(self.axis, 0)
        self.set_trait('value', self._stepToDeg(
                                             self.cdll.GetPosition(self.axis)))
        self.velocity = Q_(5, 'deg/s')

        self._statusRefresh = 0.1
        self._isMovingFuture = asyncio.Future()
        self._isMovingFuture.set_result(None)
        self._updateFuture = ensure_weakly_binding_future(self.updateStatus)

    async def updateStatus(self):
        while True:
            await asyncio.sleep(self._statusRefresh)
            if (Goniometer.connection is None):
                continue
            await self.singleUpdate()

    async def singleUpdate(self):
        steps = self.cdll.GetPosition(self.axis)
        self.set_trait('value', self._stepToDeg(steps))
        ls = self.cdll.GetLSStatus(self.axis)
        self.set_trait('positiveLimitSwitch', bool(ls & 1))
        self.set_trait('negativeLimitSwitch', bool(ls & 2))

        self.set_trait('isMoving',
                       not bool(self.cdll.GetReadyStatus(self.axis)))
        if self.isMoving:
            self.set_trait('status', self.Status.Moving)
        else:
            self.set_trait('status', self.Status.Idle)
            if not self._isMovingFuture.done():
                self._isMovingFuture.set_result(None)

    async def __aexit__(self, *args):
        self.stop()
        self._updateFuture.cancel()
        await super().__aexit__(*args)

    @action("Stop")
    def stop(self, stopMode=Ramping.Ramping):
        self.cdll.StopMotion(self.axis, stopMode.value)
        self._isMovingFuture.cancel()

    #@action("Reference")
    async def reference(self):
        if self.isMoving:
            logging.info('{} {}: Please finish'.format(self, self.axis) +
                         'movement before searching Limit Switch')
            return False

        self._setSpeedProfile(Q_(5, 'deg/s'))
        self.cdll.SetRunFreeFrq(self.axis, 100)
        self.cdll.SetRunFreeSteps(self.axis, 32000)

        self.cdll.SearchLS(self.axis, ord('-'))

        self._isMovingFuture = asyncio.Future()
        await self._isMovingFuture

        self.cdll.FindLS(self.axis, ord('-'))
        self.cdll.RunLSFree(self.axis, ord('-'))

        self._isMovingFuture = asyncio.Future()
        await self._isMovingFuture

        self.cdll.SetPosition(self.axis, 0)

    def _setSpeedProfile(self, velocity):
        ss = int(self.startSpeed.to('deg/s').magnitude*400)
        fs = int(velocity.to('deg/s').magnitude*400)
        ac = int(self.acceleration.to('deg/s**2').magnitude*400)
        dc = int(self.deceleration.to('deg/s**2').magnitude*400)
        error = self.cdll.SetSpeedProfile(self.axis, ss, fs, ac, dc)
        if error != 0:
            error = self.cdll.SetSpeedProfile(self.axis, 100, 2000, 5, 5)
            logging.error('{} {}: '.format(self, self.axis) +
                          Goniometer.Errors.get(error))
            logging.error('{} {}: Setting Speed command ignored'
                          .format(self, self.axis))
            return False
        else:
            return True

    async def moveTo(self, val: float, velocity=None):
        if velocity is None:
            velocity = self.velocity

        # The Goniometer ignores new position commands, if the stage is moving
        if self.isMoving:
            self.stop()
            while self.status != self.Status.Idle:
                await asyncio.sleep(0)

        error = self.cdll.SetDestination(self.axis, self._degToStep(val),
                                         ord('a'))

        if error != 0:
            logging.error('{} {}: '.format(self, self.axis) +
                          Goniometer.Errors.get(error))
            logging.error('{} {}: Positioning Command ignored'
                          .format(self, self.axis))
            return False

        self._setSpeedProfile(velocity)

        error = self.cdll.StartMotion(self.axis,
                                      Goniometer.Ramping.Ramping.value)
        if error != 0:
            logging.error('{} {}: '.format(self, self.axis) +
                          Goniometer.Errors.get(error))
            logging.error('{} {}: Positioning Command ignored'
                          .format(self, self.axis))
            return False

        self._isMovingFuture = asyncio.Future()
        await self._isMovingFuture

    @action('Set Calibration')
    def calibrate(self, value=None):
        if value is None:
            value = self.calibrateToDegree
        self.cdll.SetPosition(self.axis, self._degToStep(value))

    def _degToStep(self, degs):
        return int(degs.to('deg').magnitude*400)

    def _stepToDeg(self, steps):
        return Q_(steps/400.0, 'deg')
Beispiel #30
0
 def _stepToDeg(self, steps):
     return Q_(steps/400.0, 'deg')