I am currently trying to interface with a somewhat old old model of a HP-printer which gives me two possible methods of flow-control: No flow control at all or software-based flow control (XON/XOFF).
I am initializing pySerial with the following command and just justing a plain big string to write my data to the port:
serial = serial.Serial(port = '/dev/ttyUSB3', baudrate = 9600, parity = serial.PARITY_ODD, stopbits = serial.STOPBITS_ONE, bytesize = serial.EIGHTBITS)
This works fine - but there is a catch: it seems like the flow-control is completly ignored and data is sent and sent - which results in the device having a IO-buffer-overflow and stop working.
My first thought was, that if I use serial.write('unbelivable long string'), pySerial might not be able to cease transmission, so I split up the string into chunks and sent it:
data = ['command', 'another command', 'more commands', 'you get the drift...']
for i in data:
serial.write(i)
Well... This doesn't work either.
So basically I could just change the baud-rate to something lower so the device is faster than the transmission or just add something like a sleep every few chunks... But I guess, this is not how one should do it.
So... Anyone in to explain me, what am I doing wrong? ;-)
Thanks,
Martin
You forgot the xonxoff parameter. xonxoff=True
http://pyserial.readthedocs.io/en/latest/pyserial_api.html
Related
I have a device which works on serial communication. I am writing python code which will send some commands to get the data from the device.
There are three commands.
1.COMMAND - sop
Device does its internal calculation and sends below data
Response - "b'SOP,0,921,34,40,207,0,x9A\r\n'"
2.COMMAND - time
This gives a date time values which normally do not change untill the device is restarted
3.START - "\r\r" or (<cr><cr>)
This command puts the device in responsive mode after which it responds to above commands. This command is basically entering <enter> twice & only have to do once at the start.
Now the problem which I am facing is that, frequency of data received from sop command is not fixed and hence the data is received anytime. This command can also not be stopped once started, so if I run another command like time, and read the data, I do not receive time values and they are merged with the sop data sometime. Below is the code, I am using:
port = serial.Serial('/dev/ttyS0',115200) #Init serial port
port.write(("\r\r".encode())) #Sending the start command
bytesToRead = port.in_waiting #Checking data bytesize
res = port.read(bytesToRead) #Reading the data which is normally a welcome msg
port.reset_input_buffer() #Clearing the input serial buffer
port.reset_output_buffer() #Clearing the output serial buffer
port.write(("sop\r".encode())) #Sending the command sop
while True:
time.sleep(5)
bytesToRead = port.in_waiting
print(bytesToRead)
res = port.read(bytesToRead)
print(res)
port.reset_input_buffer()
port.write(("time\r".encode()))
res = port.readline()
print(res)
Using the above command I sometimes do not receive the value of time after executing its command or sometimes it is merged with the sop command. Also with the sop command, I received a lot of data during the sleep(5) out of which I need to get the latest data. If I do not include sleep(5), I miss the sop data and it is then received after executing the time command.
I was hoping if anyone can point me to right direction of how to design it in a better way. Also, I think this can easily be done using interrupt handler but I didn't found any code about pyserial interrupts. Can anyone please suggest some good code for using interrupts in pyserial.
Thanks
Instead of using time.sleep(), its preferred to use serialport.in_waiting which help to check the number of bytes available in rcv buffer.
So once there is some data is rcv buffer then only read the data using read function.
so following code sequence can be followed without having any delay
while True:
bytesToRead = port.in_waiting
print(bytesToRead)
if(bytestoRead > 0):
res = port.read(bytesToRead)
print(res)
port.reset_input_buffer()
# put some check or filter then write data on serial port
port.write(("time\r".encode()))
res = port.readline()
print(res)
I am taking a stab here: Your time.sleep(5) might be too long. Have you tried making the sleep really short, for example time.sleep(.300)? If the time data gets written back between the sop returns you will catch it before it gets merged with sop, but I am making an assumption here that it will send time data back, else there is anyway nothing more you can do on the server side (the python) code. I do believe it won't hurt to make the sleep less, it is anyway just sitting there waiting (polling) for communication.
Not having the having the same environment on my side, makes it difficult to answer, because I can't test my answer, so I hope this might help.
I'm trying to use hardware serial port devices with Python, but I'm having timing issues. If I send an interrogation command to the device, it should respond with data. If I try to read the incoming data too quickly, it receives nothing.
import serial
device = serial.Serial("/dev/ttyUSB0", 9600, timeout=0)
device.flushInput()
device.write("command")
response = device.readline()
print response
''
The readline() command isn't blocking and waiting for a new line as it should. Is there a simple workaround?
readline() uses the same timeout value you passed to serial.Serial().
If you want readline to be blocking, just delete the timeout argument, the default value is None.
You could also set it to None before calling readline(), if you want to have a timeout for openening the device:
import serial
try:
device = serial.Serial("/dev/ttyUSB0", 9600, timeout=0.5)
except:
#Exception handeling
device.flushInput()
device.write("command")
device.timeout=None
response = device.readline()
print response
I couldn't add a commend so I will just add this as an answer. You can reference this stackoverflow thread. Someone attempted something similar to your question.
Seems they put their data reading in a loop and continuously looped over it while data came in. You have to ask yourself one thing if you will take this approach, when will you stop collecting data and jump out of the loop? You can try and continue to read data, when you are already collecting, if nothing has come in for a few milliseconds, jump out and take that data and do what you want with it.
You can also try something like:
While True:
serial.flushInput()
serial.write(command)
incommingBYTES = serial.inWaiting()
serial.read(incommingBYTES)
#rest of the code down here
I'm using RS-232 port to communicate with KeithleyInstruments(SCPI Protocol) and have a problem.I can send the write command but when I send a query command it*s show the error below.
import visa
rm = visa.ResourceManager()
inst = rm.list_resources()
print inst
# print inst --> (u'USB0::0x05E6::0x2200::9060025::INSTR', u'ASRL1::INSTR', u'ASRL6::INSTR', u'ASRL7::INSTR', u'ASRL10::INSTR', u'GPIB0::16::INSTR')
keithleyInst= rm.open_resource('ASRL7::INSTR')
print keithleyInst.write("*rst")
print keithleyInst.write(":meas:temp?")
print keithleyInst.query(":meas:temp?")
Error:
pyvisa.errors.VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.
A query is a write and a read combined, so you only need the query, not the write.
If it still times out after removing the extra write, try setting a really long timeout like:
keithleyInst.timeout = 5000
To give it 5 seconds to respond. You can always shorten this once you've got it working.
If it still doesn't respond, perhaps the instrument is not sending the termination character that VISA expects.
Try communicating with the instrument with a terminal program or National Instruments' Measurement & Automation program to find out for sure what termination character it is sending (if it is sending anything).
You can change the termination character VISA expects by
keithleyInst.read_termination = '\r'
or something similar.
As Jeanne Pindar answered, this can be due to a delay in answering or a bad read termination. It can also be linked to the baud rate of RS232 devices. You can set it with :
inst.baud_rate = 11520
Look at your constructor datasheet to specify the correct baudrate.
The problem is, my script won't work (it's printing empty lane), but it works in python interactive console.
import telnetlib
tn = telnetlib.Telnet("killermud.pl", 4000)
data = tn.read_very_eager()
data = data.decode()
print(data)
tn.close()
What is the reason of such behavior?
I just took a look at the documentation for the read_very_eager method, which says:
Read all data available already queued or on the socket,
without blocking.
It is likely that at the time you call this method that there is no data "already available or queued on the socket", so you're getting nothing back. You probably want to use something like the read_until method, which will read data until it finds a specific string. For example:
data = tn.read_until('Podaj swoje imie')
According to tlnetlib documentation, Telnet.read_very_eager() Raises EOFError if connection closed and no cooked data available. Return '' if no cooked data available otherwise. Do not block unless in the midst of an IAC sequence.
If you do data=="", returns true, Therefore, it means that no cooked data is available
I have a fermentor (NBS BioFlo 3000) connected to a PC (Windows XP) via a RS232 cable. I have downloaded a free software (http://www.foxylogic.com) to monitor the fermentor.
It works, so I know for a fact, that the hardware, cable, etc, are good.
The free software is not open source, and is very old. I'd like to use pySerial to monitor the fermentor. I know the port is COM1, 8 bit data, even parity, baudrate=9600. A paper I saw (http://dx.doi.org/10.1371/journal.pone.0092108, supplement S1, page 2) says that I should be using the "AFS communication protocol" and that the string requesting information looks like:
(MD#)RA(CR)
where (MD#) is the number of the reactor (0 in my case) and (CR) is carriage return.
So based on that, I did, in iPython terminal:
import serial
ser = serial.Serial(0)
ser.parity = serial.PARITY_EVEN
ser.timeout = 1
print ser
I get: Serial<id=0x1976cb0, open=True>(port='COM1', baudrate=9600, bytesize=8, parity='E', stopbits=1, timeout=1, xonxoff=False, rtscts=False, dsrdtr=False)
ser.write('0RA\r')
print ser.read(9999)
..., and I get nothing at all - just an empty string. I tried to change the timeout (up to 15 s, and I know it cannot take longer that that), I also tried readline() and read(1), but I did not change any of the other parameters. I also tried to alter the string:
b'0RA\r'
'0RA\r'.encode()
'00RA\r'
'0RA\r\n'
'0RA\n'
'MD0RA\r'
'(0)RA\r'
'0ra\r'
and many others, I don't remember them all. Nothing works, I always get an empty string. No errors.The serial device is just completely silent.
The only time I get something else than an empty string is, when I ser.read(1) in a loop, no writing, and I physically turn the fermentor either off or on. I get one space.
I googled this extensively, but it appears I am dealing with quite a unique problem, so I don't expect to find a simple answer here. I can't test all the combinations of the strings and all the settings, so my question rather is:
Where do I start troubleshooting?
(my python is 2.7)
Thanks!
You start troubleshooting by checking if anything is actually being communicated. In Windows, utilities capable of this include PortMon from the Sysinternals suite and SerialMon.