Serial Input Char - String

Hi all,

I need to read bytes from Serial, store them in an array and then print them when there's no incoming

bytes.

char inData[20]; // Allocate some space for the string
int inChar; // Where to store the character read
byte charIndex = 0; // Index into array; where to store the character
boolean okPrint;
void setup()
{
 Serial.begin(115200);  
}


void loop()
{

  while(Serial.available() > 0) // Don't read unless
                                                 // there you know there is data
  {   
      if(charIndex < 19) // One less than the size of the array
      {
          inChar = Serial.read(); // Read a character
          inData[charIndex] = char(inChar); // Store it
          charIndex++; // Increment where to write next
          inData[charIndex] = '\0'; // Null terminate the string
      }
      okPrint == true;
  }
  // Now do something with the string (but not using ==)

//Serial.println(String(inData)); // Print the string but only once
  
}

Need help :o

Thanks

What exactly is your problem? Does your code not work? What did you expect, what did you get?

DCloud:
Hi all,

I need to read bytes from Serial, store them in an array and then print them when there's no incoming

bytes.

After how long? If there is a gap of one serial bit period between characters, you want to print everything? Or a defined number of seconds or...?

Hi guys,

i.e. if I put into the Serial monitor "12345678", I want to store the single char '1', '2'..etc into a char array,

because I need the single chars later, and I want to print the complete string "12345678" only once.

Hope is more clear

Thanks

Record the time you last received a character.
If the time now minus that time is greater than some threshold, print the string.

Hi AWOL,

Sorry, don't understand ::slight_smile:

What don't you understand?

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data.

I suspect the 2nd example does exactly what you want.

...R

Hi Robin2,

yes, 2nd example does almost exactly what I need; it works if the char endMarker = '\n'; but what if I send

data without '\n' ? Is it possible to receive data without the new line char?

Thanks

Yes it's possible, but more complicated. Why do you not want to use a character as an end-marker?

if you really don't want to use an end-marker then you need to have a variable that gets updated with the value of millis() as each character is received. If no characters come the value won't change and eventually a test such as

if (millis() - lastCharacterMillis > waitMIllis)

will be true and you can assume you have the whole message.

You will need to choose a value for waitMillis that makes sense for your application.

...R

I can't use an end line character because I'm receiving data from another board which does not send end

character, and I cannot change this.

Do I have to replace the while loop with the if (millis() - lastCharacterMillis > waitMIllis)..etc?

Thanks

DCloud:
I can't use an end line character because I'm receiving data from another board which does not send end character, and I cannot change this.

Maybe there is some other character that can be used to identify either the start or end of a message? Post some examples of typical messages.

Do I have to replace the while loop with the if (millis() - lastCharacterMillis > waitMIllis)..etc?

That does not sound at all correct.

Try this in place of recvWithEndMarker()

void recvWithTimeout() {
    static unsigned long lastCharMillis = 0; 
    unsigned long waitForCharMillis = 1000;  // allow a 1 second gap before giving up
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
   
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();


        receivedChars[ndx] = rc;
        lastCharMillis = millis();
        ndx++;
        if (ndx >= numChars) {
            ndx = numChars - 1;
        }
        if (millis - lastCharMillis >= waitForCharMillis) {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
}

I have not tested it but it should give you the flavour of what needs to happen

...R

Tidying things up then guys, here's my interpretation.......:slight_smile:

char inData[20];
uint8_t charIndex = 0;
uint8_t numChars = 19;
uint32_t lastCharMillis = 0;
uint8_t wait = 20;
bool okPrint;

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


void loop() {

  while (Serial.available())  {
    char inChar = Serial.read();
    inData[charIndex++] = inChar;
    lastCharMillis = millis();
    okPrint = true;
    if (charIndex >= numChars) charIndex = numChars - 1;
  }

  if (millis() - lastCharMillis >= wait && okPrint == true) {
    inData[charIndex] = '\0';
    charIndex = 0;
    Serial.print("The Input string was: ");
    Serial.println(inData);
    okPrint = false;
  }
}

indev2:
Tidying things up then guys, here's my interpretation.......:slight_smile:

I do hope that does not refer to my examples.

...R

Robin2:
I do hope that does not refer to my examples.

...R

?

@Robin2

The OP's subject matter was of interest to me...

DCloud:
Hi all,

I need to read bytes from Serial, store them in an array and then print them when there's no incoming

bytes.

Need help :o

Thanks

Your example was near the mark, but full of errors. Granted...

I have not tested it but it should give you the flavour of what needs to happen

...R

So I worked on something that is tested and does work :slight_smile: and does exactly as the OP's first question

indev2:
Your example was near the mark, but full of errors. Granted...

I am not surprised if there are errors. Perhaps you would be kind enough to point them out for me.

...R

Robin2:
I am not surprised if there are errors. Perhaps you would be kind enough to point them out for me.

...R

Seriously?

unsigned long waitForCharMillis = 1000;  // allow a 1 second gap before giving up

A 4 byte long for a value of 1000 ?

A second of time is ambiguous anyway, one could send hundreds of data sets in that time. The point is to get things done accurately in the shortest possible time, in fact my example of 20 milliseconds is probably way too long as well :slight_smile:

char endMarker = '\n';

Well?

    while (Serial.available() > 0 && newData == false) {

Assumes, bool 'newData' is declared elsewhere?

indev2:
Seriously?

Most definitely. When I get things wrong I like to correct them.

unsigned long waitForCharMillis = 1000;  // allow a 1 second gap before giving up

A 4 byte long for a value of 1000 ?

It avoids confusion and silly and obscure errors if all values associated with millis() are unsigned long

A second of time is ambiguous anyway, one could send hundreds of data sets in that time. The point is to get things done accurately in the shortest possible time, in fact my example of 20 milliseconds is probably way too long as well :slight_smile:

I agree that 1 second is a long time. I put that in to provoke a response from the OP who had not explained in sufficient detail what he wanted to happen. And if the person doing the typing was hesitant, you might need 1 second, or even longer.

char endMarker = '\n';

Well?

I agree, that line could have been deleted - but it won't do any harm. It is a hangover from the version recvWithEndMarker().

    while (Serial.available() > 0 && newData == false) {

Assumes, bool 'newData' is declared elsewhere?

It is. Just look at my complete example.

Thank you for your interest. I am pleased to see that my code was not "full of errors"

If you are wondering why I structured the examples the way I did, rather than put everything in loop() as you did in Reply #12 then have a look at Planning and Implementing a Program. Even for a small program it is a good idea to use functions. Small programs often expand into bigger programs. And when you have a function that has been tested and is know to work you can just copy and paste it into another program.

...R

"Full of errors" is a BS statement.
Serial Input Basics is one of the most useful tutorials on the forum.
Thank you Robin2.

Not byting :slight_smile:

In the spirit of the other thread of a similar subject, here's a better solution which misses nothing of the OP's original needs :slight_smile:

char inData[20];
uint8_t charIndex = 0;
uint8_t numChars = 19;
uint32_t lastCharMillis = 0;
uint8_t wait = 20;
bool okPrint;

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


void loop() {

  while (Serial.available())  {
    char inChar = Serial.read();
    inData[charIndex++] = inChar;
    inData[charIndex] = '\0';
    Serial.print(inChar);
    lastCharMillis = millis();
    okPrint = true;
    if (charIndex >= numChars) charIndex = numChars - 1;
  }

  if (millis() - lastCharMillis >= wait && okPrint == true) {    
    Serial.println();
    charIndex = 0;
    okPrint = false;
  }
}