Ejemplo n.º 1
0
        def move(self, pos, absolute=True):
            # Handle units as follows:
            # 1. Treat raw numbers as encoder counts.
            # 2. If units are provided (as a Quantity), check if they're encoder
            #    counts. If they aren't, apply scale factor.
            if not isinstance(pos, pq.Quantity):
                pos_ec = int(pos)
            else:
                if pos.units == pq.counts:
                    pos_ec = int(pos.magnitude)
                else:
                    scaled_pos = (pos * self.scale_factors[0])
                    # Force a unit error.
                    try:
                        pos_ec = int(scaled_pos.rescale(pq.counts).magnitude)
                    except:
                        raise ValueError(
                            "Provided units are not compatible with current motor scale factor."
                        )

            # Now that we have our position as an integer number of encoder
            # counts, we're good to move.
            pkt = _packets.ThorLabsPacket(
                message_id=_cmds.ThorLabsCommands.MOT_MOVE_ABSOLUTE
                if absolute else _cmds.ThorLabsCommands.MOT_MOVE_RELATIVE,
                param1=None,
                param2=None,
                dest=self._apt._dest,
                source=0x01,
                data=struct.pack('<Hl', self._idx_chan, pos_ec))

            response = self._apt.querypacket(
                pkt, expect=_cmds.ThorLabsCommands.MOT_MOVE_COMPLETED)
Ejemplo n.º 2
0
    def __init__(self, filelike):
        super(ThorLabsAPT, self).__init__(filelike)
        self._dest = 0x50  # Generic USB device; make this configurable later.

        # Provide defaults in case an exception occurs below.
        self._serial_number = None
        self._model_number = None
        self._hw_type = None
        self._fw_version = None
        self._notes = ""
        self._hw_version = None
        self._mod_state = None
        self._n_channels = 0
        self._channel = ()

        # Perform a HW_REQ_INFO to figure out the model number, serial number,
        # etc.
        try:
            req_packet = _packets.ThorLabsPacket(
                message_id=_cmds.ThorLabsCommands.HW_REQ_INFO,
                param1=0x00,
                param2=0x00,
                dest=self._dest,
                source=0x01,
                data=None)
            hw_info = self.querypacket(
                req_packet, expect=_cmds.ThorLabsCommands.HW_GET_INFO)

            self._serial_number = str(hw_info._data[0:4]).encode('hex')
            self._model_number = str(hw_info._data[4:12]).replace('\x00',
                                                                  '').strip()

            hw_type_int = struct.unpack('<H', str(hw_info._data[12:14]))[0]
            if hw_type_int == 45:
                self._hw_type = 'Multi-channel controller motherboard'
            elif hw_type_int == 44:
                self._hw_type = 'Brushless DC controller'
            else:
                self._hw_type = 'Unknown type: {}'.format(hw_type_int)

            # Note that the fourth byte is padding, so we strip out the first
            # three bytes and format them.
            self._fw_version = "{0[0]}.{0[1]}.{0[2]}".format(
                str(hw_info._data[14:18]).encode('hex'))
            self._notes = str(hw_info._data[18:66]).replace('\x00', '').strip()

            self._hw_version = struct.unpack('<H',
                                             str(hw_info._data[78:80]))[0]
            self._mod_state = struct.unpack('<H', str(hw_info._data[80:82]))[0]
            self._n_channels = struct.unpack('<H',
                                             str(hw_info._data[82:84]))[0]
        except Exception as e:
            logger.error(
                "Exception occured while fetching hardware info: {}".format(e))

        # Create a tuple of channels of length _n_channel_type
        if self._n_channels > 0:
            self._channel = list(
                self._channel_type(self, chan_idx)
                for chan_idx in xrange(self._n_channels))
Ejemplo n.º 3
0
 def enabled(self, newval):
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.MOD_SET_CHANENABLESTATE,
         param1=self._idx_chan,
         param2=0x01 if newval else 0x02,
         dest=self._apt._dest,
         source=0x01,
         data=None)
     self._apt.sendpacket(pkt)
Ejemplo n.º 4
0
 def output_position(self, pos):
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.PZ_SET_OUTPUTPOS,
         param1=None,
         param2=None,
         dest=self._apt._dest,
         source=0x01,
         data=struct.pack('<HH', self._idx_chan, pos))
     self._apt.sendpacket(pkt)
Ejemplo n.º 5
0
 def go_home(self):
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.MOT_MOVE_HOME,
         param1=self._idx_chan,
         param2=0x00,
         dest=self._apt._dest,
         source=0x01,
         data=None)
     self._apt.sendpacket(pkt)
Ejemplo n.º 6
0
 def change_position_control_mode(self, closed, smooth=True):
     mode = 1 + (int(closed) | int(smooth) << 1)
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.PZ_SET_POSCONTROLMODE,
         param1=self._idx_chan,
         param2=mode,
         dest=self._apt._dest,
         source=0x01,
         data=None)
     self._apt.sendpacket(pkt)
Ejemplo n.º 7
0
 def enabled(self):
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.MOD_REQ_CHANENABLESTATE,
         param1=self._idx_chan,
         param2=0x00,
         dest=self._apt._dest,
         source=0x01,
         data=None)
     resp = self._apt.querypacket(
         pkt, expect=_cmds.ThorLabsCommands.MOD_GET_CHANENABLESTATE)
     return not bool(resp._param2 - 1)
Ejemplo n.º 8
0
 def is_position_control_closed(self):
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.PZ_REQ_POSCONTROLMODE,
         param1=self._idx_chan,
         param2=0x00,
         dest=self._apt._dest,
         source=0x01,
         data=None)
     resp = self._apt.querypacket(
         pkt, expect=_cmds.ThorLabsCommands.PZ_GET_POSCONTROLMODE)
     return bool((resp._param2 - 1) & 1)
Ejemplo n.º 9
0
 def position_encoder(self):
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.MOT_REQ_ENCCOUNTER,
         param1=self._idx_chan,
         param2=0x00,
         dest=self._apt._dest,
         source=0x01,
         data=None)
     response = self._apt.querypacket(
         pkt, expect=_cmds.ThorLabsCommands.MOT_GET_ENCCOUNTER)
     chan, pos = struct.unpack('<Hl', response._data)
     return pq.Quantity(pos, 'counts')
Ejemplo n.º 10
0
 def output_position(self):
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.PZ_REQ_OUTPUTPOS,
         param1=self._idx_chan,
         param2=0x00,
         dest=self._apt._dest,
         source=0x01,
         data=None)
     resp = self._apt.querypacket(
         pkt, expect=_cmds.ThorLabsCommands.PZ_GET_OUTPUTPOS)
     chan, pos = struct.unpack('<HH', resp._data)
     return pos
Ejemplo n.º 11
0
 def identify(self):
     '''
     Causes a light on the APT instrument to blink, so that it can be
     identified.
     '''
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.MOD_IDENTIFY,
         param1=0x00,
         param2=0x00,
         dest=self._dest,
         source=0x01,
         data=None)
     self.sendpacket(pkt)
Ejemplo n.º 12
0
 def led_intensity(self, intensity):
     '''
     The output intensity of the LED display.
     
     :param float intensity: Ranges from 0 to 1.
     '''
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.PZ_SET_TPZ_DISPSETTINGS,
         param1=None,
         param2=None,
         dest=self._dest,
         source=0x01,
         data=struct.pack('<H', int(round(255 * intensity))))
     self.sendpacket(pkt)
Ejemplo n.º 13
0
 def led_intensity(self):
     '''
     The output intensity of the LED display.
     
     :type: `float` between 0 and 1.
     '''
     pkt = _packets.ThorLabsPacket(
         message_id=_cmds.ThorLabsCommands.PZ_REQ_TPZ_DISPSETTINGS,
         param1=0x01,
         param2=0x00,
         dest=self._dest,
         source=0x01,
         data=None)
     resp = self.querypacket(pkt)
     return float(struct.unpack('<H', resp._data)[0]) / 255
Ejemplo n.º 14
0
        def max_travel(self):
            pkt = _packets.ThorLabsPacket(
                message_id=_cmds.ThorLabsCommands.PZ_REQ_MAXTRAVEL,
                param1=self._idx_chan,
                param2=0x00,
                dest=self._apt._dest,
                source=0x01,
                data=None)
            resp = self._apt.querypacket(pkt)

            # Not all APT piezo devices support querying the maximum travel
            # distance. Those that do not simply ignore the PZ_REQ_MAXTRAVEL
            # packet, so that the response is empty.
            if resp is None:
                return NotImplemented

            chan, int_maxtrav = struct.unpack('<HH', resp._data)
            return int_maxtrav * pq.Quantity(100, 'nm')
Ejemplo n.º 15
0
        def status_bits(self):
            # NOTE: the difference between MOT_REQ_STATUSUPDATE and MOT_REQ_DCSTATUSUPDATE confuses me
            pkt = _packets.ThorLabsPacket(
                message_id=_cmds.ThorLabsCommands.MOT_REQ_STATUSUPDATE,
                param1=self._idx_chan,
                param2=0x00,
                dest=self._apt._dest,
                source=0x01,
                data=None)
            # The documentation claims there are 14 data bytes, but it seems there are sometimes
            # some extra random ones...
            resp_data = self._apt.querypacket(pkt)._data[:14]
            ch_ident, position, enc_count, status_bits = struct.unpack(
                '<HLLL', resp_data)

            status_dict = dict(
                (key, (status_bits & bit_mask > 0))
                for key, bit_mask in self.__STATUS_BIT_MASK.iteritems())

            return status_dict