Reputation: 5618
I have an Arduino Uno which is printing data through a usb cable at /dev/cu.usbmodem1421
. The program simply prints out analog data values. I'm trying to parse the data with the following:
while read line; do
# parse the data line for line
done < /dev/cu.usbmodem1421
For some unknown reason, that file always seems to print out some random numbers when you cat
it, then pauses a second and starts displaying accurate ones.
Here's an example:
$ cat /dev/cu.usbmodem1421
518,518
518,519
518,518
518,518
518,519
519,518
519,518
518,519
518,518
519,518
518,519
518,519
518,518
518,519
518,518
518,519
518,518
518,518
518,519
519,518
519,518
518,519
518,518
519,518
518,519
518,519
518,518
518,519
518,518
518,519
518,518
Those numbers were printed out immediately. Here it pauses for a moment, and then starts slowly printing out these (one line per 100ms, as expected):
1023,520
1022,576
1023,520
928,65
560,0
414,0
96,377
193,720
467,803
967,678
1022,519
1023,459
830,1
518,0
289,193
23,657
251,987
518,1023
715,1022
838,923
953,713
1022,520
1023,424
518,518
518,519
518,518
These numbers are correct. How do I tell my script to discard the incorrect output? The amount of incorrect lines varies, but they always print immediately and the correct ones always follow about 0.5 seconds after.
Upvotes: 0
Views: 48
Reputation: 123470
This appears to be a bug in your Arduino code.
You're assuming that data written to the serial port when no one's listening will just disappear, so that anyone who starts reading will get freshly sampled data at 100ms intervals.
Instead, the device gradually fills a send buffer (256 bytes, by the looks of it). When you start reading, you will just get the backlocked send buffer before you get any fresh data.
If you want to work around it on the PC side, you can just read for a bit as you suggest to empty out the buffer:
{
# Read and discard for a second
timeout 1 cat > /dev/null
# Read the rest of the line, in case we stopped in the middle of one
read _
# Data should now be reasonably fresh
while read line; do
: # parse the data line for line
done
} < /dev/cu.usbmodem1421
This uses the timeout
program which may or may not be available on your OS. Alternatives include cat > /dev/null & sleep 1; kill $!;
Upvotes: 1
Reputation: 1
I would code the program in some better language (like Ocaml or C). You might want to use poll(2) if you need to wait for some (multiplexed) input or output...
As a kludge, you could put a sleep 0.3
before your read
in bash, e.g.
while sleep 0.3 && read line; do
but you really should code otherwise.
You probably need to debug your application running in the Arduino. I guess the bug is in the Arduino.
Upvotes: 0