pyvisa / pyvisa-py

A pure python PyVISA backend
https://pyvisa-py.readthedocs.io
MIT License
288 stars 124 forks source link

Support for TCPIP SOCKET #38

Closed MatthieuDartiailh closed 9 years ago

MatthieuDartiailh commented 9 years ago

It would be nice to have support for TCPIP SOCKET protocol, as TCPIP is the only protocol that should always work. Could you give some pointers about what would need to be adapted from the INSTR case to support the SOCKET case ?

nktsaini commented 9 years ago

I too am looking for a way to use a raw socket connection using the pyvisa-py. Is any such thing forthcoming in the near future?

nktsaini commented 9 years ago

Hey Matthieu.

I was just digging around trying to send SCPI commands over the raw socket connection since my instrument understands SCPI only. I ran the following script:

import socket
sock = socket.socket(sock.AF_INET, sock.SOCK_STREAM)
sock.sento("DISP::TEXT::STAT ON", ("10.66.22.150", 1349))

I don't get any error messages but my instrument doesn't respond either. So I think the information is being sent but the instrument isn't understanding it. If you have an instrument, could you confirm this?

MatthieuDartiailh commented 9 years ago

Your message is lacking a termination character. You will have to check the doc to see what it expects (\r\n is a common combination).

nktsaini commented 9 years ago

You're right.

Also, I think the sendto() module sends one character at a time and hence needs to be used in a loop. If I run the following script, I am able to communicate with the instrument successfully.

import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.sendall("[Your random SCPI command]\n")
hgrecco commented 9 years ago

I will add support for SOCKET if you are willing to test it.

MatthieuDartiailh commented 9 years ago

Great !

nktsaini commented 9 years ago

Yes, let us know how do we start.

hgrecco commented 9 years ago

I have pushed a commit in this direction.

thliebig commented 9 years ago

I have fixed some issues and got a first working SOCKET connection, thanks

nktsaini commented 9 years ago

I am running this script:

import visa
rm = visa.ResourceManager('@py')
dmm = rm.open_resource('TCPIP::10.66.22.150::1394::SOCKET')

and I get the error message saying

Exception: could not create socket: an integer is required

What am I doing wrong here?

thliebig commented 9 years ago

I have fixed this and more in my commits ... please try these

nktsaini commented 9 years ago

I ran the following script:

import visa
rm = visa.ResourceManager('@py')
dmm = rm.open_resource('TCPIP::10.66.22.150::1394::SOCKET')
print(dmm.query("*IDN?"))

It sets up the connection successfully I think but doesn't print the IDN. I get the following error:

error                                     Traceback (most recent call last)
<ipython-input-4-b40c68bb1b47> in <module>()
----> 1 print(dmm.query("*IDN?"))

/usr/local/lib/python2.7/dist-packages/PyVISA-1.8.dev0-py2.7.egg/pyvisa/resources/messagebased.pyc in query(self, message, delay)
    399         """
    400 
--> 401         self.write(message)
    402 
    403         delay = self.query_delay if delay is None else delay

/usr/local/lib/python2.7/dist-packages/PyVISA-1.8.dev0-py2.7.egg/pyvisa/resources/messagebased.pyc in write(self, message, termination, encoding)
    205             message += term
    206 
--> 207         count = self.write_raw(message.encode(enco))
    208 
    209         return count

/usr/local/lib/python2.7/dist-packages/PyVISA-1.8.dev0-py2.7.egg/pyvisa/resources/messagebased.pyc in write_raw(self, message)
    183         :rtype: int
    184         """
--> 185         return self.visalib.write(self.session, message)
    186 
    187     def write(self, message, termination=None, encoding=None):

/home/debian/Downloads/pyvisa-py-8c0af80726212795af707122ce2a77d5368d8497/pyvisa-py/highlevel.py in write(self, session, data)
    273         # from the session handle, dispatch to the write method of the session object.
    274         try:
--> 275             return self.sessions[session].write(data)
    276         except KeyError:
    277             return constants.StatusCode.error_invalid_object

/home/debian/Downloads/pyvisa-py-8c0af80726212795af707122ce2a77d5368d8497/pyvisa-py/tcpip.py in write(self, data)
    434                 # use select to wait for write ready
    435                 select.select([], [self.interface], [])
--> 436                 size = self.interface.send(block)
    437             except socket.timeout as e:
    438                 return offset, StatusCode.error_io

error: [Errno 32] Broken pipe
thliebig commented 9 years ago

A broken pipe may indicate that the remote (device) closed the connection... The pyvisa-py should handle that correctly, but I don't know why it happened. Have you tried different termination characters?

hgrecco commented 9 years ago

I merged @thliebig PR. Thanks. Maybe we can implement select also on the read part.

@nktsaini: can you enable logging? can you also try:

inst.write_termination = '\n'
hgrecco commented 9 years ago

@nktsaini : can you also post your working code using socket? It will help a lot to get this right (I do not have socket instrument to test right now).

thliebig commented 9 years ago

@hgrecco Do you have a TCPIP INSTR device to test? I was able to use a socket connection on a device I usually used as INSTR device for testing as well. Maybe you can try it.

nktsaini commented 9 years ago

The script I ran is:

import visa
rm = visa.ResourceManager('@py')
visa.log_to_screen
dmm = rm.open_resource('TCPIP::10.66.22.150::1394::SOCKET')
print(dmm.query("*IDN?\n"))

An error is not thrown up anymore but nothing happens until I terminate the code.

In [10]: print(dmm.query("*IDN?\n"))
2015-03-01 22:01:26,360 - pyvisa - DEBUG - TCPIP::10.66.22.150::1394::SOCKET - reading 20480 bytes (last status <StatusCode.success_max_count_read: 1073676294>)

Also, when I write:

dmm.write_termination = '\n'

No error and no log either.

nktsaini commented 9 years ago

@hgrecco : I am new to python programming so my socket programming is pretty elementary.

import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("10.66.22.150", 1394))

#to send commands
sock.sendall("[Random SCPI command]\n")       

#to read
sock.sendall("[Triggering SCPI command]\n")
a = sock.recv(512)

That is pretty much it. Are you asking for anything more?

nktsaini commented 9 years ago

I've made a new script. How do I share it on here? I'm new on github.

hgrecco commented 9 years ago

You can create a gist a put the link

rinitha commented 9 years ago

This is the code we've been working with. Hope this helps!

hgrecco commented 9 years ago

As far as I can see, the only difference is that you are using sendall (pyvisa-py uses send in write) @thliebig what do you think?

Also some commands end with '\r', but this can be easily achieve now with pyvisa.

@rinitha or @nktsaini can you also create a gist with the code you are using to test the same thing with pyvisa so that I check that there are no errors there.

nktsaini commented 9 years ago

@hgrecco Do you mean that we test our code using pyvisa with NI-VISA as the backend?

hgrecco commented 9 years ago

@nktsaini Exactly. pyvisa-py is a backend for pyvisa that tries to provide the same functionality of the default backend (NI-VISA). It is useful in platforms where NI-VISA is not available or when you just one to use free software. To be sure that is a pyvisa-py bug, the best way is to run the same script with both backends. ie. you do:

script 1:

import visa
rm = visa.ResourceManager()
visa.log_to_screen
dmm = rm.open_resource('TCPIP::10.66.22.150::1394::SOCKET')
print(dmm.query("*IDN?\n"))

script 2

import visa
rm = visa.ResourceManager('@py')
visa.log_to_screen
dmm = rm.open_resource('TCPIP::10.66.22.150::1394::SOCKET')
print(dmm.query("*IDN?\n"))
nktsaini commented 9 years ago

I was away for the past few days. I'll do this and get back to you as soon as possible.

rinitha commented 9 years ago

Please have a look at this code. It has various attributes which help in measuring voltages across channels in a Keithley2701 DMM.

nktsaini commented 9 years ago

So I tried running script 1 with the visa backend. This is what I got:

Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.

C:\Users\ankit>ipython
Python 2.7.9 |Anaconda 2.2.0 (64-bit)| (default, Dec 18 2014, 16:57:52) [MSC v.1
500 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 3.0.0 -- An enhanced Interactive Python.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://binstar.org
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import visa

In [2]: visa.log_to_screen()

In [3]: rm = visa.ResourceManager()
2015-06-09 10:05:40,582 - pyvisa - DEBUG - No user defined library files
2015-06-09 10:05:40,663 - pyvisa - DEBUG - Automatically found library files: ['
C:\\windows\\system32\\visa32.dll', 'C:\\windows\\system32\\visa32.dll']
2015-06-09 10:05:40,943 - pyvisa - DEBUG - Library signatures: 90 ok, 0 failed
2015-06-09 10:05:40,943 - pyvisa - DEBUG - Created library wrapper for C:\window
s\system32\visa32.dll
2015-06-09 10:05:41,953 - pyvisa - DEBUG - viOpenDefaultRM('<ViObject object at
0x0000000003BD52C8>',) -> 0
2015-06-09 10:05:41,953 - pyvisa - DEBUG - Created ResourceManager with session
4097

In [4]: dmm = rm.open_resource("TCPIP::10.66.22.150::1394::SOCKET")
2015-06-09 10:06:13,279 - pyvisa - DEBUG - viParseRsrcEx(4097L, 'TCPIP::10.66.22
.150::1394::SOCKET', 'c_ushort(6)', 'c_ushort(0)', <ctypes.c_char_Array_256 obje
ct at 0x0000000003BD5AC8>, <ctypes.c_char_Array_256 object at 0x0000000003BD5B48
>, <ctypes.c_char_Array_256 object at 0x0000000003BD5C48>) -> 0
2015-06-09 10:06:13,279 - pyvisa - DEBUG - TCPIP::10.66.22.150::1394::SOCKET - o
pening ...
2015-06-09 10:06:13,349 - pyvisa - DEBUG - viOpen(4097L, 'TCPIP::10.66.22.150::1
394::SOCKET', <AccessModes.no_lock: 0>, 0, '<ViObject object at 0x0000000003BD5C
48>') -> 0
2015-06-09 10:06:13,349 - pyvisa - DEBUG - TCPIP::10.66.22.150::1394::SOCKET - i
s open with session 1

In [5]: print(dmm.query("*IDN?\n"))
2015-06-09 10:06:52,250 - pyvisa - DEBUG - viWrite(1L, '*IDN?\n\r\n', 8, 'c_ulon
g(8L)') -> 0
2015-06-09 10:06:52,250 - pyvisa - DEBUG - TCPIP::10.66.22.150::1394::SOCKET - r
eading 20480 bytes (last status <StatusCode.success_max_count_read: 1073676294>)

2015-06-09 10:06:54,250 - pyvisa - DEBUG - viRead(1L, <ctypes.c_char_Array_20480
 object at 0x0000000003BD5C48>, 20480, 'c_ulong(57L)') -> -1073807339
2015-06-09 10:06:54,250 - pyvisa - DEBUG - TCPIP::10.66.22.150::1394::SOCKET - e
xception while reading: VI_ERROR_TMO (-1073807339): Timeout expired before opera
tion completed.
---------------------------------------------------------------------------
VisaIOError                               Traceback (most recent call last)
<ipython-input-5-e0c2ef9e1d6b> in <module>()
----> 1 print(dmm.query("*IDN?\n"))

C:\Anaconda\lib\site-packages\pyvisa-1.8.dev0-py2.7.egg\pyvisa\resources\message
based.pyc in query(self, message, delay)
    405         if delay > 0.0:
    406             time.sleep(delay)
--> 407         return self.read()
    408
    409     # Kept for backwards compatibility.

C:\Anaconda\lib\site-packages\pyvisa-1.8.dev0-py2.7.egg\pyvisa\resources\message
based.pyc in read(self, termination, encoding)
    330         if termination is None:
    331             termination = self._read_termination
--> 332             message = self.read_raw().decode(enco)
    333         else:
    334             with self.read_termination_context(termination):

C:\Anaconda\lib\site-packages\pyvisa-1.8.dev0-py2.7.egg\pyvisa\resources\message
based.pyc in read_raw(self, size)
    304                     logger.debug('%s - reading %d bytes (last status %r)
',
    305                                  self._resource_name, size, status)
--> 306                     chunk, status = self.visalib.read(self.session, size
)
    307                     ret += chunk
    308             except errors.VisaIOError as e:

C:\Anaconda\lib\site-packages\pyvisa-1.8.dev0-py2.7.egg\pyvisa\ctwrapper\functio
ns.pyc in read(library, session, count)
   1583     buffer = create_string_buffer(count)
   1584     return_count = ViUInt32()
-> 1585     ret = library.viRead(session, buffer, count, byref(return_count))
   1586     return buffer.raw[:return_count.value], ret
   1587

C:\Anaconda\lib\site-packages\pyvisa-1.8.dev0-py2.7.egg\pyvisa\ctwrapper\highlev
el.pyc in _return_handler(self, ret_value, func, arguments)
    186
    187         if ret_value < 0:
--> 188             raise errors.VisaIOError(ret_value)
    189
    190         if ret_value in self.issue_warning_on:

VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation comple
ted.
hgrecco commented 9 years ago

@nktsaini Let's try to fix that first. First, remove the \n and add:

dmm.write_termination = '\n'

before the query. Run it again. If it does not work, check the manual of the instrument for the correct end of message and change it using

dmm.read_termination = <put here what the manual tells you>
nktsaini commented 9 years ago

@hgrecco I'm away for today. I'll get back to you as soon as possible.

hgrecco commented 9 years ago

I am closing this, feel free to reopen if needed.