forked from M-Labs/artiq
move thorlabs_tcube out of tree (#887)
This commit is contained in:
parent
5613565293
commit
56033b60a7
File diff suppressed because it is too large
Load Diff
@ -1,70 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import asyncio
|
|
||||||
|
|
||||||
from artiq.devices.thorlabs_tcube.driver import Tdc, Tpz, TdcSim, TpzSim
|
|
||||||
from artiq.protocols.pc_rpc import simple_server_loop
|
|
||||||
from artiq.tools import *
|
|
||||||
|
|
||||||
|
|
||||||
def get_argparser():
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument("-P", "--product", required=True,
|
|
||||||
help="type of the Thorlabs T-Cube device to control: "
|
|
||||||
"tdc001/tpz001")
|
|
||||||
parser.add_argument("-d", "--device", default=None,
|
|
||||||
help="serial device. See documentation for how to "
|
|
||||||
"specify a USB Serial Number.")
|
|
||||||
parser.add_argument("--simulation", action="store_true",
|
|
||||||
help="Put the driver in simulation mode, even if "
|
|
||||||
"--device is used.")
|
|
||||||
simple_network_args(parser, 3255)
|
|
||||||
add_common_args(parser)
|
|
||||||
return parser
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
args = get_argparser().parse_args()
|
|
||||||
init_logger(args)
|
|
||||||
|
|
||||||
if os.name == "nt":
|
|
||||||
asyncio.set_event_loop(asyncio.ProactorEventLoop())
|
|
||||||
|
|
||||||
if not args.simulation and args.device is None:
|
|
||||||
print("You need to specify either --simulation or -d/--device "
|
|
||||||
"argument. Use --help for more information.")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
product = args.product.lower()
|
|
||||||
if args.simulation:
|
|
||||||
if product == "tdc001":
|
|
||||||
dev = TdcSim()
|
|
||||||
elif product == "tpz001":
|
|
||||||
dev = TpzSim()
|
|
||||||
else:
|
|
||||||
print("Invalid product string (-P/--product), "
|
|
||||||
"choose from tdc001 or tpz001")
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
if product == "tdc001":
|
|
||||||
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")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
simple_server_loop({product: dev},
|
|
||||||
bind_address_from_args(args), args.port)
|
|
||||||
finally:
|
|
||||||
dev.close()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -10,7 +10,7 @@ class TestFrontends(unittest.TestCase):
|
|||||||
# Skip tests for GUI programs on headless CI environments.
|
# Skip tests for GUI programs on headless CI environments.
|
||||||
commands = {
|
commands = {
|
||||||
"aqctl": [
|
"aqctl": [
|
||||||
"corelog", "thorlabs_tcube"
|
"corelog"
|
||||||
],
|
],
|
||||||
"artiq": [
|
"artiq": [
|
||||||
"client", "compile", "coreanalyzer", "coremgmt", "ctlmgr",
|
"client", "compile", "coreanalyzer", "coremgmt", "ctlmgr",
|
||||||
|
@ -1,183 +0,0 @@
|
|||||||
import time
|
|
||||||
import sys
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from artiq.language.units import V
|
|
||||||
from artiq.test.hardware_testbench import ControllerCase, GenericControllerCase
|
|
||||||
|
|
||||||
|
|
||||||
class GenericTdcTest:
|
|
||||||
def test_pot_parameters(self):
|
|
||||||
test_vector = 1, 2, 3, 4, 5, 6, 7, 8
|
|
||||||
self.cont.set_pot_parameters(*test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_pot_parameters())
|
|
||||||
|
|
||||||
def test_position_counter(self):
|
|
||||||
test_vector = 42
|
|
||||||
self.cont.set_position_counter(test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_position_counter())
|
|
||||||
|
|
||||||
def test_encoder_counter(self):
|
|
||||||
test_vector = 43
|
|
||||||
self.cont.set_encoder_counter(test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_encoder_counter())
|
|
||||||
|
|
||||||
def test_velocity_parameters(self):
|
|
||||||
test_vector = 44, 45
|
|
||||||
self.cont.set_velocity_parameters(*test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_velocity_parameters())
|
|
||||||
|
|
||||||
def test_jog_parameters(self):
|
|
||||||
test_vector = 46, 47, 48, 49, 50
|
|
||||||
self.cont.set_jog_parameters(*test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_jog_parameters())
|
|
||||||
|
|
||||||
def test_gen_move_parameters(self):
|
|
||||||
test_vector = 51
|
|
||||||
self.cont.set_gen_move_parameters(test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_gen_move_parameters())
|
|
||||||
|
|
||||||
def test_moverelparams(self):
|
|
||||||
test_vector = 52
|
|
||||||
self.cont.set_move_relative_parameters(test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_move_relative_parameters())
|
|
||||||
|
|
||||||
def test_move_absolute_parameters(self):
|
|
||||||
test_vector = 53
|
|
||||||
self.cont.set_move_absolute_parameters(test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_move_absolute_parameters())
|
|
||||||
|
|
||||||
def test_home_parameters(self):
|
|
||||||
test_vector = 54
|
|
||||||
self.cont.set_home_parameters(test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_home_parameters())
|
|
||||||
|
|
||||||
def test_limit_switch_parameters(self):
|
|
||||||
test_vector = 2, 1
|
|
||||||
self.cont.set_limit_switch_parameters(*test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_limit_switch_parameters())
|
|
||||||
|
|
||||||
def test_dc_pid_parameters(self):
|
|
||||||
test_vector = 57, 58, 59, 60, 0x0f
|
|
||||||
self.cont.set_dc_pid_parameters(*test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_dc_pid_parameters())
|
|
||||||
|
|
||||||
def test_av_modes(self):
|
|
||||||
for i in range(1):
|
|
||||||
for j in range(1):
|
|
||||||
for k in range(1):
|
|
||||||
with self.subTest(i=i):
|
|
||||||
with self.subTest(j=j):
|
|
||||||
with self.subTest(k=k):
|
|
||||||
test_vector = i << 2 + j << 1 + k
|
|
||||||
self.cont.set_av_modes(test_vector)
|
|
||||||
self.assertEqual(test_vector,
|
|
||||||
self.cont.get_av_modes())
|
|
||||||
|
|
||||||
def test_button_parameters(self):
|
|
||||||
test_vector = 2, 3, 4
|
|
||||||
self.cont.set_button_parameters(*test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_button_parameters())
|
|
||||||
|
|
||||||
|
|
||||||
class GenericTpzTest:
|
|
||||||
def test_position_control_mode(self):
|
|
||||||
test_vector = 1
|
|
||||||
self.cont.set_position_control_mode(test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_position_control_mode())
|
|
||||||
|
|
||||||
def test_ouput_volts(self):
|
|
||||||
for voltage in 5*V, 10*V, 15*V, \
|
|
||||||
round(self.cont.get_tpz_io_settings()[0])*V:
|
|
||||||
with self.subTest(voltage=voltage):
|
|
||||||
test_vector = voltage
|
|
||||||
self.cont.set_output_volts(test_vector)
|
|
||||||
time.sleep(1) # Wait for the output voltage to converge
|
|
||||||
self.assertAlmostEqual(test_vector,
|
|
||||||
self.cont.get_output_volts(),
|
|
||||||
delta=0.03*V)
|
|
||||||
|
|
||||||
def test_output_position(self):
|
|
||||||
test_vector = 31000
|
|
||||||
self.cont.set_output_position(test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_output_position())
|
|
||||||
|
|
||||||
def test_input_volts_source(self):
|
|
||||||
for i in range(3):
|
|
||||||
test_vector = i
|
|
||||||
self.cont.set_input_volts_source(i)
|
|
||||||
with self.subTest(i=i):
|
|
||||||
self.assertEqual(test_vector,
|
|
||||||
self.cont.get_input_volts_source())
|
|
||||||
|
|
||||||
def test_pi_constants(self):
|
|
||||||
test_vector = 42, 43
|
|
||||||
self.cont.set_pi_constants(*test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_pi_constants())
|
|
||||||
|
|
||||||
def test_tpz_display_settings(self):
|
|
||||||
for intensity in 0, 10, 30, 50, 100, 150, 254:
|
|
||||||
with self.subTest(intensity=intensity):
|
|
||||||
test_vector = intensity
|
|
||||||
self.cont.set_tpz_display_settings(test_vector)
|
|
||||||
self.assertEqual(test_vector,
|
|
||||||
self.cont.get_tpz_display_settings())
|
|
||||||
|
|
||||||
def test_tpz_io_settings(self):
|
|
||||||
for v in 75*V, 100*V, 150*V:
|
|
||||||
with self.subTest(v=v):
|
|
||||||
test_vector = v, 1
|
|
||||||
self.cont.set_tpz_io_settings(*test_vector)
|
|
||||||
self.assertEqual(test_vector, self.cont.get_tpz_io_settings())
|
|
||||||
|
|
||||||
|
|
||||||
class TestTdc(ControllerCase, GenericTdcTest):
|
|
||||||
def setUp(self):
|
|
||||||
ControllerCase.setUp(self)
|
|
||||||
self.start_controller("tdc")
|
|
||||||
self.cont = self.device_mgr.get("tdc")
|
|
||||||
|
|
||||||
|
|
||||||
class TestTdcSim(GenericControllerCase, GenericTdcTest):
|
|
||||||
def get_device_db(self):
|
|
||||||
return {
|
|
||||||
"tdc": {
|
|
||||||
"type": "controller",
|
|
||||||
"host": "::1",
|
|
||||||
"port": 3255,
|
|
||||||
"command": (sys.executable.replace("\\", "\\\\")
|
|
||||||
+ " -m artiq.frontend.aqctl_thorlabs_tcube "
|
|
||||||
+ "-p {port} -P tdc001 --simulation")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
GenericControllerCase.setUp(self)
|
|
||||||
self.start_controller("tdc")
|
|
||||||
self.cont = self.device_mgr.get("tdc")
|
|
||||||
|
|
||||||
|
|
||||||
class TestTpz(ControllerCase, GenericTpzTest):
|
|
||||||
def setUp(self):
|
|
||||||
ControllerCase.setUp(self)
|
|
||||||
self.start_controller("tpz")
|
|
||||||
self.cont = self.device_mgr.get("tpz")
|
|
||||||
|
|
||||||
|
|
||||||
class TestTpzSim(GenericControllerCase, GenericTpzTest):
|
|
||||||
def get_device_db(self):
|
|
||||||
return {
|
|
||||||
"tpz": {
|
|
||||||
"type": "controller",
|
|
||||||
"host": "::1",
|
|
||||||
"port": 3255,
|
|
||||||
"command": (sys.executable.replace("\\", "\\\\")
|
|
||||||
+ " -m artiq.frontend.aqctl_thorlabs_tcube "
|
|
||||||
+ "-p {port} -P tpz001 --simulation")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
GenericControllerCase.setUp(self)
|
|
||||||
self.start_controller("tpz")
|
|
||||||
self.cont = self.device_mgr.get("tpz")
|
|
@ -88,7 +88,13 @@ The preferred way to specify a serial device is to make use of the ``hwgrep://``
|
|||||||
URL: it allows to select the serial device by its USB vendor ID, product
|
URL: it allows to select the serial device by its USB vendor ID, product
|
||||||
ID and/or serial number. Those never change, unlike the device file name.
|
ID and/or serial number. Those never change, unlike the device file name.
|
||||||
|
|
||||||
See the :ref:`TDC001 documentation <tdc001-controller-usage-example>` for an example of ``hwgrep://`` usage.
|
For instance, if you want to specify the Vendor/Product ID and the USB Serial Number, you can do:
|
||||||
|
|
||||||
|
``-d "hwgrep://<VID>:<PID> SNR=<serial_number>"``.
|
||||||
|
for example:
|
||||||
|
|
||||||
|
``-d "hwgrep://0403:faf0 SNR=83852734"``
|
||||||
|
|
||||||
|
|
||||||
run unit tests?
|
run unit tests?
|
||||||
---------------
|
---------------
|
||||||
|
@ -7,90 +7,3 @@ Core device logging controller
|
|||||||
.. argparse::
|
.. argparse::
|
||||||
:ref: artiq.frontend.aqctl_corelog.get_argparser
|
:ref: artiq.frontend.aqctl_corelog.get_argparser
|
||||||
:prog: aqctl_corelog
|
:prog: aqctl_corelog
|
||||||
|
|
||||||
|
|
||||||
Thorlabs T-Cube
|
|
||||||
---------------
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
When power is applied before the USB connection, some devices will enter a state where they fail to report the completion of commands. When using the ARTIQ controller, this cause certain function calls to never return and freeze the controller. To prevent this, connect USB first and then power up the device. When a device has entered the problematic state, power-cycling it while keeping the USB connection active also resolves the problem.
|
|
||||||
|
|
||||||
TDC001 Driver
|
|
||||||
+++++++++++++
|
|
||||||
|
|
||||||
.. autoclass:: artiq.devices.thorlabs_tcube.driver.Tdc
|
|
||||||
:members:
|
|
||||||
|
|
||||||
TPZ001 Driver
|
|
||||||
+++++++++++++
|
|
||||||
|
|
||||||
.. autoclass:: artiq.devices.thorlabs_tcube.driver.Tpz
|
|
||||||
:members:
|
|
||||||
|
|
||||||
Controller
|
|
||||||
++++++++++
|
|
||||||
|
|
||||||
.. argparse::
|
|
||||||
:ref: artiq.frontend.aqctl_thorlabs_tcube.get_argparser
|
|
||||||
:prog: aqctl_thorlabs
|
|
||||||
|
|
||||||
.. _tdc001-controller-usage-example:
|
|
||||||
|
|
||||||
TDC001 controller usage example
|
|
||||||
+++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
First, run the TDC001 controller::
|
|
||||||
|
|
||||||
$ aqctl_thorlabs_tcube -P TDC001 -d /dev/ttyUSBx
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
On Windows the serial port (the ``-d`` argument) will be of the form ``COMx``.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
Anything compatible with `serial_for_url <http://pyserial.sourceforge.net/pyserial_api.html#serial.serial_for_url>`_
|
|
||||||
can be given as a device in ``-d`` argument.
|
|
||||||
|
|
||||||
For instance, if you want to specify the Vendor/Product ID and the USB Serial Number, you can do:
|
|
||||||
|
|
||||||
``-d "hwgrep://<VID>:<PID> SNR=<serial_number>"``.
|
|
||||||
for instance:
|
|
||||||
|
|
||||||
``-d "hwgrep://0403:faf0 SNR=83852734"``
|
|
||||||
|
|
||||||
The hwgrep URL works on both Linux and Windows.
|
|
||||||
|
|
||||||
Then, send commands to it via the ``artiq_rpctool`` utility::
|
|
||||||
|
|
||||||
$ artiq_rpctool ::1 3255 list-targets
|
|
||||||
Target(s): tdc001
|
|
||||||
$ artiq_rpctool ::1 3255 call move_relative 10000 # will move forward
|
|
||||||
$ artiq_rpctool ::1 3255 call move_relative -10000 # will move backward
|
|
||||||
$ artiq_rpctool ::1 3255 call move_absolute 20000 # absolute move to 20000
|
|
||||||
$ artiq_rpctool ::1 3255 call move_home # will go back to home position
|
|
||||||
$ artiq_rpctool ::1 3255 call close # close the device
|
|
||||||
|
|
||||||
TPZ001 controller usage example
|
|
||||||
+++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
First, run the TPZ001 controller::
|
|
||||||
|
|
||||||
$ aqctl_thorlabs_tcube -P TPZ001 -d /dev/ttyUSBx
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
On Windows the serial port (the ``-d`` argument) will be of the form ``COMx``.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
See the :ref:`TDC001 documentation <tdc001-controller-usage-example>` for
|
|
||||||
how to specify the USB Serial Number of the device instead of the
|
|
||||||
/dev/ttyUSBx (or the COMx name).
|
|
||||||
|
|
||||||
Then, send commands to it via the ``artiq_rpctool`` utility::
|
|
||||||
|
|
||||||
$ artiq_rpctool ::1 3255 list-targets
|
|
||||||
Target(s): tpz001
|
|
||||||
$ artiq_rpctool ::1 3255 call set_output_volts 15 # set output voltage to 15 V
|
|
||||||
$ artiq_rpctool ::1 3255 call get_output_volts # read back output voltage
|
|
||||||
15
|
|
||||||
$ artiq_rpctool ::1 3255 call set_tpz_io_settings 150 1 # set maximum output voltage to 150 V
|
|
||||||
$ artiq_rpctool ::1 3255 call set_output_volts 150 # set output voltage to 150 V
|
|
||||||
$ artiq_rpctool ::1 3255 call close # close the device
|
|
||||||
|
1
setup.py
1
setup.py
@ -37,7 +37,6 @@ console_scripts = [
|
|||||||
"artiq_flash = artiq.frontend.artiq_flash:main",
|
"artiq_flash = artiq.frontend.artiq_flash:main",
|
||||||
|
|
||||||
"aqctl_corelog = artiq.frontend.aqctl_corelog:main",
|
"aqctl_corelog = artiq.frontend.aqctl_corelog:main",
|
||||||
"aqctl_thorlabs_tcube = artiq.frontend.aqctl_thorlabs_tcube:main",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
gui_scripts = [
|
gui_scripts = [
|
||||||
|
Loading…
Reference in New Issue
Block a user