I have a sensor that outputs a serial string of numbers, spaces, and letters. It's in a format like this: "525 0 894xcf"
It's basically 3 numbers separated by white spaces. The numbers can vary from 1 to 4 digits, so I have to use the white spaces as delimiters. And there are always a few letters tacked onto the last number that I want to throw away. I need to separate the 3 numbers into integers so that they can be stored or transmitted further down in the script.
I'm able to successfully read in the serial data and store it in a string. The trouble comes when I try to parse it.
I've searched this forum and got several different examples. Some people say to use sscanf, others say atoi or strtok. It seems like there are several ways to do it and everyone has their own opinion about what should or should not be used. I've tried all 3 of the above by using examples people have posted here, but can't seem to make them work. So I'm wondering which method I should focus on if somebody has some tips.
strtok can be useful to quickly and easily break a string up into the specified tokens (but it doesn't do any datatype conversion, so you still have to use something like atoi to convert the values). An important side affect to strtok is that it modifies the string it is tokenizing.
sscanf is going to have more compiled overhead than atoi, because it's a much more versatile function. On small sketches this may not be an issue, but if you're low on flash space, the difference between sscanf and atoi could be the difference between your program fitting on the micro or not.
strtok will do it. Here's a quick & dirty example. Note that it assumes that you have the string with all three numbers & doesn't check that that is really the case:
Thanks for the help. I'm posting the code I have so far, but I'm getting the following error on the line with the sscanf function:
_5TMtest_2:25: error: cannot convert 'String' to 'const char*' for argument '1' to 'int sscanf(const char*, const char*, ...)'
My code:
#include <NewSoftSerial.h>
NewSoftSerial mySerial(8, 9);
int x,y,z;
String readString;
void setup()
{
Serial.begin(1200);
mySerial.begin(1200);
Serial.println("5TMtest-2"); // so I can keep track of what is loaded
}
void loop() {
while (mySerial.available()) {
delay(1);
if (mySerial.available() >0) {
char c = mySerial.read(); //gets one byte from serial buffer
readString += c; //makes the string readString
}
}
if (readString.length() >0) {
Serial.print("readString = ");
Serial.println(readString); //so you can see the captured string
sscanf (readString, "%d %d %d", &x, &y, &z);
Serial.print("first= ");
Serial.println(x);
Serial.print("middle= ");
Serial.println(y);
Serial.print("last= ");
Serial.println(z);
}
readString="";
}
The error is saying you can't pass a String object to sscanf, which expects a C string (an array of "char", terminated by a zero).
You need to convert your String to a C string if you want to use sscanf.
Okay, that makes sense. But how to I convert the string to a C string? Would it be easier to read the data from the sensor directly into a C string first instead of converting?
andywatson:
Would it be easier to read the data from the sensor directly into a C string first instead of converting?
No easier, but probably safer - you won't have to worry about string operations fragmenting your heap and failing unexpectedly after you've been running for a while.
It's working now, except that the serial data from my sensor apparently has a couple non-numeric characters before the actual numbers I want to read, along with a carriage return after them, and that seems to be throwing things off. Is there a way to filter out non-numeric things when populating the string during the myserial.read part?
I just captured several lines of the raw serial data from the sensor using a program on my PC called RealTerm to save it to a text file. I'm attaching a picture of what the raw sensor data looks like when viewed with notepad. Note the strange character at the beginning of each line and the little box after 642, which I guess is a carriage return.