Receiving 2 Serial Ascii messages in a row

I know I will have 2 serial (ascii) streams coming from Serial1, first i'm expecting 13 numbers, and then the second stream is 111 numbers (1's or 0's as it happens but that doesn't matter).

I have a program that works fine, as long as it is assumed that nothing will be sent too early or late:

[code]

String inData = "";
String ms1 = "";
int A = 0;
char recieved = 'a';
int tick = 0;
int newtick = 0;
int done = 0;
void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial.println("Printing text messages...");
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(12, OUTPUT);
  ms1 = "";
  tick = 0;
  newtick = 0;
  done = 1;
}
void loop() {
  while (tick <= 12)
  {
    if (Serial1.available() > 0) {
      char recieved = Serial1.read();
      ms1 += recieved;
      tick = tick + 1;
    }
    // Process message when new line character is recieved
    if (tick == 13)
    {
      Serial.println("Message1: " + ms1);
    }
  }
  while (newtick <= 110)
  {
    if (Serial1.available() > 0) {
      char recieved = Serial1.read();
      inData += recieved;
      newtick = newtick + 1;
    }
    if (newtick == 111) {
      A = inData.length();
      Serial.println(A);
      Serial.println(inData);

      A = inData.length();
      Serial.println(A);
      Serial.println(inData);

      for (int i = 0; i <= A; i++) {
        //
        if (inData.charAt(i + 1) == '0') {
          digitalWrite(12, HIGH);
          //   Serial.println('1');
        }
        else {
          digitalWrite(12, LOW);
          //   Serial.println('0');
        }
      }
      newtick++;
    }
  }
  ms1 = "";
  tick = 0;
  newtick = 0;
  inData = ""; // Clear recieved buffer
}

[/code]

The problem is that, I could possbily start to read at a bad time, when old bytes are still being read, or before the device receiving things, has processed what it has to, which results in everything being out of time and not working correctly.

What I would like to do is to 'secure' this a little bit, so that the first message will never start unless it contains a '\n' at the start of the message being sent to Arduino (I can take care of that no problem) or something similar, and the second message too, or maybe you can recommend something helpful?

I have been trying to do this, but I am not sure if I am waiting for a string "\n" or a char '\n' or how exactly to receive the \n at the start of a serial message and ensure it does not leave the loop until the correct amount of characters has been received. I have seen many wrong ways of doing this. Any help would be appreciated.

check the tutorial, "serial input basics" in this forum

I have seen many wrong ways of doing this.

Not as many as we have.

2 Likes
String inData = "";
String ms1 = "";

While I have argued for years that "blocked" Strings work OK, random length Strings are not efficient. A char array of max length is a far better approach... use 2 arrays or a 2nd dimension to handle both serial channels.

// Process message when new line character is recieved
    if (tick == 13)
    {
      Serial.println("Message1: " + ms1);
    }

Serial print within your conditional check will to slow you down as it is blocking. Just set a flag and print char-by-char only when there is nothing in the serial inputs.

9600 BAUD is reasonably slow in terms of the uC's clock, but if you find that buffer overruns happen, You can double-buffer: Adafruit's GPS code is a great example of how to efficiently build a second buffer.
Or, not recommended for most coders: you could increase the core serial input length... several posts within the forum discuss that method.

Very old serial project may have something to steal :face_with_peeking_eye:

1 Like

Is your program going to do more things, later on? Right now, you have a lot of blocking code that will kill any chance of real time response to stimuli.

2 Likes

Yes, it is, but the rest of the code needs to wait on these messages.

Sorry, I thought I made that clear by stating that I definitely will receive 2 messages via serial.

You need to define a special format for your messages. It must contains a "preable" with unique byte sequence, that will help your program to determine a start of new message. And you need a trailing "suffix", perhaps with control sum, to be sure that the data received is valid.

All of this is described in Serial input tutorials

Also, if your messages composed by "1" and "0" only, perhaps you should to think about changing the text format to binary - your messages will became 8 times shorter

1 Like

have you consider using readBytesUntil()

yes, the first line may be incomplete

const byte PinLed = LED_BUILTIN;

void loop()
{
    if (Serial.available ())  {
        char buf [80];
        int n = Serial.readBytesUntil ('\n', buf, sizeof(buf)-1);
        buf [n] = '\0';

        digitalWrite (PinLed, atoi(buf)); 

        Serial.println (buf);
    }
}

void setup() {
    Serial.begin(9600);
    pinMode (PinLed, OUTPUT);
}
1 Like

I think it's just a coincidence that the character count happens to result in a number that is the same as the line-ending \0x0d, folks.
@matalog Your first message is 12 characters long, plus the line-ending x0D("new line character" reference in the comment), correct?
Then you have a decision to make. You really must monitor your input for that 0x0D, buffering the incoming characters up until that point; if you have the required 12 characters buffered at that point, then you know you can receive the next message, but
what if you have, for example, 10 characters when you receive the new line marker? Can you simply go back to waiting, ignoring the next message? Or are you dead in the water?

The first message is 13 characters. I am not using a end receiver marker, that is the point of what I am asking. I wait for any 13 characters and accept those currently.

How could you know that you received the data completely, if you not using start and end markers?

The problem is that, I could possbily start to read at a bad time, when old bytes are still being read, or before the device receiving things, has processed what it has to, which results in everything being out of time and not working correctly.

What I would like to do is to 'secure' this a little bit, so that the first message will never start unless it contains a '\n' at the start of the message being sent to Arduino (I can take care of that no problem) or something similar, and the second message too, or maybe you can recommend something helpful?

I have been trying to do this, but I am not sure if I am waiting for a string "\n" or a char '\n' or how exactly to receive the \n at the start of a serial message and ensure it does not leave the loop until the correct amount of characters has been received. I have seen many wrong ways of doing this. Any help would be appreciated.

Back to your problem statement. If you have no end marker, all you can do is loop indefinitely, waiting for that '\n' (it's a char) which you seem to think could start a serial message. Then grab your 13 bytes after that. Since you have no end marker, one missed character messes up your next message as well, but that's the protocol you've chosen. Serial is not a 'strong' communication method(no under the hood packetization, no error checking, etc), if you want any garbage protection you have to provide it.

I expect 13 digits, I get them. I expect 111 digits and I get them. I have a known amount of digits arriving, so I know if I have received a complete amount.

Except when there's a transmission error and one or more characters are discarded.

1 Like

You're expecting perfection, which is a perfect recipe for a futszup. You've been told, I'm done.

Transmissions errors are not the problem, as it is, my setup works without transmission errors, and they are not the subject of the question here. Did you read the whole thread?

You stated your problem and asked for solutions. When given several solutions, you decided to ignore them and ask for more solutions.

Saw it coming. But I waited for a response like this, before adding you to my permanent ignore list.

Enough to realize that you don't know what you're doing.

1 Like

Thanks for the helpful Replies. The serial tuturials on this forum are great.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.