pyvisa / pyvisa-py

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

GPIB: character char not identified in middle of meesage #283

Open daturach opened 3 years ago

daturach commented 3 years ago

Hello

I have an old Philips PM6666 counter connected to a GPIB PCI board (old as well...). I have installed pyvisa and linux-gpib. I have 2 different py scripts that should give the same results, one for the linux-gpib python binding and the other one for pyvisa. Here are the different scenarios: (notice the number of chars read)

Python bindings:

import sys
import time
import Gpib
inst = Gpib.Gpib(0,6)
inst.write("BUS?")
time.sleep(0.1)
cur1 = inst.read(100)
time.sleep(0.1)
print (cur1)
inst.close()

Result: b'MSR 000,OUTM 000\nEOI ON,SPR 010\n'

pyvisa:

import pyvisa as visa
rm = visa.ResourceManager('@py')
#print(rm.list_resources())  # bug, see https://github.com/pyvisa/pyvisa-py/issues/282
instr = rm.open_resource('GPIB0::6::INSTR')
instr.write('BUS?')
print(instr.read_bytes(33))
instr.close()

Result: b'MSR 000,OUTM 000\nEOI ON,SPR 010\n'

The result is the same. Now change line in pyvisa script. print(instr.read_bytes(33)) to print(instr.read_bytes(35))

Result:

Traceback (most recent call last):
  File "bug_visa.py", line 7, in <module>
    print(instr.read_bytes(35))
  File "/home/daturach/.local/lib/python3.7/site-packages/pyvisa/resources/messagebased.py", line 371, in read_bytes
    chunk, status = self.visalib.read(self.session, size)
  File "/home/daturach/.local/lib/python3.7/site-packages/pyvisa_py/highlevel.py", line 519, in read
    return data, self.handle_return_value(session, status_code)
  File "/home/daturach/.local/lib/python3.7/site-packages/pyvisa/highlevel.py", line 251, in handle_return_value
    raise errors.VisaIOError(rv)
pyvisa.errors.VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.

I wonder why the end of line is not detected.

Output python3 -m visa info

/home/daturach/.local/lib/python3.7/site-packages/visa.py:23: FutureWarning: The visa module provided by PyVISA is being deprecated. You can replace `import visa` by `import pyvisa as visa` to achieve the same effect.

The reason for the deprecation is the possible conflict with the visa package provided by the https://github.com/visa-sdk/visa-python which can result in hard to debug situations.
  FutureWarning,
Machine Details:
   Platform ID:    Linux-4.19.0-11-686-pae-i686-with-debian-10.6
   Processor:      

Python:
   Implementation: CPython
   Executable:     /usr/bin/python3
   Version:        3.7.3
   Compiler:       GCC 8.3.0
   Bits:           32bit
   Build:          Jul 25 2020 13:03:44 (#default)
   Unicode:        UCS4

PyVISA Version: 1.11.1

Backends:
   ivi:
      Version: 1.11.1 (bundled with PyVISA)
      Binary library: Not found
   py:
      Version: 0.5.1
      ASRL INSTR:
         Please install PySerial (>=3.0) to use this resource type.
         No module named 'serial'
      USB INSTR:
         Please install PyUSB to use this resource type.
         No module named 'usb'
      USB RAW:
         Please install PyUSB to use this resource type.
         No module named 'usb'
      TCPIP INSTR: Available 
      TCPIP SOCKET: Available 
      GPIB INSTR: Available via Linux GPIB (b'4.2.0')
      GPIB INTFC: Available via Linux GPIB (b'4.2.0')

Thanks for your help.

MatthieuDartiailh commented 3 years ago

When reading a fixed number of bytes PyVISA will by default try to read exactly that number. You can pass break_on_termchar= True to stop early but in that case make sure to set the proper termchar (see below).

This behavior comes from the fact that read_bytes is kind of low-level and meant for debugging/special purpose in pyvisa. If you goal is simply to read your instrument answer but ignore the \n (meaning there are not termination characters). You can do the following:

instr.read_termination = None
msg = instr.read_raw()  # If you want bytes
# msg = inst.read()  # if you prefer text
daturach commented 3 years ago

Hello

Thanks for the quick answer. I have tried the following and still no success: It doesn't stop after the first \n

import pyvisa as visa
rm = visa.ResourceManager('@py')
#print(rm.list_resources())  # bug, see https://github.com/pyvisa/pyvisa-py/issues/282
instr = rm.open_resource('GPIB0::6::INSTR')
instr.read_termination = '\n'  # from github https://github.com/pyvisa/pyvisa-py/issues/283
instr.write_termination = '\n'
instr.write('BUS?')
print(instr.read_bytes(33, break_on_termchar=True))
instr.close()

Result: b'MSR 000,OUTM 000\nEOI ON,SPR 010\n'

I need to be able to read a line without knowing in advance how many chars are going to be sent. I can then easily split at any chars. Thanks

daturach commented 3 years ago

That looks better:

import pyvisa as visa
rm = visa.ResourceManager('@py')
#print(rm.list_resources())  # bug, see https://github.com/pyvisa/pyvisa-py/issues/282

instr = rm.open_resource('GPIB0::6::INSTR')
instr.write('BUS?')
print(instr.read_raw())  # If you want bytes; from github https://github.com/pyvisa/pyvisa-py/issues/283
instr.close()

Result: b'MSR 000,OUTM 000\nEOI ON,SPR 010\n'

Thanks for your help.

MatthieuDartiailh commented 3 years ago

I took the liberty to edit the title so that I can try to come back later and fix the handling of the termchar.