Go Down

Topic: Data loss when sending to native USB port (SerialUSB) (Read 9 times) previous topic - next topic

PeterVH

Hi Stimmer,

I found kicking out the circular buffer a great demonstration "out of the box" thinking.

I have tested your implementation with ArduinoISP. I think this is a good real life use scenario of the serial port, with lots of messages of different sizes (though relatively small) in both directions. I powered my leonardo from the due's 3v3 and modified ArduinoISP to use SerialUSB instead of Serial. It worked well: I could upload download the bootloader to/from the leonardo several times.

Nevertheless dropping the serial buffer also has consequences for feeding the due lots of small messages. Each message is received in a separate bank and you only have two of them. Take for example this shell script:
Code: [Select]
n=0
while true; do

        echo "$n" > /dev/ttyACM1
        echo $?
        sleep 1
        let "n = $n + 1"
done


I ran this sketch on the due:
Code: [Select]
static const int led = 13;
static const int button = 3;

void setup() {
  // initialize serial:
  SerialUSB.begin(9600);
  Serial.begin(115200);
  pinMode(led, OUTPUT);     
  pinMode(button, INPUT);
  digitalWrite(button, HIGH);
}

void loop() {
  // if there's any serial available, read it:
  int i = 0;
  if (digitalRead(button)) {
    while (SerialUSB.available() > 0) {
      char c = SerialUSB.read();
      Serial.write(c);
      i++;
    }
  }
  Serial.print("i=");
  Serial.println(i);
  digitalWrite(led, HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
}


If you press the button for a few seconds, some of the messages are lost.
Odd enough the return code of echo is always 0.

I am not sure where the bytes get lost. And maybe it can be prevented with stty calls, but a circular buffer would prevent this. A circular buffer which you fill up with memcpy would also make sense as an implementation.




stimmer

Interesting - I am not losing any data with that script. What happens for me is that echo blocks until ttyACM1 accepts the data. I expect that there is some mysterious stty setting which controls this.

However, it isn't really the right way to use a serial port in a script. The echo command opens the serial port, writes to it, then closes it again each time it executes. That's not what you'd do in, say, a C++ program, where you'd open the serial port once, write to it periodically, and close it at the end of the program. To do this in a shell script you'd use a fifo or a fd, for example:
Code: [Select]

exec 3<>/dev/ttyACM1
n=0
while true; do

       echo "$n" >&3
       echo $?
       sleep 1
       let "n = $n + 1"
done

This doesn't lose any data for me either, and it buffers the data on the computer rather than blocking.

PeterVH

#17
Feb 04, 2013, 10:39 pm Last Edit: Feb 04, 2013, 10:41 pm by PeterVH Reason: 1
Quote
What happens for me is that echo blocks until ttyACM1 accepts the data.


Well, that is what I expected to happen for me too when I wrote the script. (And on another pc (linux 3.5 vs. 3.0.0)),  I did actually observe echo blocking). The point I wanted to make is that having no circular buffer, one could temporarily block a program on the pc.

But you are right. Closing and reopening the file every time causes the os to flush the file and this makes echo block. If a program would write to ttyACM1 in a normal way, the os would buffer the output... So it looks like we can indeed live without the buffer in the Due.


PeterVH

I read you have Albert's test running. Is it easy to test with SerialUSB?

stimmer

#19
Feb 05, 2013, 12:35 am Last Edit: Feb 05, 2013, 12:40 am by stimmer Reason: 1
Yes, Albert's program does work with my SerialUSB. In SimpleArduinoSerPro3 change "Serial." to "SerialUSB." in all 5 places. Then in setup()  after SerialUSB.begin(BAUD_RATE); add this line: delay(1000);
I'll have a think about buffers. I'm sure I could reintroduce a buffer with not too much loss of speed. But right now I am sick at the sight of USB code  :smiley-mr-green: So I'm going to take a break for a week or two and try some other projects which are more fun.

Go Up