From 20d6c605b10892d191b59627a67df4b1f57ef376 Mon Sep 17 00:00:00 2001 From: Kasper Revsbech Date: Mon, 14 Sep 2020 15:02:16 +0200 Subject: [PATCH] driver/pyvisadriver: add driver to support PyVISA Add driver and resource to support controlling test instruments using the PyVISA package. Signed-off-by: Kasper Revsbech --- CHANGES.rst | 2 ++ dev-requirements.txt | 1 + doc/configuration.rst | 28 ++++++++++++++++++++++++++ examples/pyvisa/env.yaml | 9 +++++++++ examples/pyvisa/pyvisa_example.py | 15 ++++++++++++++ labgrid/driver/__init__.py | 1 + labgrid/driver/pyvisadriver.py | 33 +++++++++++++++++++++++++++++++ labgrid/resource/__init__.py | 1 + labgrid/resource/pyvisa.py | 17 ++++++++++++++++ pyvisa-requirements.txt | 2 ++ tests/test_pyvisa.py | 14 +++++++++++++ 11 files changed, 123 insertions(+) create mode 100644 examples/pyvisa/env.yaml create mode 100644 examples/pyvisa/pyvisa_example.py create mode 100644 labgrid/driver/pyvisadriver.py create mode 100644 labgrid/resource/pyvisa.py create mode 100644 pyvisa-requirements.txt create mode 100644 tests/test_pyvisa.py diff --git a/CHANGES.rst b/CHANGES.rst index 52a1a2f10..6010726a9 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -61,6 +61,8 @@ New Features in 0.3.0 - ``labgrid-client`` now respects the ``LG_HOSTNAME`` and ``LG_USERNAME`` environment variables to set the hostname and username when accessing resources. +- PyVISA support added, allowing to use PyVISA controlled test equipment from + Labgrid. Breaking changes in 0.3.0 ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/dev-requirements.txt b/dev-requirements.txt index f8a6b26f6..82e45ab43 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -13,3 +13,4 @@ psutil==5.6.6 -r xena-requirements.txt -r graph-requirements.txt -r docker-requirements.txt +-r pyvisa-requirements.txt diff --git a/doc/configuration.rst b/doc/configuration.rst index 4bacc74a5..08232fa0b 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -627,6 +627,23 @@ A XenaManager resource describes a Xena Manager instance which is the instance t Used by: - `XenaDriver`_ +PyVISADevice +~~~~~~~~~~~~ +A PyVISADevice resource describes a test stimuli device controlled by PyVISA. +Such device could be a signal generator. + +.. code-block:: yaml + + PyVISADevice: + type: "TCPIP" + url: "192.168.110.11" + +- type (str): device resource type following the pyVISA resource syntax, e.g. ASRL, TCPIP... +- url (str): device identifier on selected resource, e.g. for TCPIP resource + +Used by: + - `PyVISADriver`_ + RemotePlace ~~~~~~~~~~~ A RemotePlace describes a set of resources attached to a labgrid remote place. @@ -1796,6 +1813,17 @@ Binds to: Implements: - :any:`DigitalOutputProtocol` +PyVISADriver +~~~~~~~~~~~~ +The PyVISADriver uses a PyVISADevice resource to control test equipment manageable by PyVISA. + +Binds to: + pyvisa_resource: + - `PyVISADevice`_ + +Implements: + - None yet + Strategies ---------- diff --git a/examples/pyvisa/env.yaml b/examples/pyvisa/env.yaml new file mode 100644 index 000000000..0979c4d7b --- /dev/null +++ b/examples/pyvisa/env.yaml @@ -0,0 +1,9 @@ +targets: + main: + resources: + PyVISADevice: + type: "TCPIP" + url: "192.168.110.11" + drivers: + PyVISADriver: + name: "PyVisa_device" diff --git a/examples/pyvisa/pyvisa_example.py b/examples/pyvisa/pyvisa_example.py new file mode 100644 index 000000000..16743ef40 --- /dev/null +++ b/examples/pyvisa/pyvisa_example.py @@ -0,0 +1,15 @@ +import pytest + + +@pytest.fixture() +def signal_generator(target): + return target.get_driver('PyVISADriver').get_session() + + +def test_with_signal_generator_example(signal_generator): + signal_generator.write('*RST') + + # Setup channel 1 + signal_generator.write('C1:BSWV WVTP,SQUARE,HLEV,5,LLEV,0,DUTY,50') + # Switch on channel 1 + signal_generator.write('C1:OUTP ON,LOAD,HZ,PLRT,NOR') diff --git a/labgrid/driver/__init__.py b/labgrid/driver/__init__.py index 2f8346abd..a29a1a120 100644 --- a/labgrid/driver/__init__.py +++ b/labgrid/driver/__init__.py @@ -29,3 +29,4 @@ from .xenadriver import XenaDriver from .dockerdriver import DockerDriver from .lxaiobusdriver import LXAIOBusPIODriver +from .pyvisadriver import PyVISADriver diff --git a/labgrid/driver/pyvisadriver.py b/labgrid/driver/pyvisadriver.py new file mode 100644 index 000000000..92174933e --- /dev/null +++ b/labgrid/driver/pyvisadriver.py @@ -0,0 +1,33 @@ +from importlib import import_module +import attr + +from ..factory import target_factory +from .common import Driver + + +@target_factory.reg_driver +@attr.s(eq=False) +class PyVISADriver(Driver): + """The PyVISADriver provides a transparent layer to the PyVISA module allowing to get a pyvisa resource + + Args: + bindings (dict): driver to use with PyVISA + """ + bindings = {"pyvisa_resource": "PyVISADevice"} + + def __attrs_post_init__(self): + super().__attrs_post_init__() + _py_pyvisa_module = import_module('pyvisa') + self._pyvisa_resource_manager = _py_pyvisa_module.ResourceManager() + self.pyvisa_device = None + + def on_activate(self): + device_identifier = '{}::{}::INSTR'.format(self.pyvisa_resource.type, self.pyvisa_resource.url) + self.pyvisa_device = self._pyvisa_resource_manager.open_resource(device_identifier) + + def on_deactivate(self): + self.pyvisa_device = None + + @Driver.check_active + def get_session(self): + return self.pyvisa_device diff --git a/labgrid/resource/__init__.py b/labgrid/resource/__init__.py index c05193aeb..5b1cf5a83 100644 --- a/labgrid/resource/__init__.py +++ b/labgrid/resource/__init__.py @@ -17,3 +17,4 @@ from .flashrom import Flashrom, NetworkFlashrom from .docker import DockerManager, DockerDaemon, DockerConstants from .lxaiobus import LXAIOBusPIO +from .pyvisa import PyVISADevice diff --git a/labgrid/resource/pyvisa.py b/labgrid/resource/pyvisa.py new file mode 100644 index 000000000..d1a93e89f --- /dev/null +++ b/labgrid/resource/pyvisa.py @@ -0,0 +1,17 @@ +import attr + +from ..factory import target_factory +from .common import Resource + + +@target_factory.reg_resource +@attr.s(eq=False) +class PyVISADevice(Resource): + """The PyVISADevice describes a test stimuli device controlled with PyVISA + + Args: + type (str): device resource type following the pyVISA resource syntax, e.g. ASRL, TCPIP... + url (str): device identifier on selected resource, e.g. for TCPIP resource + """ + type = attr.ib(validator=attr.validators.instance_of(str)) + url = attr.ib(validator=attr.validators.instance_of(str)) diff --git a/pyvisa-requirements.txt b/pyvisa-requirements.txt new file mode 100644 index 000000000..f1223a6d8 --- /dev/null +++ b/pyvisa-requirements.txt @@ -0,0 +1,2 @@ +pyvisa==1.10.1 +PyVISA-py==0.4.1 diff --git a/tests/test_pyvisa.py b/tests/test_pyvisa.py new file mode 100644 index 000000000..5c92951f3 --- /dev/null +++ b/tests/test_pyvisa.py @@ -0,0 +1,14 @@ +from labgrid.resource.pyvisa import PyVISADevice +from labgrid.driver.pyvisadriver import PyVISADriver + + +def test_pyvisa_resource(target): + PyVISADevice(target, name=None, type='TCPIP', url='127.0.0.1') + + +def test_resource_driver(target, mocker): + PyVISADevice(target, name=None, type='TCPIP', url='127.0.0.1') + driver = PyVISADriver(target, name=None) + + mocker.patch('pyvisa.ResourceManager.open_resource', return_value=None) + target.activate(driver)