Python script stops reading serial port after several days

Hi everyone!

I’ve got my BBB rev. C set up as a data logger for a serial data stream from an Arduino. It basically takes this data, uploads it to xively, and checks certain values for exceeded thresholds and sends an email if found. This works fine. However, after the script has been running for several days, it stops working. The script itself seems to continue running, but it stops acknowledging that it’s receiving any data or trying to upload to xively. If I ctrl+c out of the script and restart it, it starts working fine again. The device it’s connected to continues to work properly regardless of whether the BBB is logging anything, so I don’t believe that the problem is with it.

Is there any way to determine where the problem lies? (BBB, python, etc.?) Here’s a copy of my code (please don’t mock it too much, I’m a Python noob) :
http://susepaste.org/399d9d1f

(This is what the data looks like if it makes any difference:
2014-08-31 20:51:38.841985
91,h,44

2014-08-31 20:51:40.063139
92,t,72

2014-08-31 20:51:44.727206
92,h,42

2014-08-31 20:51:45.463794
90,t,71

2014-08-31 20:52:17.112091
90,h,44

…)

I’ve Googled around, and haven’t really found anything regarding something like this. There were a couple of random bulletin board posts that seemed similar, but they all went off into no-answer-land.

Thanks in advance :slight_smile:

Hi Chris,

I don't think the problem is related to the serial port itself. I have a python code that uses 4 serial ports of BBB (tty01, tty02, tty04, tty05) running without any problem for months.

I saw your code. If it reaches the "Dropping out due to an error: ", I don't think it will keep running.

Use the logging module to write to a file when there is an exception:
https://docs.python.org/2/howto/logging.html

Use repr() instead of the str() to show the error, as it "returns a string containing a printable representation of an object.", and it is easier to see what's wrong.
https://docs.python.org/2/library/functions.html#func-repr

If you catch the problem with the logging module, send an email and I can help you with more details.

Miguel

I think Miguel’s logging idea is the best way to know exactly what’s going on. Some additional thoughts:

Based on code, if your program stops receiving data but still runs then it is probably infinitely blocking at arduino.readline(). The fact that you don’t see output from “print(line)” or print str(LAST_UPDATED) further supports that. Perhaps there was a transmission error at some point and the two went out of sync(eg the stop bit is never detected)? When you restart the script(and re-establish the serial connection), things work fine.

You could try…
-Lowering the baud rate. You can check the AVR data sheet, but I think the Arduino’s error rate is higher for 115kbps than for say 9600bps. The frequency of your data(based on your sample) doesn’t necessarily require a 115kbps transmission rate.
-Adding a timeout to the serial.Serial() constructor. Then do something like:
while True:
line = None
line = arduino.readline()
if line is None:
arduino.close()
arduino = serial.Serial(…)
else:
#Do all the Xively/email stuff

(This is just a guess, since I don’t know exactly what timeout does: raise an error, returns “None”, returns junk? You’ll have to experiment.)

Hope that helps.

I should add that the timeout should be larger than the largest expected gap between each data transmission. For example if you expect data coming in every minute, then set the timeout to be 2 minutes. If no data comes in for 2 minutes, then you know something is wrong.

Good point. People from 3D printing word normally use 250Kbps because this
is fast and has lower error rate than 115Kbps for the crystal frequency
used on Arduinos. Although this data rate is not standard, newer kernels
and python support it very well. Sure that 3D Printers need faster
communication so 9600 is out of question that leads to choose non standard
data rates. It is more likely that Chris application will work well on
9600bps.

regards,
Benito