I am fairly new to C++ programming and I'm working on a project that will read and parse a 2400baud serial ASCII data stream. For now I'm using an Arduino Uno as my prototyping platform. The stream is comma delimited, continuously repeating, and formatted exactly like this:
I have no problem opening the serial port, setting the baud rate, and seeing the ASCII stream… but I need a help with the parsing of the stream. I think that strtok (split string into tokens) is probably the best function to do this as I need (some of) the numbers as integers and (some of) the text as descriptors.
The data I currently need from the stream are the ints from the descriptors V, A, W and %. I guess I may also need to store these ints in a buffer so I can use/output them?
Ultimately I'll be printing to an LCD shield, but for now I would be happy just to realtime serial.print the output (using the above stream as the example) as:
Volts 13.7
Amps 00.1
Watts 0.82
Percent 100
Any advice or sample code would be appreciated.
Thanks in advance!
-Mark
Build a string from the incoming characters then when it is complete (you need an end of message indicator) use strtok to split it at the commas then you can split each substring and turn the number strings into numbers using the strtof function if you actually need the numbers, otherwise just display the number substrings.
Thats not a very effective way of doing things. Your wasting alot of memory and string functions are quite slow.
It's more efficient to listen for characters as they come in. It's very easy.
How about something like below.
I just quickly put it together, could contain some error or be made more efficient(by not using floats) but the general idea should be made clear.
PaulS:
A one element array? Get real.
That whole routine for reading one character from the serial port is riddled with waste.
Heard about constructive feedback? you could have asked me why i did that, hearing me out and then giving me advise on how to do things better. Under my opinion readBytes was needed here since the Serial buffer could be read faster then it being filled. Serial.read would just return a -1, while readBytes actually 'waits' for data to arrive. ReadBytes needed an array as input, a normal char would generate an error with that function. Now you knew why i did what i did, you could have provided me with a helpful post on how to fix such error or do things differently.
You talk about waste. What is actually wasteful is that your not using your 'expertise' to help the people like the OP but instead use it 'laugh' at other people's examples who actually do want to help.
Now back on topic, feel free to give constructive feedback
Fairly simple code that probably can be modified to do what you want.
//zoomkat 3-5-12 simple delimited ',' string
//from serial port input (via serial monitor)
//and print result out serial port
String readString, data;
int CD, CM, CT, CS, BR;
void setup() {
Serial.begin(9600);
Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}
void loop() {
//expect a string like CD01,CM01,CT01,CS03,BR255,
if (Serial.available()) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
Serial.println(readString); //prints string to serial port out
if(readString.indexOf("CD") >=0) {
data=readString.substring(2);
Serial.print("CD is: ");
Serial.println(data);
CD = data.toInt();
Serial.println(CD);
Serial.println();
}
if(readString.indexOf("CM") >=0) {
readString=readString.substring(2);
Serial.print("CM is: ");
Serial.println(readString);
CM = readString.toInt();
Serial.println(CM);
Serial.println();
}
if(readString.indexOf("CT") >=0) {
readString=readString.substring(2);
Serial.print("CT is: ");
Serial.println(readString);
CT = readString.toInt();
Serial.println(CT);
Serial.println();
}
if(readString.indexOf("CS") >=0) {
readString=readString.substring(2);
Serial.print("CS is: ");
Serial.println(readString);
CS = readString.toInt();
Serial.println(CS);
Serial.println();
}
if(readString.indexOf("BR") >=0) {
readString=readString.substring(2);
Serial.print("BR is: ");
Serial.println(readString);
BR = readString.toInt();
Serial.println(BR);
Serial.println();
}
//do some stuff
readString=""; //clears variable for new input
data="";
}
else {
readString += c; //makes the string readString
}
}
}
zoomkat, THANK YOU VERY MUCH!!!
Everybody else; I'm self-taught and trying (read: struggling) to figure out most of this on my own and this is the first time I have had to parse a stream like this. The bickering doesn't make it any easier for me. Please keep your comments relevant.
Thanx,
-Mark
Under my opinion readBytes was needed here since the Serial buffer could be read faster then it being filled. Serial.read would just return a -1, while readBytes actually 'waits' for data to arrive.
The readBytes() method is NOT needed. A simple while loop, waiting for either Serial.available() to return a non-zero value or for the desired time to have passed would have allowed for reading just one character, using Serial.read().
Learning how to do things properly, instead of relying on crutches or forcing an array to do what a single char can do, would serve you better in the long run.