diff --git a/artiq/devices/thorlabs_tcube/driver.py b/artiq/devices/thorlabs_tcube/driver.py index 545887e18..10bb6ea9c 100644 --- a/artiq/devices/thorlabs_tcube/driver.py +++ b/artiq/devices/thorlabs_tcube/driver.py @@ -207,7 +207,8 @@ class _Tcube: # derived classes must implement this raise NotImplementedError - async def send_request(self, msgreq_id, wait_for_msgs, param1=0, param2=0, data=None): + async def send_request(self, msgreq_id, wait_for_msgs, param1=0, param2=0, + data=None): await self.send(Message(msgreq_id, param1, param2, data=data)) msg = None while msg is None or msg.id not in wait_for_msgs: @@ -218,7 +219,7 @@ class _Tcube: async def set_channel_enable_state(self, activated): """Enable or Disable channel 1. - :param activated: 1 to enable channel, 2 to disable it. + :param activated: 1 to enable channel, 0 to disable it. """ if activated: @@ -283,9 +284,13 @@ class _Tcube: class Tpz(_Tcube): + """Either :py:meth:`set_tpz_io_settings()` + or :py:meth:`get_tpz_io_settings()` must + be completed to finish initialising the driver. + """ def __init__(self, serial_dev): _Tcube.__init__(self, serial_dev) - self.voltage_limit = self.get_tpz_io_settings()[0] + self.voltage_limit = None async def handle_message(self, msg): msg_id = msg.id @@ -336,7 +341,7 @@ class Tpz(_Tcube): :rtype: int """ get_msg = await self.send_request(MGMSG.PZ_REQ_POSCONTROLMODE, - [MGMSG.PZ_GET_POSCONTROLMODE], 1) + [MGMSG.PZ_GET_POSCONTROLMODE], 1) return get_msg.param2 async def set_output_volts(self, voltage): @@ -348,9 +353,8 @@ class Tpz(_Tcube): :param voltage: The output voltage applied to the piezo when operating in open loop mode. The voltage value must be in range [0; voltage_limit]. Voltage_limit being set by the - :py:meth:`set_tpz_io_settings() - ` method - between the three values 75 V, 100 V and 150 V. + :py:meth:`set_tpz_io_settings()` + method between the three values 75 V, 100 V and 150 V. """ if voltage < 0 or voltage > self.voltage_limit: raise ValueError("Voltage must be in range [0;{}]" @@ -366,7 +370,7 @@ class Tpz(_Tcube): :rtype: float """ get_msg = await self.send_request(MGMSG.PZ_REQ_OUTPUTVOLTS, - [MGMSG.PZ_GET_OUTPUTVOLTS], 1) + [MGMSG.PZ_GET_OUTPUTVOLTS], 1) return st.unpack("` method. + ` method. 0x01 External Signal: Unit sums the differential signal on the rear panel EXT IN(+) and EXT IN(-) connectors with the voltage set @@ -426,13 +430,12 @@ class Tpz(_Tcube): amplifier circuit. :return: Value which selects the various analog sources, cf. - :py:meth:`set_input_volts_source() - ` method - docstring for meaning of bits. + :py:meth:`set_input_volts_source()` + method docstring for meaning of bits. :rtype: int """ get_msg = await self.send_request(MGMSG.PZ_REQ_INPUTVOLTSSRC, - [MGMSG.PZ_GET_INPUTVOLTSSRC], 1) + [MGMSG.PZ_GET_INPUTVOLTSSRC], 1) return st.unpack("` + ` function), then only the first cyclelength values need to be set. In this manner, any arbitrary voltage waveform can be programmed into the LUT. Note. The LUT values are output by the system at a maximum @@ -499,8 +502,8 @@ class Tpz(_Tcube): to 512 for TPZ). :param output: The voltage value to be set. Values are in the range [0; voltage_limit]. Voltage_limit being set with the - :py:meth:`set_tpz_io_settings - ` method. + :py:meth:`set_tpz_io_settings` + method. """ volt = round(output*32767/self.voltage_limit) payload = st.pack("` for the - meaning of those parameters. + ` for + the meaning of those parameters. :rtype: a 2 elements tuple (int, int) """ get_msg = await self.send_request(MGMSG.PZ_REQ_TPZ_IOSETTINGS, @@ -760,8 +764,7 @@ class Tdc(_Tcube): :return: An 8 int tuple containing the following values: zero_wnd, vel1, wnd1, vel2, wnd2, vel3, wnd3, vel4. See - :py:meth:`set_pot_parameters() - ` for a + :py:meth:`set_pot_parameters()` for a description of each tuple element meaning. :rtype: An 8 int tuple """ @@ -839,7 +842,7 @@ class Tdc(_Tcube): return st.unpack("` + ` method. :rtype: A 2 int tuple. """ @@ -1001,11 +1005,13 @@ class Tdc(_Tcube): The relative distance parameter used for the move will be the parameter sent previously by a :py:meth:`set_move_relative_parameters() - ` + ` command. """ await self.send_request(MGMSG.MOT_MOVE_RELATIVE, - [MGMSG.MOT_MOVE_COMPLETED, MGMSG.MOT_MOVE_STOPPED], 1) + [MGMSG.MOT_MOVE_COMPLETED, + MGMSG.MOT_MOVE_STOPPED], + 1) async def move_relative(self, relative_distance): """Start a relative move @@ -1015,7 +1021,8 @@ class Tdc(_Tcube): """ payload = st.pack("` + ` command. """ await self.send_request(MGMSG.MOT_MOVE_ABSOLUTE, - [MGMSG.MOT_MOVE_COMPLETED, MGMSG.MOT_MOVE_STOPPED], + [MGMSG.MOT_MOVE_COMPLETED, + MGMSG.MOT_MOVE_STOPPED], param1=1) async def move_absolute(self, absolute_distance): @@ -1039,7 +1047,8 @@ class Tdc(_Tcube): """ payload = st.pack("` - command until a :py:meth:`move_stop() - ` command (either + ` + command until a :py:meth:`move_stop()` command (either StopImmediate or StopProfiled) is called, or a limit switch is reached. :param direction: The direction to jog: 1 to move forward, 2 to move backward. """ - await self.send(Message(MGMSG.MOT_MOVE_VELOCITY, param1=1, param2=direction)) + await self.send(Message(MGMSG.MOT_MOVE_VELOCITY, param1=1, + param2=direction)) async def move_stop(self, stop_mode): """Stop any type of motor move. @@ -1080,11 +1090,11 @@ class Tdc(_Tcube): if await self.is_moving(): await self.send_request(MGMSG.MOT_MOVE_STOP, [MGMSG.MOT_MOVE_STOPPED, - MGMSG.MOT_MOVE_COMPLETED], + MGMSG.MOT_MOVE_COMPLETED], 1, stop_mode) async def set_dc_pid_parameters(self, proportional, integral, differential, - integral_limit, filter_control=0x0F): + integral_limit, filter_control=0x0F): """Set the position control loop parameters. :param proportional: The proportional gain, values in range [0; 32767]. @@ -1108,8 +1118,8 @@ class Tdc(_Tcube): :return: A 5 int tuple containing in this order: proportional gain, integral gain, differential gain, integral limit and filter control. Cf. :py:meth:`set_dc_pid_parameters() - ` for - precise description. + ` + for precise description. :rtype: A 5 int tuple. """ get_msg = await self.send_request(MGMSG.MOT_REQ_DCPIDPARAMS, @@ -1151,10 +1161,10 @@ class Tdc(_Tcube): :param mode: If set to 1, the buttons are used to jog the motor. Once set to this mode, the move parameters for the buttons are taken from the arguments of the :py:meth:`set_jog_parameters() - ` method. - If set to 2, each button can be programmed with a differente - position value such that the controller will move the motor to that - position when the specific button is pressed. + ` + method. If set to 2, each button can be programmed with a + differente position value such that the controller will move the + motor to that position when the specific button is pressed. :param position1: The position (in encoder counts) to which the motor will move when the top button is pressed. :param position2: The position (in encoder counts) to which the motor @@ -1169,8 +1179,8 @@ class Tdc(_Tcube): :return: A 3 int tuple containing in this order: button mode, position1 and position2. Cf. :py:meth:`set_button_parameters() - ` for - description. + ` + for description. :rtype: A 3 int tuple """ get_msg = await self.send_request(MGMSG.MOT_REQ_BUTTONPARAMS, diff --git a/artiq/frontend/aqctl_thorlabs_tcube.py b/artiq/frontend/aqctl_thorlabs_tcube.py index bb9e5b716..e8e489c3e 100755 --- a/artiq/frontend/aqctl_thorlabs_tcube.py +++ b/artiq/frontend/aqctl_thorlabs_tcube.py @@ -53,6 +53,8 @@ def main(): dev = Tdc(args.device) elif product == "tpz001": dev = Tpz(args.device) + loop = asyncio.get_event_loop() + loop.run_until_complete(dev.get_tpz_io_settings()) else: print("Invalid product string (-P/--product), " "choose from tdc001 or tpz001")