Need help in reading and parsing serial data?

Hi there,

Im very new at this arduino world, i have knowledge in PICS and Pic basic Pro im starting sow please give me a hand.

What i want to do is ex: on arduino ide serial terminal send “1234;5678” and de arduino see if the 1st four numbers (or somw letters) are 1234 in this case and then read the next four after the “;”
My code have a problem if a put the god “pass” “1234;tefi” it woks god but when i put a rwong pass like example “e3r5;tec8” and after put the god one “1234;ehf6” it stops working !!

Please see my sample code and help me.

Thankz

char pass [5];
int data; 

void setup()
{
  //Create Serial Object
  Serial.begin(9600);
  Serial.println("ARDUINO ON!");
}

void loop() {
  
 if (Serial.available() >8) { //assumir que o outro byte vem a caminho. 
    for (int i = 0; i<4; i ++) {
      pass[i] = Serial.read();
    }
    pass[4] = '\0'; //end string
    if ((strcmp(pass, "1234") == 0) && (Serial.read() == ';')) {//equal and the separator is good
  
       for (int i = 0; i< 4; i++) {
           pass[i] = Serial.read(); } //get the number. 
       data = atoi(pass); 
       Serial.println("PASS OK!");
       Serial.println(data); 
    } else {
       Serial.println("FAIL");
        }
   }  
}

The problem is that you do not clear the rest of the "wrong" command. You should introduce a command-end character, such as newline ('\n'), and read characters until that character is seen after the parsing code.

  if (Serial.available() > 8) {
    ...
    do all your stuff
    ...
    /* now, read all incoming data until end-of-command, so you know the next character will be the start of a new command */
    while (true) {
      if (Serial.available() > 0 && Serial.read() == '\n') {
        break;
      }
    }
  }

Hi,

First thanks for the help, your code works god except for this situaction if a send the god or wrong pass with out the command-end character “1234;5678” the god one and “2233;5678” the bad next time that i send them with command-end character “1234;5678t”(i have change the command-end character for “t” leter)dont work i need to send a secund time the “1234;5678t” to get "PASS OK! from arduino! any ideas how to solve it?

Thanks

char pass [5];
int data; 

void setup()
{
  //Create Serial Object
  Serial.begin(9600);
  Serial.println("ARDUINO ON!");
}

void loop() {
  
 if (Serial.available() >8) { //assumir que o outro byte vem a caminho. 
    for (int i = 0; i<4; i ++) {
      pass[i] = Serial.read();
    }
    pass[4] = '\0'; //end string
    if ((strcmp(pass, "1234") == 0) && (Serial.read() == ';')) {//equal and the separator is good
  
       for (int i = 0; i< 4; i++) {
           pass[i] = Serial.read(); } //get the number. 
       data = atoi(pass); 
       Serial.println("PASS OK!");
       Serial.println(data); 
    } else
    {
       Serial.println("FAIL");
       }
        while (true) {
      if (Serial.available() > 0 && Serial.read() == 't') {
        break;
      }
    }
      }   

           }

if a send

What are you using to send the data? If you are using the serial monitor, set the option to append a carriage return/line feed, and expect that as the end-of-packet marker. That way, you can't forget to send it.

1234;5678t

is not 8 characters. It is 10!

PaulS:

if a send

What are you using to send the data? If you are using the serial monitor, set the option to append a carriage return/line feed, and expect that as the end-of-packet marker. That way, you can't forget to send it.

1234;5678t

is not 8 characters. It is 10!

Now im using the the serial monitor but later i will use other devices...

If i change "if (Serial.available() >8)" to if (Serial.available() >10) the first time that i send the pass dont work need to send it one time more

You are saying that you first send a command without end character, and then send the command again, and then it doesn't work? That's expected. The code will believe that everything up to the first end character is part of the first command. It can't magically "know" what you "intend" -- the command end character is the only way it can know, so you have to send that. Another way of implementing your code would be to read data into a buffer, and then parse the command once you have the end character.

char buf[100];
int bufPtr = 0;
void loop() {
  ...
  if (Serial.available()) {
    char ch = Serial.read();
    if (ch == END_CHARACTER) {
      buf[bufPtr] = 0;
      parseBufferCommand(buf, bufPtr);
      bufPtr = 0;
    }
    else {
      buf[bufPtr++] = ch;
      if (bufPtr == sizeof(buf)) {
        tooMuchDataError();
        bufPtr = 0;
      }
  }
}

Another way of implementing your code would be to read data into a buffer, and then parse the command once you have the end character.

That's fine, except that the name bufPtr is horrible. It is an index, not a pointer. It does not point to buffer. bufInd would be a better name, in my opinion.

PaulS: That's fine, except that the name bufPtr is horrible. It is an index, not a pointer. It does not point to buffer. bufInd would be a better name, in my opinion.

If we're going for descriptive names, "bufCnt" or "bufEnd" would be even better :-)

Hi,

First thanks for pointing out the rigt way for doing the code, now a have a problem i need to declare "parseBufferCommand" can you hellp me?

char buf[100];
int bufPtr = 0;

void setup()
{
  //Create Serial Object
  Serial.begin(9600);
  Serial.println("ARDUINO ON!");
}

void loop() {

  if (Serial.available()) {
    char ch = Serial.read();
    if (ch == 't') {
      buf[bufPtr] = 0;
      parseBufferCommand(buf, bufPtr);
      bufPtr = 0;
    }
    else {
      buf[bufPtr++] = ch;
      if (bufPtr == sizeof(buf)) {
        tooMuchDataError();
        bufPtr = 0;
      }
  }
}

now a have a problem i need to declare "parseBufferCommand"

What problem do you have?

From the call, it is obvious that the function need not return a value, so:

void parseBufferCommand(char *buf, int bufSiz)
{
  // Do some parsing...
}

If you properly NULL terminated the array, passing the size would not be necessary, and parsing could use standard strXXX type functions.