3

I am using a USB-to-serial adapter to let the Raspberry Pi talk with some motor controller through the serial bus.

I made the following Python script:

#!/usr/bin/ipython

import serial
import time

ser =serial.Serial(
    port='/dev/ttyUSB0',
    baudrate=115200,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    writeTimeout = 0,
    timeout = 10,
    rtscts=False,
    dsrdtr=False,
    xonxoff=False)

print("Port " + ser.portstr + " opened : " + str(ser.isOpen()))

time.sleep(5)

bytesToRead = ser.inWaiting()
print ser.read(bytesToRead)

ser.close()

The first time the code is executed everything works and gives the following expected answer:

>>>    pi@raspberrypi ~ $ sudo ./Work/Tests/Test_Serial_1.py
>>>    Port /dev/ttyUSB0 opened : True
>>>
>>>    ReceiveMessage: CanInID = 2, CanControllerID = 1, CanBroadcastID = 0
>>>
>>>    ReceiveMessage: CanInID = 2, CanControllerID = 1, CanBroadcastID = 0

The problem is now that if I directly re-run the script, I get the following incoming messages:

>>> pi@raspberrypi ~ $ sudo ./Work/Tests/Test_Serial_1.py
>>> Port /dev/ttyUSB0 opened : True
>>> wĸ7�a)�    �7ę

The only solution is then to reboot the Raspberry Pi. I tried unplugging/replug the USB-to-serial adapter, but nothing changed.

It is like if the baud rate were wrong the second time, but the connected devices are exactly the same.

My setup is Raspberry Pi 2, Linux raspberrypi 4.1.10-v7+, and the USB-to-serial adapter is there.

How can I fix this problem?

  • Electrically did you check the connections fist ? Like common ground etc... – user36435 Nov 4 '15 at 11:06
  • Yes everything is fine from this side, and the fact that the first attempt works confirm it. Thanks though – Adrien Nov 4 '15 at 11:13
  • I've faced the similar issue in the past, ie, serial works fine in the first try but as soon as I close the connection, it stops working and have to reboot every time to get it working. I somehow managed it by avoiding USB serial and using Rpi in-built serial port (/dev/ttyAMA0) but it is very likely that PySerial could be responsible for this. You can use serial C program to see if it's happening. If problem continues, it could be more deeper issue. Hope it helps. – dhruvvyas90 Nov 4 '15 at 11:33
  • Thanks a lot for this very interesting feedback! I will test as you suggested in C and if it work normally I'll try to report and hopefully get python-serial fixed. I was not using the built in serial port as it is not the same voltage level as the raspberry... It definitely helped :) – Adrien Nov 4 '15 at 14:26
  • 1
    After doing the same in C with this library, it is working without problem. The python-serial is thus the issue. – Adrien Nov 4 '15 at 14:49
3

As mentioned in the comments above, the use of this C library solves the problem.

However, as I don't want to switch to C I will not accept it as an answer for now.

EDIT: There is the solution:

pip uninstall pyserial
pip install "pyserial==2.5"

Thanks @MartinHjelmare on github

2

I've noticed the same issue using python to read Arduino serial output. If I use a Tcl script or the 'screen' application then the output is a stream of numbers as expected. However, when using Python - the first attempt works normally but subsequent runs of the application output incorrect data.

The fault seems to be that pyserial since 2.5 only applies the termios settings if they are going to change. Unfortunately for some serial devices this seem cause this fault. Modifying pyserial's serialposix.py file to always make the tcsetattr call and apply the calculated flags resolves the issue. ALternatively setting either the bytesize or parity flags to something other than the defaults causes pyserial to make the call to tcsetattr and fixes this issue.

Some demo code is posted below. The Arduino device is configured as per the default to emit 8 bit bytes with no parity and 1 stop bit. We can force an application of the terminal settings by setting the parity to something other than the default (eg: odd) and then resetting it back to 'none'.

This problem may well be dependent on different USB serial chipsets. Using a device with an FTDI FT232 chip did not demonstrate this but using a CH340G chip (as seen commonly on clone Arduino devices) did reproduce the fault.

Demo Arduino program:

#include <Arduino.h>

static unsigned long counter = 0;

void setup() {
    Serial.begin(19200, SERIAL_8N1);
}

void loop() {
    Serial.print(counter++, HEX);
    delay(1000);
}

Demo python reader:

import sys, serial
def main():
    s = serial.Serial('/dev/ttyUSB0', 19200)
    s.parity = serial.PARITY_ODD # work around pyserial issue #30
    s.parity = serial.PARITY_NONE
    try:
        while True:
            d = s.read()
            sys.stdout.write("%s" % d.decode('ascii'))
            sys.stdout.flush()
    except KeyboardInterrupt as ke:
        pass
    s.close()

main()

Update

A fix for this problem has now been committed to pyserial.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.