Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fallback functions for environments without NI VISA installed #483

Open
wbarnha opened this issue Jun 24, 2021 · 3 comments
Open

Fallback functions for environments without NI VISA installed #483

wbarnha opened this issue Jun 24, 2021 · 3 comments
Labels
Feature Request Wished Feature Help Wanted Nobody is working on this, you are welcome to! Improvements Improvements of existing feature Instruments

Comments

@wbarnha
Copy link
Contributor

wbarnha commented Jun 24, 2021

Opened by request from PR #482.

Most of the development environments I use are Ubuntu-based. According to https://lightlab.readthedocs.io/en/master/_static/installation/sysadmin.html#ubuntu-installation, it's possible to install NI VISA for Ubuntu. However, this approach isn't exactly user-friendly since not everyone has a software background. Plus I think it's a good move for us to move away on our dependency of needing binaries provided by NI in order to interface with Keysight instruments.

I have been able to communicate with plenty of Keysight instruments via a LAN interface, and there's plenty of documentation available to implement these commands. Would there be interest from the community to defer to trying to connect to a device over LAN if NI VISA isn't installed?

Another thing that should be considered is giving the user an option to turn off their usage of NI VISA, but usually they have that installed for a specific reason.

@jhillairet jhillairet added Feature Request Wished Feature Improvements Improvements of existing feature Instruments labels Jun 24, 2021
@jhillairet
Copy link
Member

I think it would be certainly useful, but I will let other express their opinions, as I do not use the measurement capabilities myself.

@dvincentwest
Copy link
Contributor

I'll chime in here that hardware related code is its own beast. I spent effort in the area a few years ago, and generally speaking it's hard to test, and everybody's setup is a little bit different. To me it seems a little bit tricky to get consensus, so you'll have to march to the beat of your own drum and if you have some good ideas, go for it, and then present what you're thinking. Maybe the one bit of direction is that pyvisa, I think, is the main api for communication. They intrinsically support different backends, and probably nivisa or at list some visa.dll is the default. pyvisa-py is a pure python backend that implements visa api calls, but then sends them over tcp or over serial communications. You might have a look at some of that and see if the problems aren't solvable with a simple pyvisa backend configuration.

@DavidLutton
Copy link
Contributor

I use PySerial everywhere I need to, then
NI with PyVISA on Windows
PyVISA with PyVISA-py on Linux to control USB-TMC or Ethernet instruments
gpib-ctypes works well with Linux GPIB (No NI or Keysight software) on Linux

Installation and usage of gpib-ctypes is not clear, I should clean install and write some notes.
There are also some permission quirks with USB-TMC devices on Linux, that need udev rules put in place.

What I do is wrap up common things in a metaclass and inherit that and IEEE4882 in the driver class
This should mean that I can arrange this for testing with pytest as the driver is not attempting to invoke hardware

As the resource connection is not established by the driver I can use different communication interfaces without changing the drivers behaviour. (or different host operating systems)

Demo follows with two different connection examples ManualMockInstrument and Hardware with PyVISA

import abc
from pyvisa.constants import VI_GPIB_REN_ADDRESS_GTL


class Instrument(metaclass=abc.ABCMeta):
    
    def __init__(self, instrument):
        self.inst = instrument
        self.inst.read_termination = '\n'
        self.inst.write_termination = '\n'
        self.__post__()
        
    # https://discuss.python.org/t/add-a-post-method-equivalent-to-the-new-method-but-called-after-init/5449/2
    def __post__(self):
        # use __post__ from metaclass to configure instrument
        None
    
    def write(self, *args, **kwargs):
        return self.inst.write(*args, **kwargs)

    def query(self, *args, **kwargs):
        return self.inst.query(*args, **kwargs)
        
    def query_float(self, *args, **kwargs):
        return float(self.query(*args, **kwargs))

    def query_int(self, *args, **kwargs):
        return int(self.query(*args, **kwargs))

    def query_bool(self, *args, **kwargs):
        return bool(int(self.query(*args, **kwargs)))

    
class IEEE4882(Instrument):
    @property
    def local(self):
        return self.inst.control_ren(VI_GPIB_REN_ADDRESS_GTL)

    @property
    def IDN(self):
        return self.query('*IDN?')
    
    @property
    def OPC(self):
        return self.query_bool('*OPC?')

    
class KeysightXA(IEEE4882):
    """Class for Keysight N90nnB Spectrum Analyser."""
    
    def __post__(self): 
        self.write(f':SYST:ERR:VERB {True:b}')  # Turn on verbose command errors
    
    @property
    def frequency(self):
        """Center frequency."""
        return self.query_float(":FREQuency:CENT?")

    @frequency.setter
    def frequency(self, frequency):
        self.write(f":FREQuency:CENT {frequency}")
            
    @property
    def sweep_points(self):
        return self.query_int(":SWEep:POINts?")

    @sweep_points.setter
    def sweep_points(self, points):
        self.write(f":SWEep:POINts {points:.0f}")
class ManualMockInstrument():
    def write(self, input_):
        print(input_)
    def read(self):
        return input('... : ')
    def query(self, input_):
        return input(f'{input_} :')
    
    def control_ren(self, input_):
        print(f'CTRL {input_}')

# Mock
inst = KeysightXA(ManualMockInstrument())
inst.frequency
inst.sweep_points
inst.OPC
# Hardware with PyVISA
import pyvisa
rm = pyvisa.ResourceManager()
inst = KeysightXA(rm.open_resource('GPIB0::18::INSTR'))
inst.frequency
inst.sweep_points
inst.OPC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request Wished Feature Help Wanted Nobody is working on this, you are welcome to! Improvements Improvements of existing feature Instruments
Projects
Development

No branches or pull requests

4 participants