Difference Between Serial on Arduino 101 and Arduino Uno

Hello All,

I am experiencing different behavior when using the serial.available() function between Arduino Uno and Arduino 101 boards.

This is the code I am using

char incomingByte = 0;

void setup() {
Serial.begin(9600);
}

void loop() {

if (Serial.available() > 0)
{
// Read in the entire line of serial data received one byte at a time
while (Serial.available() > 0)
{
incomingByte = Serial.read();
}
// Print the bytes available and the last byte recieved
Serial.println(Serial.available());
Serial.print(incomingByte);
Serial.println("-");
}
}

What I expect to see is reading in one byte at a time, meaning I will only see that last byte read when I enter "12345" (What I see on the Arduino 101): Arduino_101.png (attached)

What I see on the Arduino Uno is that it skips right over the while loop: Arduino_Uno.png (attached)

Can someone explain what is going on here and how I can get my Uno to behave the correct way?

Any help is greatly appreciated!

Arduino_101.PNG

Arduino_1.PNG

I am setting them both to the same buad rate, is that possible?

That is what it looks like is happening though. If I put the print statement inside of my while loop like so:
if (Serial.available() > 0)
{
// Read in the entire line of serial data received one byte at a time
while (Serial.available() > 0)
{
incomingByte = Serial.read();
// Print the bytes available and the last byte recieved
Serial.println(Serial.available());
Serial.print(incomingByte);
Serial.println("-");
}
}

I get the attached output.

Arduino_101-inside_while_loop.PNG

Arduino_1-inside_while_loop.PNG

You could probably test Delta_G's theory by inserting a temporary delay in both codes at the same spot. See if you still get different results.

And I could be misunderstanding the issue.

I verified that if I remove the serial.read() line, that it loops the same for each (printing out 5 repeatedly as expected). Which would imply that it is indeed being read slower on the 101 board...

DangerToMyself:
You could probably test Delta_G's theory by inserting a temporary delay in both codes at the same spot. See if you still get different results.

Adding a delay(500) as shown below makes my Arduino Uno behave just like the 101, where I only get the last byte (the 5). I believe this confirms Delta_G's theory...

if (Serial.available() > 0)
{
// Read in the entire line of serial data received one byte at a time
while (Serial.available() > 0)
{
incomingByte = Serial.read();
delay(500);
}
// Print the bytes available and the last byte recieved
Serial.println(Serial.available());
Serial.print(incomingByte);
Serial.println("-");
}

I have been using the 101 mostly for my development and was suprised to find this issue when I programmed the code onto an Uno. Is this what should be expected from the Uno?

Thank you very much for your help!

Arduino_1_and_101_output.PNG

Edit: attached image is from when I removed the serial.read()

Delta_G:
Yes, this is exactly what you should expect from any board. It can only give you what it has received. It can't possibly know that there is more bytes that are going to come later.

The only reason it seemed to be working differently on the 101 must be because the 101 was slow.

I wish someone could explain what is causing the 101 to be "slow" compared to the Uno. According to the specifications, the 101 has twice the clock speed of the Uno...

Delta_G:
This actually comes up a lot on the forum and the answer is always the same. Your while loop to get the last byte is not going to work. If you want to wait until 5 bytes show up then you need

if (Serial.available() >= 5)

This is not my intent, this was just to demonstrate the difference in behavior.

Developing on the 101, this allowed me to parse a variable message inside of the while loop until the whole message was received. I will have to change the logic for it to behave the same on the Arduino Uno, which is surprising.

I can make it work either way, I just want to know why I have to rewrite my code going between boards.

I disagree that this is a design flaw since it works with the Arduino 101 hardware... but thanks for the condescending reply. It hasn't mattered if I sent 1 byte or 1000 bytes for over a year, I have not had an issue with this until moving to the Uno. Yes I can write the code in a more robust way that will work on both boards, I get it.

If we could focus on the issue I asked about I would appreciate it.

Here is a description of Serial.available from the Arduino web site:

Serial.available()
Description

Get the number of bytes (characters) available for reading from the serial port. This is data that’s already arrived and stored in the serial receive buffer (which holds 64 bytes).

According to this, the Intel Curie is receiving those bytes FASTER than the ATMega328 (reports 5 bytes on the first loop, where ATMega reports 1) somehow even though they are sent at the same speed and both boards are set to the same baud rate.

Looking at both board schematics, I see that processors are both directly wired to the DP/DM USB connection through a 22 OHm resistors and do not appear to have any buffer between them.

It's a looong time since I did any of this stuff, but isn't the Baud rate only concerned with the speed of the bits inside a byte, and the delivery of bytes is asynch (unless specifically noted as synchronous as in eg various IBM protocols of old)?

(Hence the need for start bits to get the bits synched inside the byte, where the gap between bytes is random.)

meltDown:
It's a looong time since I did any of this stuff, but isn't the Baud rate only concerned with the speed of the bits inside a byte, and the delivery of bytes is asynch (unless specifically noted as synchronous as in eg various IBM protocols of old)?

(Hence the need for start bits to get the bits synched inside the byte.)

Yes I would agree with that, but these are both on the receiving side and receive from the same source.

It read to me that you expected characters to arrive at the same speed for the same Baud rate, ie that the inter-character timing depended on Baud, not simply the intra-character timing.

meltDown:
It read to me that you expected characters to arrive at the same speed for the same Baud rate, ie that the inter-character timing depended on Baud, not simply the intra-character timing.

I am sending them in a continuous stream, but have not verified they are spaced exactly the same intrabyte as interbyte. From my experience, this is the case for a continuous stream of bytes. You get a stop bit, then a start bit right after until the stream is done.
*I will measure this tomorrow to verify.

I imagine the Intel Curie probably has a much faster ISR for moving the bytes into this 64 byte buffer than the ATMega328. Just a theory, is there any way to test or verify this? Any other suggestions are welcome.

Delta_G:
What is your definition of "right after". At 9600 baud how long is that? Hint: It's a virtual lifetime to one of these processors.

9600 baud with 8 bites per byte, 1 stop, 1 start, no parity is 1.04ms per byte (104us per bit). So there are 104us from the time the stop bit edge and the next start bit edge which is 1664 clock cycles at 16MHz. Sure... a "lifetime" in processor time...Great! That doesn't explain how one device can move them into a buffer faster than the other.

Also, this would imply somehow my Curie processor that is TWICE AS FAST is not able to process my code as fast as the Uno? It is the same exact code... I am not servicing any extra peripherals.

Here is the scope shot of the bytes coming in just as I expected one after the other (attached).

Delta_G:
You can test this. Send more than 5 bytes. Keep increasing. You'll find the point where it stops working out for you.

I sent up to 117 bytes at once (123456789 13 times) and did not have it fail. I am not going to "go to the point where it stops working" because that seems pretty obscure for my usage beyond this point.

See attached.

  • Edit: I also copy pasted well past 256 bytes (just held down paste) and made sure to put a marker AA at the beginning and BB at the end and they all came through without missing bytes. The highest I saw Serial.available() respond was 255.

Delta_G:
OK, go look at the serial class for the 101. Maybe it has some code to stop and wait for another byte for a while or something.

Can you explain where I can find this? I was not aware that the 101 and Uno use a different serial class.

Delta_G:
Try reading micros in those loops and printing it at the end. Be careful not to affect the timing too much with the prints. See what the time is from the first byte to the last byte.

Here is the print out from sending 270 characters (0123456789 x 27).
Columns A-D are running the following with a print of micros inside the while(serial.available()) loop:

void loop() {

if (Serial.available() > 0)
{
while (Serial.available() > 0)
{

incomingByte = Serial.read();
Serial.println(micros());
}
}
}

The delta column is the difference in micros between each print. Rows 9-35, 41-91, and 101-269 are hidden to show all of this in a single screenshot, but resemble the same as what is shown.

I notice that the Uno only gets 97 of those characters while the 101 gets all 270.

Columns F-I are from running the following code with a print outside of the while(serial.available()) loop:

void loop() {

if (Serial.available() > 0)
{
Serial.println(micros());
while (Serial.available() > 0)
{

incomingByte = Serial.read();

}
Serial.println(micros());

}
}

Here I take the difference between the first and last only time in the delta column.

Here is a similar test but instead printing every value:

if (Serial.available() > 0)
{
Serial.println(micros());
// Read in the entire line of serial data received one byte at a time
while (Serial.available() > 0)
{
// Print the bytes available and the last byte recieved
//Serial.println(Serial.available());
incomingByte = Serial.read();
Serial.print(incomingByte);
Serial.print(",");
Serial.print(micros());
Serial.println(",");
}
}