Errors in the data received through serial using Python - python

I want to send data to a peripheral using PySerial. However, errors sometime appear in the data received.
import serial
dongle = serial.Serial("/dev/ttyUSB0", 9600)
dongle.write("Some data\n")
And then, Some data\n is transmitted to the peripheral.
Sometime it works great, but sometime, errors appear in the data received: Somata\n, Som a\n, etc…
How to fix that issue?

I suspect you need to add an inter-char delay to your serial write. Unfortunately, such a thing is not available in PySerial. There is an inter_byte_timeout, but that's for reads.
Something like:
import serial
import time
def write_with_delay(command):
while len(command)>0: # Loop till all of string has been sent
char_to_tx = command[0] # Get a
dongle.write(char_to_tx)
command = command[1:] # Remove sent character
time.sleep(0.01)
dongle = serial.Serial("/dev/ttyUSB0", 9600)
write_with_delay('Some data\n')
Which will send the string with a 10ms (0.01s) delay between each character. Ordinarily, adding arbitrary delays into code is a bad thing, but for serial comms it is sometimes necessary.

Related

Detecting python serial read timeout or serial interruption

I am making a program to talk to a piece of serial equipment. The code I have so far allows me to talk to the device just fine. However I would like to have the program do alert the user if the link does dead, along with triggering a different section of code. Ideally I would like the code to be able to detect a interruption in any part in the transmission.
I intend to have this code used with kivy with a user interface to indicate link status.
I have read about people using threading, and I have tried making timers with threading. But I think it all just gets messy.
Thank you for any input.
import serial
import time
# lineread is the variable to store the data read from comport
# b"\x80" is the format to read and write hex values this = 80 in hex
SerialConfig = serial.Serial(port='COM5', baudrate=9600, parity=serial.PARITY_EVEN, timeout=.1) # comport configurations
def Start_loop():
while True: # loop forever
lineread = SerialConfig.read() # lineread variable is = to serial configurations reading from com port
if lineread == b"\x80": # wait for device to start handshake
SerialConfig.write(b"\x80") # reply to device with handshake
del lineread # clear lineread variable to wait for next value to come in
while True: # keep looping till
lineread = SerialConfig.read() # lineread variable is = to serial configurations reading from com port
if lineread == b"\x80": # if comport sees reply respond with the following lines
SerialConfig.write(b"\xA0")
SerialConfig.write(b"\x90")
print("handshake complete")

Why can't I read my data from my serial port?

Why is this code not working?
import serial
s = serial.Serial('/dev/ttyUSB1')
#s.open()
s.write(b"1234")
print(s.read())
print(s.read_all())
When I run this code, I get this output:
b'1'
b''
Since there is on Information about any device connected and the output is empty the second time I assume you need a delay or some kind of waiting in your code. This is because the machine you are running the python script on executes much faster than your baudrate of the serial device.
Try this for example:
import serial
import time
s = serial.Serial('/dev/ttyUSB1')
s.write(b'1234')
time.sleep(1)
print(s.read_all())

Pyserial can't read device

I'm trying to read data off of a sensor that I bought, using a conversion module (SSI to RS232). I have the module plugged into my Windows laptop via USB/serial converter.
When I use Putty in Serial mode, I can send the command $2RD and receive the appropriate response from the sensor unit. When I run a script to try to do the same thing, the unit returns: ''
Here is the code I am using:
import sys
import serial
import time
ser = serial.Serial(
port='COM4',
baudrate=9600,
timeout=1,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
)
while True:
ser.write('$2RD'.encode())
#time.sleep(1)
s = ser.read(26)
print s
A few other notes:
I've tried some variations using flushInput, flushOutput, sleeping, waiting, etc...nothing seems to help.
I know I have the COM ports right/the hardware all works in Putty, so pretty sure this is something with my code.
I've also tries 13,400 BAUD with no difference in outcome.
If I connect the TX and RX lines from the USB, I can read the command I'm sending...so it should be at least getting to the RS232/SSI conversion device.
s = ser.read(26) should probably be ser.read(size=26) since it takes keyword argument and not positional argument.
Also, you can try to set a timeout to see what was sent after a specific time because otherwise the function can block if 26 bytes aren't sent as specified in the read docs of pyserial :
Read size bytes from the serial port. If a timeout is set it may return less characters as requested. With no timeout it will block until the requested number of bytes is read.

Reset an open serial port

I am reading data from a serial port, sent by an arduino.
I have two files, which I use separately to write some code and try differents things. In one of them, I read the data and I draw it using a matplotlib figure. After I finish using it, it remains connected to my computer and sending data. So, what i need to do is to "reset" the port. This is, close the opened port and open it again, and stop it from sending data so I can use the arduino to try some modifications in the code of this file.
So to accomplish this, i mean, to reset the port, i created another file and wrote this code:
import serial
print "Opening port"
try:
serial_port = serial.Serial("com4", 9600)
print "Port is open"
except serial.SerialException:
serial.Serial("com4", 9600).close()
print "Port is closed"
serial_port = serial.Serial("com4",9600)
print "Port is open again"
print "Ready to use"
But this code does not seems to work.The port is still connected and sending data. So, it means that I can not close the port with my code,and then reopen it again.
What am i doing wrong? How can I stop the arduino from sending data? Or how can I reset thw arduino, maybe?
Hope you can help me.
----- EDIT -----
I accomplish to identify the real problem that i am having, and it is not what i thought. The problem was not that the port was open despite that i use the closefunction that Pyserial have. The real thing is that the port is closing as I want, but the device (the arduino) is still sending data. So, i changed the code to reproduce the situation.
This is the code:
print "Abriendo puerto"
ser = serial
try:
ser = serial.Serial("com4", 9600, timeout = 1)
serial_port = "Open"
print "The port %s is available" %ser
except serial.serialutil.SerialException:
print "The port is at use"
ser.close()
ser.open()
while ser.read():
print "Sending data"
ser.setBreak(True)
time.sleep(0.2)
ser.sendBreak(duration = 0.02)
time.sleep(0.2)
ser.close()
time.sleep(0.2)
print "The port is closed"
exit()
With this code, what i do is:
1) I open the serial port
2) If the device is sending data, I print "Sending data"
3) After 1 sec, I try to close the port and stop the device from sending data
I tried these last two thing with the close function to close the port, and reading the docs I tried with setBreak and sendBreak as you can see in the code above (i left them on purpose). But the device is still sending the data, which means that the code does not work.
So, is there a way to tell the arduino "stop sending data", or can i reset the device?
I do a very similar thing, two ways with success.
The first way is to let the Arduino send data continuously. The problem here is when your python code wakes up and starts to read from the serial port, the Arduino might be anywhere in its procedures. The simple solution is to modify the Arduino code to send some kind of "restarting" line. All your python code needs to do in this case is wait for "restart", then read real data until it again sees "restart". I had noisy lines so my code read (and parsed) through multiple cycles to make sure it got good data.
resetCount = 0;
while resetCount < 3:
line = s.readline().rstrip("\r\n")
if string.find(line, "restart") != -1 :
resetCount += 1
elif resetCount > 0 :
fields = string.split(line, " ")
dict[fields[0]] = fields
The second way is to implement a command-response protocol with the Arduino, wherein the Arduino sends data only when requested. In this case your python code sends a command to the Arduino ("RT" in the example below) and then reads data from the Arduino until it sees a "completed" line or it times out.
dict = {}
regex = re.compile('28-[0-9A-Fa-f]{12}') # 28-000005eaa80e
s = serial.Serial('/dev/ttyS0', 9600, timeout=5)
s.write("RT\n");
while True:
line = s.readline().rstrip("\r\n")
print line
if string.find(line, "completed") != -1:
break;
fields = string.split(line)
if (regex.match(fields[0]) != None and len(fields) == 4) :
dict[fields[0]] = fields
s.close()
It is possible that when you close the port, data is still coming from the arduino and being buffered by the operating system. There is a short delay between your script calling close() and the device driver actually shutting stuff down.
An immediate re-open may allow the driver to carry on without resetting its buffer. This is the device driver buffer, not the one seen by the Python serial port instance.
If you wait for at least a couple of seconds after the call to close() before you try to call open() then the behaviour should be as you hope.
I have just spent most of the day working out that this is what had been preventing my code from working properly.
I think you have to do a serial_port.open() immediately after creation to actually open the port.
It also looks like it just opens the port and exits if successful. Maybe I'm missing something here. I've never used pySerial, I'm just going by the docs.
Try using the handle to close the port instead of invoking the constructor again.
If you the port is open and you call serial.Serial("com4", 9600) it will attempt to re-open the port again and fail.
If serial_port was assigned successfully then serial_port.close() should close it.

Reading a Serial Port with Python. How does the buffers work?

I am just wondering how the buffers work on a com port.. The code below is a snip of how I am reading a com port. I am wondering if by doing serial_connection.close() and serial_connection.open() I would be losing any data, or would it remain in the buffer? You might ask why I am closing and opening the comport.. The reason being is that it is actually a virtual port and for what ever reason when I stay connected to it for a length of time data stops transmitting...
import serial
serial_connection = serial.Serial(
port = self.SERIAL_PORT,
baudrate = self.BAUD_RATE,
timeout = 10
)
while true:
serial_connection.close()
serial_connection.open()
line = serial_connection.readline()
print line
PySerial has a separate thread that sits there listening for data to make sure that nothing gets lost. However, the OS itself does not buffer data. There is a slim chance that you could lose some data for the brief period of time between when you close the port and open it again.

Categories