pyvisa / pyvisa-py

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

Cannot write hex characters above 7F #129

Closed themikemachine closed 6 years ago

themikemachine commented 6 years ago

I tried using PyVISA to communicate via RS232 with a Neslab RTE-111 water bath. I can find the instrument, but I cannot communicate with it because the pyvisa 'write' command gives an error when sending any hex character that is larger than '7F'. Unfortunately the water bath requires sending commands such as "CA 00 01 F0 02 01 2C DF".

The code is below.

import pyvisa
rm = pyvisa.ResourceManager()
inst = rm.open_resource('ASRL::INSTR')
inst.write('\xca\x00\x01\x20\x00\xde')

This gives the error:


Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Owner\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pyvisa\resources\messagebased.py", line 223, in write
    count = self.write_raw(message.encode(enco))
UnicodeEncodeError: 'ascii' codec can't encode character '\xca' in position 0: ordinal not in range(128)

The write command seems to work fine for hex values below \x7f. Is it possible to send, say, '\xca'?

MatthieuDartiailh commented 6 years ago

The issue is that write expect a unicode string to encode. It looks like your device relies on some lower level interface and requires you to explicitly write bytes. Here this fails because the ascii encoding fail to encode your data. You could either try to set the encoding to utf-8 using the encoding keyword argument, or directly passing a byte string to write_raw

inst.write_raw(b'\xca\x00\x01\x20\x00\xde')
themikemachine commented 6 years ago

Thanks that helps. I can now communicate with the instrument and send it temperatures. However, I cannot read the replies coming from the instrument, always getting a 'timed out' error.

To read the reply, I am following the "inst.write_raw" command with inst.read()

Any ideas on what to try?

This is the error in full Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Users\Owner\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pyvisa\resources\messagebased.py", line 413, in read message = self._read_raw().decode(enco) File "C:\Users\Owner\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pyvisa\resources\messagebased.py", line 386, in _read_raw chunk, status = self.visalib.read(self.session, size) File "C:\Users\Owner\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pyvisa\ctwrapper\functions.py", line 1584, in read ret = library.viRead(session, buffer, count, byref(return_count)) File "C:\Users\Owner\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pyvisa\ctwrapper\highlevel.py", line 188, in _return_handler raise errors.VisaIOError(ret_value) pyvisa.errors.VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.

MatthieuDartiailh commented 6 years ago

Usually instruments use a special character to indicate the end of a message (\r or \n are the usual markers). This should be given in the documentation. Given that your instrument apparently relies on closer to the metal protocol, it may use fixed length message. If it is so you can use the read_bytes function to read a given number of bytes.

themikemachine commented 6 years ago

Perfect. That works great. I believe that my instrument does not use any end of message characters, that must be why it was hanging. Now I have all I need.

MatthieuDartiailh commented 6 years ago

Perfect I will close then feel free to re-open if necessary.