How would i capture the following serial data, and split it into parts? <Alarm,MPos:0.000,0.000,0.000,WPos:0.000,0.000,0.000>

the parts i need from this is Alarm - This is a state. i.e Alarm, Idle, Paused, Working MPos: - This is a series of positions X,Y,Z WPos: - This is a series of positions X,Y,Z

What i want to do is capture the string from serial (See above for formatting) Then display the information on the LCD.

i.e. X: 0.000 Y:0.000 Z: 0.000 Idle

I've managed to figure out how to do all the LCD display stuff, and send commands to the serial, but it appears there are so many variations on how to split the data up, that i't really confusing to me, as well, almost all of the examples i find use loop to do this, but i would like to have this done in a function, that way i can display this info only when needed, not constantly, as i'll be useing the LCD for a menu system.

  • An actual example of what the string looks like would help - your description is very very vague and of no use to us whatsoever.
    – Majenko
    Aug 29 '15 at 15:35
  • Wierd.. i did include an example.. not sure where it went. <Alarm,MPos:0.000,0.000,0.000,WPos:0.000,0.000,0.000> That is the string i need to capture and split up
    – ArcAiN6
    Aug 29 '15 at 15:37
  • Ah, it probably thought it was HTML and pruned it out.
    – Majenko
    Aug 29 '15 at 15:37
  • Are all the parts always there and always in the same order?
    – Majenko
    Aug 29 '15 at 15:43
  • Yes, all parts are always there, and always in the same order, however, they are not always the same. I.e. <Alarm,MPos:0.000,0.000,0.000,WPos:0.000,0.000,0.000><br/> <[1],MPos:[2],[3],[4],WPos:[5],[6],[7]> 1) This could be any of the following: Idle, Run, Hold, Door, Home, Alarm, Check 2) This is Machine Position X 3) This is Machine Position Y 4) This is Machine Position Z 5) This is Work Position X 6) This is Work Position Y 7) This is Work Position Z
    – ArcAiN6
    Aug 29 '15 at 15:49

This string is actually fairly easy to split up, because everything is separated by commas nice and regularly.

Assuming you have the string in a char array (aka a C string) and not a String object (I and most other programmers abhor the String class) you can use the function strtok() to split the string up into parts.

So you have the string:

char string[] = "<Alarm,MPos:0.000,0.000,0.000,WPos:0.000,0.000,0.000>";

The function strtok() takes, on its first call, the string you want to split and the delimiter that you want to split on. It returns a pointer to the chunk:

char *alarm = strtok(string, ",");

alarm now contains <Alarm and strtok() moves its internal pointer to point at the next character, so it sees the string as MPos:0.000,0.000,0.000,WPos:0.000,0.000,0.000>

With the next and subsequent calls to strtok() you don't give it the string, or it will reset its internal pointer. You just pass it NULL and it gives you the next block:

char *mposX = strtok(NULL, ",");
char *mposY = strtok(NULL, ",");
char *mposZ = strtok(NULL, ",");
char *wposX = strtok(NULL, ",");
char *wposY = strtok(NULL, ",");
char *wposZ = strtok(NULL, ">");

Note that I changed the delimiter on the last one to > so it chops off that extra character that we don't want (and there is no , after the last part).

So now you have 7 variables that point to chunks of the string, which has internally been chopped up and modified into individual substrings:

*alarm = "<Alarm";
*mposX = "MPos:0.000";
*mposY = "0.000";
*mposZ = "0.000";
*wposX = "WPos:0.000";
*wposY = "0.000";
*wposZ = "0.000";

So now we can clean up the three entries that have extra stuff in them, and that is a simple as adding an offset value to the pointers we have:

alarm += 1;
mposX += 5;
wposX += 5;

Our list of pointers now looks like this:

*alarm = "Alarm";
*mposX = "0.000";
*mposY = "0.000";
*mposZ = "0.000";
*wposX = "0.000";
*wposY = "0.000";
*wposZ = "0.000";

The position variables can now be passed through strtod() to convert them to float values:

float mx = strtod(mposX, NULL);
float my = strtod(mposY, NULL);
float mz = strtod(mposZ, NULL);
float wx = strtod(wposX, NULL);
float wy = strtod(wposY, NULL);
float wz = strtod(wposZ, NULL);

You can do different things depending on the content of the *alarm string by using strcmp():

if (strcmp(alarm, "Busy") == 0) {
    // Something to do when Busy


Or you can just use it to print the content to the LCD.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.