Coder Social home page Coder Social logo

easy-scpi's Introduction

Easy SCPI

A simple and robust library making communication with SCPI (Standard Control of Programmbale Instruments) instruments easy. After creating an instrument object that connects to an actual instrument, commands are sent to the instrument using a property-like format. This class is useful for inheritance when creating a controller for a specific instrument. Communication with instruments is done with PyVISA.

Install with python -m pip install easy-scpi

API

SCPI Commands

Generic SCPI commands can be executed by transforming the SCPI code in to attributes via the hierarchy relationship, then calling it. Instrument properties can be queried by passing no arguments to the call. Commands with no arguments are run by passing an empty string to the call.

Examples

# import package
import easy_scpi as scpi 

# Connect to an instrument
inst = scpi.Instrument( <port> )

# Read the voltage [MEASure:VOLTage:DC?]
inst.measure.voltage.dc()
# or
inst.meas.volt.dc()

# Set the voltage to 1 V [MEASure:VOLTage:DC 1]
inst.measure.voltage.dc( 1 )
# or
inst.source.voltage( '1' )

# Execute a command to take a reading [SYSTem:ZCORrect:ACQuire]
inst.syst.zcor.aqc( '' )

Methods

Instrument( <port>, backend = '', **resource_params ): Creates an instance of a SCPI instrument. The backend is used to create the VISA Resource Manager. Upon connection, the resource_params are passed to the VISA resource.

connect(): Connects the object instance to the actual instrument on the specified port.

disconnect(): Disconnects the instrument from the program, closing the port.

write( <msg> ): Sends msg to the instrument.

read(): Gets the most recent response from the instrument.

query( <msg> ): Sends msg to the instrument and returns its response.

reset(): Sets the instrument to its default state.

init(): Initializes the instrument for a measurement.

Properties

backend: Returns the name of the VISA backend used. [Read Only]

inst: Returns the resource used by the instance. [Read Only]

port: The communication port.

handshake: Handshake mode of the device. If a string is provided a handshake message will be read after every command or query. If the message matches the string, nothing occurs, otherwise an error is raised. If True a default message of 'OK' is used. If False no message is read. [Default: False]

rid: The resource id associated with the instrument. [Read Only]

resource_params: Returns the resource parameters passed on creation. [Read Only]

timeout: The communication timeout of the instrument. [Read Only]

id: The manufacturer id of the instrument. [Read Only]

value: The current value of the instrument. [Read Only]

connected: Whether the instrument is connected or not. [Read Only]

is_connected: Alias for connected.

Full Example

For use with Tektronix PWS4305

# scpi controller
import easy_scpi as scpi

class PowerSupply( scpi.Instrument ):
    
    def __init__( self ):
        super().__init__( 
            port = None, 
            timeout = 5,
            read_termination = '\n', 
            write_termination = '\n' 
        )

        # other initialization code...

        
    #--- public methods ---

    
    @property        
    def voltage( self ):
        """
        Returns the voltage setting
        """
        return self.source.volt.level()
    
    
    @voltage.setter
    def voltage( self, volts ):
        """
        Sets the voltage of the instrument
        """
        self.source.volt.level( volts )
        
    
    @property
    def current( self ):
        """
        Returns the current setting in Amps
        """
        return self.source.current.level()
        
        
    @current.setter
    def current( self, amps ):
        """
        Set the current of the instrument
        """
        self.source.current.level( amps )
        
    
    def on( self ):
        """
        Turns the output on
        """
        self.output.state( 'on' )
        
        
    def off( self):
        """
        Turns the output off
        """
        self.output.state( 'off' )
        

easy-scpi's People

Contributors

bicarlsen avatar bmjones2 avatar gillesc avatar mrv96 avatar mtenders avatar sciguy14 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

easy-scpi's Issues

Add support for queries with a parameter

Dear Brian,

I have a TCPIP instrument whose API includes some parametrized SCPI queries in the form of :STUFf:THINg?[<wsp>MIN|MAX|DEF|SET|ACT|ALL] and I can't find how to perform those queries using easy_scpi.

Trying:

my_instrument.stuff.thing('MIN')

would return a fixed int (let's say 24 for instance). easy_scpi does no processing of the response so I believe this integer is genuinely sent back by the instrument although its documentation does not mention it.

Am I doing it wrong or is it not yet supported by easy_scpi?

Thank you for your time and your great abstraction work in this module.

Feature request: optionally permit topmost SCPI class NAME to emit :NAME instead of NAME + raw sketch

Use case: Owon HDS200 series scope meter.

In this SCPI dialect, normal commands and queries usually(?) start with a mandatory ":".

Currently INSTRUMENT.chan.("OFF") sends CHAN OFF to the device. For the Owon to not ignore command, it must begin with a colon: i.e. :CHAN OFF to turn off the signal generator channel.

As expected, INSTRUMENT.:chan("OFF") and variants make Python throw errors, while easy-scpi already properly injects colons deeper in the hierarchy: INSTRUMENT.foo.bar(42) translates to <>FOO<:>BAR 42 (<> marks the spots).

So my issue is just a way to add the missing first colon on (some?) sent commands.

Possible implementation for this:

In the invoking script, permit the use of some horribly long "unique" string such as REPLACEBYCOLON as prefix to <SCPI-CLASS-NAME>.

Then mangle the used top class name of the command before sending by substituting REPLACEBYCOLON with just a colon. A global prefix on sending will probably have to implement exceptions, as e.g. the Owon dialect and esp. the programming guide are a bit - hmmm - funny.

Maybe make REPLACEBYCOLON configurable for the caller, thus that on collision or via eval the user can can change it or turn it off for a bit..

Thx,
Peter

'@py' backend under Windows

Im using the pyvisa-py backend under Windows. When I try connect to an Instrument and set the backend to '@py' explicitly, I get the following error:

SerialException: could not open port 'COMCOM7': FileNotFoundError(2, 'The system cannot find the file specified.', None, 2)

If I don't set any backend it works flawlessly. I think removing the following if-clause would solve the problem:

# adjust port name for resource id to match backend
if self.__backend == '@py':
r_port = port
if 'COM' not in r_port:
r_port = 'COM' + r_port
else:
r_port = port.replace( 'COM', '' )
self.__rid = 'ASRL{}::INSTR'.format( r_port )

I didn't open a pull request, because I wasn't sure if the if-clause is needed for something.

GPIB Support

Looks like only COM and USB are supported, but PyVisa supports GPIB, so this should be a simple change?

Problem with sending commands - no termination sign

Hi, I have a problem with sending commands over TCPIP using this lib.

Simple code:
inst = scpi.Instrument(port_match=False) inst.rid='TCPIP0::192.168.8.211::30000::SOCKET' inst.connect() print(inst.id())

TCPIP0::192.168.8.211::30000::SOCKET Traceback (most recent call last): return self.query( '*IDN?' ) raise errors.VisaIOError(rv) pyvisa.errors.VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.

What I observe is that even to use pyvisa manager I have to set termination sign. I tried in such way:

inst.__inst.read_termination = '\n'
inst.__inst.write_termination = '\n'

But it is not working this should be set in such way:
self.__inst = self.__rm.open_resource( self.rid, read_termination = '\n', write_termination = '\n')

Do you have any workaround or hint how to fix that without changing a code??

`pip list
Package Version


easy-scpi 0.1.4
modbus-tk 1.1.2
pip 21.2.3
pymodbus 3.0.2
pyserial 3.5
PyVISA 1.13.0
PyVISA-py 0.6.0
setuptools 57.4.0
typing_extensions 4.4.0`

Use case for easy-scpi (or not?)

Dear Brian,

I spent a few hours trying to figure out how to use easy-scpi for my use case and I thought you might be interested in my conclusions:

  • My SCPI instrument has parametrized queries (see this previous issue) so I have to call the SCPI_Instrument.query() method which is not much different than using PyVISA directly.
  • My instrument has several "channels" (let's say they are channels) of which I use only a subset. Making that subset user-defined at my instrument class instantiation (inheriting from SCPI_Instrument) does not mixes well with easy-scpi parsing of nested method calls of my instrument. This could be done using eval() although this generalization negates the ease-of-use of easy-scpi:
eval(f"my_instrument.{channel_label_as_a_string}.whatever()")
  • It hides away PyVISA objects and makes manual control of my instrument MUCH MORE USER-FRIENDLY for testing and debugging.
  • It is one more library in the final requirement file and I have to consider the licensing if I intend to redistribute my work.

Overall, I believe it's still worth interacting with my instrument as a subclass of SCPI_Instrument, mostly for the third point. The class methods are identical to an ab initio class based on PyVISA (assuming some aliases for the query() and write() methods of the PyVISA resource).
The fourth point will have to be considered of course.

Support for commands with multiple parameters

I'm trying to enter a command to my SCPI-enabled device that takes multiple parameters:

Concretely"

MEMory:WORD <address>,<value>

With a concrete invocation of:

MEM:WORD #H0196, 511

However, when I try to execute inst.mem.word(0x196, 512), I get:

Traceback (most recent call last):
  File "easy_scpi_test.py", line 20, in <module>
    main()
  File "easy_scpi_test.py", line 13, in main
    inst.mem.word(0x196, 512)
TypeError: __call__() takes from 1 to 2 positional arguments but 3 were given

Awkward passing of serial device on linux

Hi!

Thanks for this initiative. I'm trying to use this library to communicate with a SCPI-enabled device over a serial link, running in linux.

The serial device that it's connected to is /dev/ttyACM0 and the underlying port that should be passed on to pyvisa should be ASRL/dev/ttyACM0::INSTR.

To make this work, I need to initialize the instrument using

inst = scpi.Instrument("COM/dev/ttyACM0"), which is a bit awkward under linux as the "COM" terminology isn't used there.

Add a proper full example to using the easy-scpi library to make it "easy"

Your example in the readme is confusing for beginners who don't know about VISA.
What should "<port>" look like in

# Connect to an instrument
inst = scpi.Instrument( <port> )

e.g I have a device I want to talk scpi comms to over tcp/ip on ip address 169.254.89.0 port 5025.

Trying these all fail:

inst = scpi.Instrument( "169.254.89.0:5025" , read_termination='\n', write_termination='\n')
inst = scpi.Instrument("169.254.89.0", read_termination='\n', write_termination='\n')
inst = scpi.Instrument("TCPIP0::169.254.89.0::5025::SOCKET", read_termination='\n', write_termination='\n')

What is a concrete example for the value ?

I eventually found that this worked:

inst = scpi.Instrument(read_termination='\n', write_termination='\n')
inst.rid="TCPIP0::169.254.89.0::5025::SOCKET"

Can you add an explanation to setting the rid in the readme if this is the correct connection method for tcp/ip case or explain the scpi.Instrument( <port> ) better.

Not an issue

Greetings Brian,

Couldn't find how to get in touch (linked-in won't let me, twitter account from there is down) so am using this. Not writing about an issue, just some thanks.

I've been using easy-scpi to build wrappers from the devices I have and use the most and it made everything extremely easy.

I made some classes to give the objects derived from scpi.Instrument utility functions (and autocomplete!) so I don't have to remember each thing's API. I've been using this stuff for a while, but as I was doing a demo of it on a recent livestream I decided it might be useful to others.

If you're curious how I'm using the lib, its the Rigol DSO, Unitrend signal generator and Siglent power supply support in: https://github.com/psychogenic/psytestbench

In any case, thanks again.
Cheers,
Pat D

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.