Arduino serial parsing

based on Robin2’s example sketch,

// Example 5 - Receive with start- and end-markers combined with parsing

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

      // variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;

boolean newData = false;

//============

void setup() {
    Serial.begin(9600);
    Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value");
    Serial.println("Enter data in this style <HelloWorld, 12, 24.7>  ");
    Serial.println();
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

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

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
 
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    integerFromPC = atoi(strtokIndx);     // convert this part to an integer

    strtokIndx = strtok(NULL, ",");
    floatFromPC = atof(strtokIndx);     // convert this part to a float

}

//============

void showParsedData() {
    Serial.print("Message ");
    Serial.println(messageFromPC);
    Serial.print("Integer ");
    Serial.println(integerFromPC);
    Serial.print("Float ");
    Serial.println(floatFromPC);
}

focusing on this part,

void showParsedData() {
    Serial.print("Message ");
    Serial.println(messageFromPC);
    Serial.print("Integer ");
    Serial.println(integerFromPC);
    Serial.print("Float ");
    Serial.println(floatFromPC);
}

[/code]

i am trying to modify it but i dont think im setting “timevar” properly? and it also print out the wrong variable at Serial.print(timevar); below,

void showParsedData() {
    if (strcmp(messageFromPC, "set time") == 0) {
      unsigned long timevar = integerFromPC;
    Serial.print("Time Set To ");
    Serial.println(integerFromPC);
  }
    //do other stuff
    Serial.print(timevar);
}

it also print out the wrong variable at Serial.print(timevar); below,

I am willing to be that it doesn't. It may print a value that you do not expect but it will come from timevar

timevar will only contain the value of integerFromPC if the condition returns true, otherwise it will contain its previous value or may be changed in the code that you have not posted.

Do you ever see the "Time Set To " message ? What happens if you print timevar inside the if instead of integerFromPC

UKHeliBob:
I am willing to be that it doesn’t. It may print a value that you do not expect but it will come from timevar

timevar will only contain the value of integerFromPC if the condition returns true, otherwise it will contain its previous value or may be changed in the code that you have not posted.

Do you ever see the "Time Set To " message ?
What happens if you print timevar inside the if instead of integerFromPC

yeas im sorry i meant to say value not variable, and yes it does print time. the ultimate goal is to update a variable in the program with the numbers from integerFromPC, in not sure if its actually setting timevar to the variable i want it to but i know it don’t print the correct value?

it still fails inside the if statement and when i type <time set,1111111> i get

Time Set To -19961
3580857472

now that i think about it Serial.println(integerFromPC); dont display the right value either if its higher than 4 digits? what am i missing here. and i did post the code its the example code from the top minus the if statement

@notsolowki, please post your complete program.

...R

here is the complete program,

// Example 5 - Receive with start- and end-markers combined with parsing

unsigned long timevar = 1000000;
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

      // variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = 0;

float floatFromPC = 0.0;


boolean newData = false;

//============

void setup() {
    Serial.begin(9600);
    Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value");
    Serial.println("Enter data in this style <HelloWorld, 12, 24.7>  ");
    Serial.println();
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

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

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
 
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    integerFromPC = atoi(strtokIndx);
   

    strtokIndx = strtok(NULL, ",");
    floatFromPC = atof(strtokIndx);     // convert this part to a float

}

//============

void showParsedData() {
    if (strcmp(messageFromPC, "set time") == 0) 
    timevar = integerFromPC;
    Serial.print("Time Set To ");
    Serial.println(integerFromPC);
    Serial.println(timevar);

  }
    //do other stuff

what can i do with the int to accept a value larger than 16bits. for example if the value was 999999999

void showParsedData()

{
  if (strcmp(messageFromPC, “set time”) == 0) {
  …
}

<time set,1111111>

I don’t get anything :wink: Guess why :wink:

Your problem lays in the fact that an integer is only two bytes. So if you enter a number greater than 32767 it becomes negative.

void showParsedData()
{
  if (strcmp(messageFromPC, "set time") == 0) {
    unsigned long timevar = integerFromPC;
    Serial.print("Time Set To 0x");
    Serial.print(integerFromPC, HEX);
    Serial.print(" -> ");
    Serial.println(integerFromPC);
    Serial.print("timevar = 0x"); Serial.print(timevar, HEX);
    Serial.print(" -> ");
    Serial.println(timevar);
  }
  //do other stuff
}

Input

<set time,123456,9>

Output

Time Set To 0xFFFFE240 -> -7616
timevar = 0xFFFFE240 -> 4294959680

Numbers greater than or equal 0x8000 will be negative. Ignore the leading Fs of the first line. Next you assign to timevar (unsigned long) and you see the result.

You need to change your integerFromPC to an unsigned long and use atol instead of atoi.
For the same input

Time Set To 0x1E240 -> 123456
timevar = 0x1E240 -> 123456

thankyou, but i still cannot get timevar to update to the the value of “integerFromPC” please look at this and tell me why the timevar is not being update now?

unsigned long timevar = 0;
const byte numChars = 128;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

// variables to hold the parsed data
char messageFromPC[numChars] = {0};
unsigned long integerFromPC = 0;
float floatFromPC = 0.0;


boolean newData = false;

//============

void setup() {
    Serial.begin(9600);
    Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value");
    Serial.println("Enter data in this style <HelloWorld, 12, 24.7>  ");
    Serial.println();
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            // because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
       long rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    integerFromPC = atol(strtokIndx);


    strtokIndx = strtok(NULL, ",");
    floatFromPC = atof(strtokIndx);     // convert this part to a float

}

//============

void showParsedData() {
    if (strcmp(messageFromPC, "a") == 0) 
    unsigned long timevar = integerFromPC;
    Serial.print("Time Set To ");
    Serial.println(integerFromPC);
    Serial.println(timevar);

  }
    //do other stuff

Referring to Reply #8 Wouldn't it make a lot more sense if this

unsigned long integerFromPC = 0;

was

unsigned long unsignedLongFromPC = 0;

but i still cannot get timevar to update to the the value of "integerFromPC" please look at this and tell me why the timevar is not being update now?

Probably because you have two variables called timeVar. One if defined at the top of the program and the other is defined as a local variable inside an IF clause in showParsedData(). Drop the unsigned long prefix in that function.

Also, if you always display ALL if clauses with { } like this

if (strcmp(messageFromPC, "a") == 0) {
      unsigned long timevar = integerFromPC;
}

that sort of problem would be more obvious.

Of course the $64K question is why not do this

strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    timevar = atol(strtokIndx);

...R