Hey guys, I'm trying to process a string that will have several bits of information in it delimited by a colon or comma or something like that on an arduino. The data is coming in over the serial port and I would like to be able to split the parts up in one routine. I've searched the forums and the Internet without a lot of luck on how to work with delimited data, can anyone provide me some pointers? I'm looking for something similar to perls split() function I guess.
The good news; it's doable. The better news; you get to implement functionality yourself! ;)
I do not know your constraints or if there is some limitations on how long your raw string is going to be.
When you recieve something serially you actually get one char at a time, not the entire string, so you either need to buffer the whole string into a variable, or a delimited piece into a variable (use it then reuse variable) or you can build yourself a 2 dimentional array of characters that will represent all your data, but beware, it consumes a lot of rom.
tell me more about your goal and data.
what kind of data is it, how much needs to be stored?
Wow, that was a fast reply, thank you! I'm trying to create a bot that will use skid steering and be controlled over a serial link. I picked serial because I would like to have the option of using an xbee to control and a physical tether without having to do a lot of hardware manipulation or coding. My thought was to send a chunk of data similar to LEFT:100 where LEFT would mean left wheels and 100 would be the speed, a negative value would mean reverse. The motors are PWM controlled DC motors and the end goal is to have 3 statements + speed to control them. LEFT, RIGHT and ALL. This is still a paper bot though, so I'm more then willing to entertain other ideas for control with the only constraint being the serial bit.
Hey, penguin, and welcome. (My slightly dyslexic eyes read your name as "featherpenguin" at first. :))
Assuming you have managed to get a string buffer full of delimited data, it's pretty easy to iterate through it using the standard library function strtok_r(). For example this little sketch:
char sz = "Here; is some; sample;100;data;1.414;1020";
char *p = sz;
while ((str = strtok_r(p, ";", &p)) != NULL) // delimiter is the semicolon
generates this output:
That said, Arduino doesn't have any facilty for directly reading a string into a buffer. As AlphaBeta says, you get serial characters, well, serially. But it's not too hard to write your own GetString() function.
hehehe yeah, I've been using this handle since 1996 and almost everyone reads it that way first ;D so If I understand correctly, I have two hurdles to overcome really. The first is that, assuming an arduino is sending the data, if I use something like Serial.println("Hello Nurse") and then a Serial.Read, my first challenge is going to be determining when I've received my full string. Once that's done, your parsing code looks pretty straight forward. Would it be more efficient to due a while loop around serial.read looking for a specific character and adding to a string (with a bounds check of course to make sure I don't explodiate my memory) or should I get my rear back onto google?
What you propose is exactly what I'd do: make a while loop that repeatedly reads up until a certain terminator. Let's say, for example, that you define 0 (binary 0) to be your string terminator. Your transmitting Arduino would do something like:
Serial.print("LEFT:100:RIGHT:50"); // the data
Serial.print(0, BYTE); // the terminator.
Then, on the receiving side I'd write a function that captured the data into a string buffer like this:
void GetString(char *buf, int bufsize)
for (i=0; i<bufsize - 1; ++i)
while (Serial.available() == 0); // wait for character to arrive
buf[i] = Serial.read();
if (buf[i] == 0) // is it the terminator byte?
buf[i] = 0; // 0 string terminator just in case
Then, call the function to get a string and parse it using strtok_r():
/* parse buf using technique above */
/* do something with the data */
That seem reasonable?
You are good, you are wise. That all makes a fair amount of sense to me and gives me a great jumping off point. It also gives me an idea on how to extend things a bit to control other functions like lights etc. Thanks again for the pointers and examples!