Pages: [1] 2   Go Down
Author Topic: Need help parsing serial data stream please.  (Read 476 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

V=13.7,FV=13.7,V2=00.0,A=00.1,FA=00.1,AH=0.18,%=100,W=0.82,DSC=1.87,DSE=1.98,

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
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 116
Posts: 4309
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Note that several of your not integers.
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Offline Offline
Newbie
*
Karma: 5
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Code:
char ch;
float Volts,Amps,Watts,Percentage;
char buffer[3];
if (Serial.available()){
ch=Serial.read();
if (ch=="V" && getch()=="="){
Volts=CharsToFloat();
}
else if (ch=="A" && getch()=="="){
Amps=CharsToFloat();
}
else if (ch=="W" && getch()=="="){
Watts=CharsToFloat();
}
else if (ch=="%" && getch()=="="){
Percentage=CharsToFloat();
}
}
char getch(){
  char bytebuffer[1];
  Serial.setTimeout(1000);
  Serial.readBytes(bytebuffer,1);
  return bytebuffer[0];
}
float CharsToFloat(){
buffer[0]=getch()-0x30;
ch =getch();
if (ch!="."){
buffer[1]=ch-0x30;
ch=getch();
if (ch=="."){
buffer[2]=getch()-0x30;
return 10*buffer[0]+Buffer[1]+0.1*Buffer[2];
}
else{
buffer[2]=ch;
return 100*buffer[0]+10*Buffer[1]+Buffer[2];
}
}
else{
buffer[1]=getch()-0x30;
buffer[2]=getch()-0x30;
return 1*buffer[0]+0.1*Buffer[1]+0.01*Buffer[2];
}
}


« Last Edit: February 08, 2014, 02:58:31 pm by racquemis » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you raquemis! I'll give that a try.
-Mark
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50041
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  char bytebuffer[1];
A one element array? Get real.

That whole routine for reading one character from the serial port is riddled with waste.
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 116
Posts: 4309
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
string functions are quite slow.
Do you mean String functions are quite slow or string functions are quite slow ?  Not the same thing at all.
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50041
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Not the same thing at all.
Especially since one is true and one is not.
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 116
Posts: 4309
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Not the same thing at all.
Especially since one is true and one is not.
That was my point.
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Offline Offline
Newbie
*
Karma: 5
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50041
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
That was my point.
A bit too subtly made, I thought.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 308
Posts: 26469
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
ReadBytes needed an array as input, a normal char would generate an error with that function.
But the address of a normal char would not.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 5
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

now that's actually helpful. thank you.
« Last Edit: February 08, 2014, 07:03:47 pm by racquemis » Logged

0
Offline Offline
Tesla Member
***
Karma: 145
Posts: 9671
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Fairly simple code that probably can be modified to do what you want.

Code:
//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
    }
  }
}
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 631
Posts: 50041
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

Pages: [1] 2   Go Up
Jump to: