Serial Communications problem using Linux Kernel 4.10 and 4.12

General discussion of using Roboclaw motor controllers
gdoisy
Posts: 33
Joined: Tue Oct 18, 2016 7:53 am
Re: Losing communication with Roboclaw,TTL serial and Raspberry PI

Post by gdoisy »

@IMC Support: Now that the issue is confirmed by at least 2 persons, shouldn't the title of the topic be changed to something like "Linux kernel 4.10 and above breaks roboclaw python library" ?
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12

Post by Basicmicro Support »

Currently we dont know if it is breaking the roboclaw library or a library the roboclaw uses(pyserial) or is a uart/CDC driver problem in Kernel 4.10 and possibly 4.12.

I've updated the subject to reflect the information we do have(eg Linux 4.10 and 4.12 are having communications problems).
robof
Posts: 36
Joined: Tue Jun 27, 2017 11:21 pm
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12

Post by robof »

Does anyone have any idea how hard it would be to convert the arduino c++ roboclaw library to use the correct serial headers/functions to try this in Ubuntu? I've not coded much in c++ in around 10 years so not sure how feasible this is to try to compare to the pyserial library. It seems like it should be straight forward though.
gdoisy
Posts: 33
Joined: Tue Oct 18, 2016 7:53 am
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12

Post by gdoisy »

I am very limited in time right now, but I am definitely interested if you start working in this direction?
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12

Post by Basicmicro Support »

The arduino C++ library was rewriten a while ago to take a Software or Hardware Serial object. This means the vast majority of the C++ library is portable C++. In fact if you create a class that mimics the Serial object from arduino you would probably not need to make any changes to the Roboclaw C++ code at all.
robof
Posts: 36
Joined: Tue Jun 27, 2017 11:21 pm
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12

Post by robof »

I haven't tried to do anything with the c++ here, but I have been digging more into the python library.

I have found that pyserial (serialposix.py) is hanging on write on this line:

Code: Select all

abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None)
Per the documentation,
select.select(rlist, wlist, xlist[, timeout])

This is a straightforward interface to the Unix select() system call. The first three arguments are sequences of ‘waitable objects’: either integers representing file descriptors or objects with a parameterless method named fileno() returning such an integer:

rlist: wait until ready for reading
wlist: wait until ready for writing
xlist: wait for an “exceptional condition” (see the manual page for what your system considers such a condition)

Empty sequences are allowed, but acceptance of three empty sequences is platform-dependent. (It is known to work on Unix but not on Windows.) The optional timeout argument specifies a time-out as a floating point number in seconds. When the timeout argument is omitted the function blocks until at least one file descriptor is ready. A time-out value of zero specifies a poll and never blocks.
This blocking call can be avoided if we set a write_timeout in the Serial constructor, like this:

Code: Select all

self._port = serial.Serial(port=self.comport, baudrate=self.rate,
                                       timeout=1,
                                       inter_byte_timeout=self.timeout,
                                       write_timeout=10)
I tried with a write_timout of 1 and even 10 and with both I still eventually had a timeout error (which makes sense since before it was blocking forever), but now I have no blocking beyond the timeout period and eventual error. So I just took this as an opportunity to wrap the roboclaw self._port.write() command in a while loop with a retry option to just attempt the command again. So ever so often it will timeout, reattempt write, and carry on.
This probably isn't the most elegant solution, but will have to do for me for now. I just hope there are no adverse effects from this hack.

If anyone can offer some tips to improve this, or if you want to dig more into why it's timing out, I would be glad to hear your feedback.

If you want to test this:
--add this function to roboclaw.py:
----and update all calls to
--------self._port.write(...
-----------with
--------self._port_write(...

Code: Select all

    
    def _port_write(self, bytes, retry_count=1):
        try_count = 0
        while try_count <= retry_count:
            try:
                self._port.write(bytes)
                break
            except:
                # We probably don't need a 10ms sleep to clear buffer
                # since the timeout itself should have been enough time.
                try_count += 1
--adjust this in roboclaw.py:

Code: Select all

    def Open(self):
        try:
            # I think current roboclaw.py is setting param
            # interCharTimeout instead of newer inter_byte_timeout that
            # I'm using in python3, so adjust as needed.
            self._port = serial.Serial(port=self.comport, baudrate=self.rate,
                                       timeout=1,
                                       inter_byte_timeout=self.timeout,
                                       write_timeout=0.02)
        except:
            return 0
        return 1
gdoisy
Posts: 33
Joined: Tue Oct 18, 2016 7:53 am
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12

Post by gdoisy »

Thanks for sharing.
I will wait a bit and if you don't report an issue with your solution i will use it. I already have several machine which updated automatically to the next kernel and it starts to be a real issue in our case.
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12

Post by Basicmicro Support »

Interesting. I've never had a write timeout problem before, so we didnt implement any kind of timeout for writing(just reading) in the library. I honestly didnt think it was even possible(and it may only be possible with USB virtual serial ports). Your solution is probably at least as good as what I would implement. It will be a little while before we can update this in the roboclaw.py library but it will probably end up looking very similar. I'll have to go through the structure to see if there isnt a better option but I cant think of one off the top of my head.

Post Reply