Serial communication: Strings and (long)integers

It took me some time to find a sketch that shows me how strings and integers can be communited to the Arduino Mega via the serial interface. I wrote a simple sketch showing how it works and maybe someone else can profit from it:

Upload the sketch and via the serial monitor you can send a message containing a 10 character string and a value. String is read until the first space or first 10 characters (what ever comes first), the value is read after the space until the new line character ('\n') or enter.

try sending the following via the serial monitor:

test 1234 (= string + integer)
test (= string only)
1234 (= integer only if you start with space)
1234 (= string as there is no leading space)

/*
 * Sample Serial Communication Sketch
 * By:   Rolf Bakker
 * Date: 20190507
 * 
 * This sketch demonstrates how to capture strings and (long) integers from the serial communication
 * 
 */

char inArr[11];                                                                   // container for 10 characters + "\0" ending character
long inInt;                                                                       // container for long integer

void setup(){
  Serial.begin(115200);                                                           // set serial speed
  Serial.setTimeout(1);                                                           // set time-out delay for readBytesUntil
  Serial.println("Arduino is ready");

}

void loop()
{
  while (Serial.available()) 
  {
    size_t bytes_read = Serial.readBytesUntil(' ', inArr, sizeof(inArr)-1 );      // read bytes until: space or time-out or max size of the array
    inInt=Serial.readStringUntil('\n').toInt();                                   // read long int from serial
    inArr[bytes_read] = '\0';                                                     // add ending character to the array
    String outStr(inArr);                                                         // convert array to string, just as an example
    Serial.print("Array  : ");
    Serial.println(inArr);                                                        // print the array received
    Serial.print("String : ");
    Serial.println(outStr);                                                       // print the string created from char array
    Serial.print("Value  : ");
    Serial.println(inInt);                                                        // print value received
    Serial.println();
  }
}

PS: I updated the code so the max time-out is 1ms for serial data to arrive.

  while (!Serial) {;}

Useless on a Mega :wink:

And you piked pretty much the most terrible name for your thread. It's pretty much the same as Robin2's excellent Serial Input Basics - updated. And this is nothing compared to that. You mix and match strings and Strings (why????) and rely fully on timeout to read data. Really not what you want. I suggest to have a look at Robin2's writeup :slight_smile:

To avoid confusion please revise the title of this thread

septillion:

  while (!Serial) {;}

Useless on a Mega :wink:

And you piked pretty much the most terrible name for your thread. It's pretty much the same as Robin2's excellent Serial Input Basics - updated. And this is nothing compared to that. You mix and match strings and Strings (why????) and rely fully on timeout to read data. Really not what you want. I suggest to have a look at Robin2's writeup :slight_smile:

Thx, I've updated the code

UKHeliBob:
To avoid confusion please revise the title of this thread

Thanks

UKHeliBob:
To avoid confusion please revise the title of this thread

Done

R4C3R:
Thx, I've updated the code

But what makes this special or useful even? It fully relies on the timeout and is blocking code.

@septillion

not sure what you mean by your remark:

The serial code is only processed when there is serial input waiting, if not the code continuous to process other code, I don't see any blocking code here. It is also not solely relying on timeouts, as it looks for a space or a new line to terminate. The 10ms timeout is only a last resort in case the space or new line are not found within the 10ms.

So, I fail to see the points that you are trying to make.

In my opinion the code is a nice and compact example that demonstrates how readBytesUntil and readStringUntil can be used in a sketch to read strings and integers from the serial interface.

R4C3R:
I don't see any blocking code here.

Look again. But now think of serial as the mailman who comes by once a day. Yes, compared to the rest serial is THAT slow :wink:

Aka, once you receive a single letter you keep waiting for some days until you receive the right letter or 10 weeks have passed.

R4C3R:
It is also not solely relying on timeouts, as it looks for a space or a new line to terminate. The 10ms timeout is only a last resort in case the space or new line are not found within the 10ms.

True, but are you always sending that? No. So yeah, you rely on the time out.

R4C3R:
So, I fail to see the points that you are trying to make.

My biggest point is the HUGE difference between teh Arduino speed and the serial speed which is causing the Arduino to do a lot of waiting.

R4C3R:
In my opinion the code is nice and compact example that demonstrates how readBytesUntil and readStringUntil can be used in a sketch to read strings and integers.

Can only agree on the compact and demonstration aspects. If you want nice you should not be using any of those methods :wink: Because they are blocking by design.

I think the code is a fairly common way of doing things on the Arduino.

Unless you use an interrupt for serial communication, the code will have to check whether there is serial data waiting to be processed.

And like I explained before the timeout is only a fall back. If the terminating characters are used, there is no waiting at all. If you want, the timeout can be reduced to 1 ms when using 115.200 baud.

In my opinion you are making a lot of fuzz about nothing, I don't find that very helpfull.

Thank you for changing the Title of this Thread.

...R

R4C3R:
Unless you use an interrupt for serial communication, the code will have to check whether there is serial data waiting to be processed.

That is quite true.

But because you are using readStringUntil() your program is also waiting for all the characters to arrive.

If you study the examples in Serial Input Basics you will see that the code checks to see if there is data waiting. If there is it collects whatever has arrived. And if the end-of-message has not yet arrived it allows the Arduino to go off and do other stuff. Next time round it checks again to see if more data has arrived. If the end-of-message has arrived it sets a flag so another part of the program can deal with the data.

...R

Prior to posting this post I read your post regarding Serial Input Basics. I find that your code is very robust and well written. Especially in the case of slow serial connections it will be very reliable as it patiently checks the serial interface for more data to arrive until the termination character arrives. This way, nothing gets lost.

Actually your posts triggered me to create this post as I was looking for examples that do make use of the readBytesUntil and readStringUntil functions that are available in the Arduino IDE. I predominantly use the serial communications between a linux server and an Arduino Mega and therfore my emphasis is not so much on slow serial connections. I've never experienced that the Arduino had to wait for the full string to arrive at the serial interface send by the linux pc at 115.200 baud.

The readStringUntil() in my code only waits when there is no termination character send with the string. Then and only then will it wait for another 1ms before continuing to process the consecutive code. (I've changed the code from 10ms to 1ms in the meantime). However, if the termination character is send the consecutive code is processed without delay.

So, the discussion here is about the potential 1ms delay in the case that no termination character was send with the string, which might be relevant for some Arduino users. In my opinion this is not an issue for most Arduino users, but I might be wrong.

In my view this post shows a relevant alternative solution and gives the Arduino users (like me) one more option to choose from with regard to Serial communications handling of strings and (long) integers.

R4C3R:
I was looking for examples that do make use of the readBytesUntil and readStringUntil functions that are available in the Arduino IDE.

Just because you CAN does not mean that you SHOULD :slight_smile: IMHO

...R

R4C3R:
In my view this post shows a relevant alternative solution and gives the Arduino users (like me) one more option to choose from with regard to Serial communications handling of strings and (long) integers.

In my view it's another crappy example that misleads beginners.

I was looking for examples that do make use of the readBytesUntil and readStringUntil functions that are available in the Arduino IDE.

NEVER use them or the other methods to this type

The only method of Serial that you need id read() (you do not need available() , peek() is worth a look).

each time loop is called

Read a byte (if available), process it and move on to allow the program to do what ever else it is required to do.

Mark

you do not need available()
Read a byte (if available)

At first sight these two statements appear to be mutually exclusive. I think that I have an idea of what you have in mind but you might like to expand on what you wrote for the sake of clarity.

read() returns an int not a byte -1 if no data so

i=Serial.read();
if (i != -1){
  do things with the data we have read!

}

Which is a touch faster than available/read as normally used

Mark

holmes4:
Which is a touch faster than available/read as normally used

I will stick with available() as it makes code easier to understand (IMHO).

...R

I agree with Robin2. In my opinion it would have been neater if read() would only return a byte anyway.