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.
1 Answer 1
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
}
etc.
Or you can just use it to print the content to the LCD.
Explore related questions
See similar questions with these tags.
<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<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