Serial Communications problem using Linux Kernel 4.10 and 4.12
Re: Losing communication with Roboclaw,TTL serial and Raspberry PI
@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" ?
- Basicmicro Support
- Posts: 1594
- Joined: Thu Feb 26, 2015 9:45 pm
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12
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).
I've updated the subject to reflect the information we do have(eg Linux 4.10 and 4.12 are having communications problems).
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12
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.
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12
I am very limited in time right now, but I am definitely interested if you start working in this direction?
- Basicmicro Support
- Posts: 1594
- Joined: Thu Feb 26, 2015 9:45 pm
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12
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.
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12
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:
Per the documentation,
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(...
--adjust this in roboclaw.py:
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)
This blocking call can be avoided if we set a write_timeout in the Serial constructor, like this: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.
Code: Select all
self._port = serial.Serial(port=self.comport, baudrate=self.rate,
timeout=1,
inter_byte_timeout=self.timeout,
write_timeout=10)
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
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
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12
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.
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.
- Basicmicro Support
- Posts: 1594
- Joined: Thu Feb 26, 2015 9:45 pm
Re: Serial Communications problem using Linux Kernel 4.10 and 4.12
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.