2 2
Dmitry_

Problem with UART on Orange PI Zero

Recommended Posts

I have Orange PI Zero running the stable Ubuntu image. Kernel: Linux orangepizero 3.4.113-sun8i. I'm writing a python3 app to communicate with an Arduino using UART. The app works fine for a few hours and then it stops being able to send or receive commands to/from the Arduino.  Is there some known issue with the UART on OPI Zero? It looks like the file descriptor for the serial port becomes unavailable somehow.

Share this post


Link to post
Share on other sites

Simply, no. Not that I'm aware of.

I've personally tested onboard UART and over USB-OTG for days on end. I've not experienced any problems (that weren't of my own doing ;D) Then again, I'm also using a small heatsink and mini 5v fan.
What are you doing with OPi/Arduino? The reason I ask is because I've experienced 'drop outs' in connection over SSH/UART, etc... (which exhibit similar behavior to what little description you provide) as result of power for various reasons on OPi. 

  • Updating/installing/compiling large packages
  • High CPU usage
  • Poor power cable
  • Combination of the above + Heat

Are you cooling OPi at all? Heat is a known issue with OPi Zero. Provide logs and/or more description. ie: armbianmonitor -u

 

 

On 7/23/2017 at 8:53 AM, Dmitry_ said:

It looks like the file descriptor for the serial port becomes unavailable somehow.


Isn't convincing enough evidence for me to rule out:

  • Problem with UART, not necessarily "on Orange PI Zero."
  • Problem with the Arduino's communication to the UART

 

Share this post


Link to post
Share on other sites

 

On 7/26/2017 at 9:39 PM, StuxNet said:

Are you cooling OPi at all?

I have a small radiator and a 80mm fan connected to a separate 12v power supply. Also the CPU is under-clocked to 648Mhz.

 

On 7/26/2017 at 9:39 PM, StuxNet said:

Provide logs and/or more description. ie: armbianmonitor -u

https://paste.ubuntu.com/25211788/  - this is last 5000 lines of armhwinfo.log

 

My code looks something like this:

import threading
import time
import serial

class ArduinoConnector():
    def __init__(self, portName, baudrate):
        self._serial = serial.Serial(port=portName, baudrate=baudrate, xonxoff=False, rtscts=False, dsrdtr=False, timeout=0.001)
        self._readBuffer = bytearray()

        self._commRLock = threading.RLock()
        
        self._readingThread = threading.Thread(daemon=True,target=self._readingLoop)
        self._readingThread.start()
                                
    def _readingLoop(self):
        while 1:
            data = b''
            try:
                self._commRLock.acquire()
                data = self._serial.read(1000)
            except Exception as e:
                pass
                #write exception to log
            finally:
                self._commRLock.release()
            
            self._readBuffer.extend(data)
            #process data
            time.sleep(0.0001)

    def write(self, data):
        try:
            self._commRLock.acquire()
            self._serial.write(data)
        except Exception as e:
            pass
            #write exception to log
        finally:
            self._commRLock.release()

May be because I try to read from the com-port every 0.1ms it hangs somehow. It uses like 30% of 1 CPU. I'm trying to rewrite it with PyZMQ and gevent. Gevent has wait_read and wait_write function, those can block until there is actually something to read/write. It uses much less CPU this way.

Share this post


Link to post
Share on other sites

The way you are reading the serial port is ugly since you try to read(1000) without even checking if there is something to read, and yes 0.1ms is waste of time, especially if serial is empty, you should make it longer.

You should is serial.inWaiting() > 0 to check if at least one char has come in...

 

Share this post


Link to post
Share on other sites

@martinayotte, thank for the advice. Now that I look at it I can do read(1) without timeout and let the reading thread block until there is something to read.

Share this post


Link to post
Share on other sites
34 minutes ago, Dmitry_ said:

@martinayotte, thank for the advice. Now that I look at it I can do read(1) without timeout and let the reading thread block until there is something to read.

Good on ya for using try/except/finally however I believe this problem could have been avoided with a couple more. Since you try/finally it never errors out as it would if you ran the commands manually. It always has somewhere to go, which is what you need it to do. My suggestion is what I've learned from personal experience as a cowboy coder (take with grain of salt) is...

1: Always be cautious when using sleep() or other timeouts. It's best to start bigger in dev/testing and then push it to it's limits as it's proven to work. Sleeping and while loops can cause some weird things to happen depending on the application.

2: Do something with you exceptions! I see you except Exception as e  but I don't see you reference "e" anywhere. You've commented out "Write exception to log" so I'm sure you had good intentions but.... were going to do it. I prefer to let the script crash and write to a log. That way you get a better idea of what's going with the raw exception and know empirically something is up because your script isn't running anymore :P

Anyways, that's my 2 cents. Might not even be applicable since I can read your code but I'm not familiar with it. Regardless, I'd like to think it's still worth a whole 2 cents since they're lessons I've learned. Take care, good luck!

Share this post


Link to post
Share on other sites

I left it running for a few days and it hang up. It is not connected to network now and the only message I get on UART console is

Quote

[259303.810010] INFO: rcu_preempt detected stalls on CPUs/tasks:
[259303.810010]         3: (1 GPs behind) idle=cc1/140000000000000/0 
[259303.810010]         (detected by 2, t=20184807 jiffies)
[259303.810010] INFO: Stall ended before state dump start

Does someone knows what is it?

Share this post


Link to post
Share on other sites

My money is on one of the first things mentioned and suggested. An issue resulting from CPU usage. Especially since you've gone on to mention you've underclocked the CPU.

 

When you search for the first error (INFO: rcu_preempt detected stalls on CPUs/task) the first 3 results specifically apply to your situation! ie: real time applications, 1ms delay, etc... 


https://unix.stackexchange.com/questions/252045/rcu-preempt-detected-stalls-on-cpus-tasks-message-appears-to-continue

https://www.kernel.org/doc/Documentation/RCU/stallwarn.txt

This one (https://stackoverflow.com/questions/35401317/rcu-preempt-self-detected-stall-on-cpu-0) specifically mentions "continuous us[e] of CPU from a high priority thread for a long time"


Maybe I'm missing minutiae in regards to the "RCU CPU Stall Warnings" peppered throughout those results but again, i'd bet money on it.
Try not underclocking a board that has been known to drop out when the CPU load is pushed to it's max?

I highly recommend reading through the bullet points of the second link provided. It details potential causes "for RCU CPU Stall Warnings". Read through them and use them as diagnostics to your specific use case. See if you can get different results or change something. Respond back with your findings. With all due respect intended, if you don't do as suggested because the answer isn't a direct fix, you might as well not even be on the forum.

Share this post


Link to post
Share on other sites

@StuxNet, the CPU was underclocked to 480MHz at that time. I also tried to undervolt it to 1V but it did not work. It could not switch frequencies. I've changed it back to 648MHz and 1.1V and it works OK now. I also removed the timeout on read so the CPU usage is much lower now.

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
2 2