Pages: [1]   Go Down
Author Topic: [solved] problems with extracting values from Serial communication  (Read 423 times)
0 Members and 1 Guest are viewing this topic.
Near Rotterdam in Holland
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, i'm having some difficulties extracting values from a Serial connection.
I have spent way too long looking and experimenting so now it is time to ask here smiley

What I'm trying to do is this:

Thru Serial1 on my Arduino Due is data coming in like this: 200;1962;2145;2689;48;
I need to have the 1962 and the 2145 and the 2689 and the 48 as floats.
1962 stands for 19.62 degrees. Same goes for the 2145 and the 2689. The 48 is 48% humidity.

I managed to get 4 char arrays with the seperate digits and try to use atof() to convert to float (double in this case).
Some of my char arrays work fine and the others return ovf (no idea what it stands for guess it is similar to NaN).

Anyway, the code is probably easier to interpret than my explanation smiley

Code:
void ProcessJeeNodeData() {
SerIndex = 0;
int flag = 0;

// Don't read unless something is sent to Serial1;
while (Serial1.available() > 0 && SerIndex < 22) {
flag = 0;

inChar = Serial1.read(); // Read a character

// data I receive is in this format:
//200;1962;2145;2689;48; it is 3digits which I do not use, 4 digits temperature * 100, 4 digits temperature * 100, 4 digits temerature * 100, 2 digits humidity
//0123456789012345678901  location of the different chars in the datastring
//I write the values to 4 char arrays: TempVal1[3], TempVal2[3], TempVal3[3] and RVVal1[1]

// extracting the first temperature
if (SerIndex > 3 && SerIndex < 8) {
TempVal1[SerIndex-4] = inChar;
Serial.print(SerIndex);Serial.print(" => ");Serial.print("TempVal1[");Serial.print(SerIndex-4);Serial.print("]=");Serial.println(TempVal1[SerIndex-4]);
flag = 1;
}

// extracting the second temperature
if (SerIndex > 8 && SerIndex < 13) {
TempVal2[SerIndex-9] = inChar;
Serial.print(SerIndex);Serial.print(" => ");Serial.print("TempVal2[");Serial.print(SerIndex-9);Serial.print("]");Serial.println(TempVal2[SerIndex-9]);
flag = 1;
}

// extracting the third temperature
if (SerIndex > 13 && SerIndex < 18) {
TempVal3[SerIndex-14] = inChar;
Serial.print(SerIndex);Serial.print(" => ");Serial.print("TempVal3[");Serial.print(SerIndex-14);Serial.print("]");Serial.println(TempVal3[SerIndex-14]);
flag = 1;
}

// extracting the humidity
if (SerIndex > 18 && SerIndex < 21) {
RVVal1[SerIndex-19] = inChar;
Serial.print(SerIndex);Serial.print(" => ");Serial.print("RVVal1[");Serial.print(SerIndex-19);Serial.print("]");Serial.println(RVVal1[SerIndex-19]);
flag = 1;
}

// for debugging I also print the chars I skip. Using the flag to trigger this
if (flag == 0) {
Serial.print(SerIndex);Serial.print(" => ");Serial.print("inChar = ");Serial.println(inChar);
flag = 0;
}


           SerIndex++; // Increment where to write next
}

// after receiving the data and collecting it into the char arrays I process the raw data to floats
if (SerIndex > 0) {

Temp_DS_1 = atof(TempVal1);
Temp_DS_2 = atof(TempVal2);
Temp_SHT = atof(TempVal3);
RV_SHT = atof(RVVal1);


Serial.print("Temp_DS_1 = ");Serial.print(Temp_DS_1);Serial.print(" => ");Serial.print(Temp_DS_1 / 100.0);Serial.println("deg");
Serial.print("Temp_DS_2 = ");Serial.print(Temp_DS_2);Serial.print(" => ");Serial.print(Temp_DS_2 / 100.0);Serial.println("deg");
Serial.print("Temp_SHT = ");Serial.print(Temp_SHT);Serial.print(" => ");Serial.print(Temp_SHT / 100.0);Serial.println("deg");
Serial.print("RV_SHT = ");Serial.print(RV_SHT);Serial.print(" => ");Serial.print(RV_SHT);Serial.println("%");
}

/*  the result in my serial window is:
0 => inChar = 2
1 => inChar = 0
2 => inChar = 0
3 => inChar = ;
4 => TempVal1[0]=1
5 => TempVal1[1]=9
6 => TempVal1[2]=5
7 => TempVal1[3]=6
8 => inChar = ;
9 => TempVal2[0]2
10 => TempVal2[1]1
11 => TempVal2[2]9
12 => TempVal2[3]3
13 => inChar = ;
14 => TempVal3[0]2
15 => TempVal3[1]8
16 => TempVal3[2]7
17 => TempVal3[3]8
18 => inChar = ;
19 => RVVal1[0]4
20 => RVVal1[1]6
21 => inChar = ;
Temp_DS_1 = ovf => 1956219289.60deg
Temp_DS_2 = 21932878.00 => 219328.78deg
Temp_SHT = 2878.00 => 28.78deg
RV_SHT = 46.00 => 46.00%
0 => inChar =
1 => inChar =

Temp_DS_1 = ovf => 1956219289.60deg
Temp_DS_2 = 21932878.00 => 219328.78deg
Temp_SHT = 2878.00 => 28.78deg
RV_SHT = 46.00 => 46.00%
*/
}

I hope someone can explain to my where I'm going wrong and point me into the right direction. Maybe/probably there is a better way of doing this??
« Last Edit: February 06, 2014, 03:08:53 pm by Alban » Logged

Best regards,

Alban

P.S. sorry for asking silly questions... I'm a mechanical engineer and not an electronics engineer smiley-wink


www.reptile-addict.nl

BCC AZ USA
Offline Offline
Edison Member
*
Karma: 37
Posts: 1294
It gets hot so it must be working
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Where is the data coming from?  Can you format the data that is sent?  If so, have the sender send float values and use Serial.parseFloat() to get your values into an array of floats.  Or you can use parseint() with the current data and divide by 100.00, as the case may be,  and cast to float.
« Last Edit: February 05, 2014, 06:11:30 pm by groundfungus » Logged

0
Offline Offline
Shannon Member
****
Karma: 214
Posts: 12424
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You are much much better off processing your numbers on the fly - this is
called lexical analysis, producing the float values as you go:
Code:
#define NARGS 4   // 4 arguments on a line
float args [NARGS] ;  // put them here
int arg_index = 0 ;  // where in the list of args:
float current = 0.0 ;

void loop ()
{
  ..
  if (Serial.available () > 0)  // no need for while, we are in a loop already
  {
    char ch = Serial.read () ;
    if (ch == '\n') // newline, process existing values and reset
    {
      process_args () ;
      arg_index = 0 ;
      current = 0.0 ;
    }
    else if (ch == ';')  // separator
    {
      if (arg_index < NARGS)  // mustn't write off end of array
      {
        args [arg_index ++] = current ;
      }
      current = 0.0 ; // reset for next number
    }
    else if (ch >= '0' && ch <= '9')
    {
      int digit = ch - '0' ;  // get digit
      current = current * 10 + digit ; // accumulate
    }
    else
    {  // maybe report an error condition back on serial?
    }
  }
  ..
}

Logged

[ I won't respond to messages, use the forum please ]

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

If you have control of how the data is being sent, then adding an identifier for each data type would make the coding pretty easy. Instead of 200;1962;2145;2689;48; try something like 200a;1962b;2145c;2689d;48e; to identify each data packet type.
Logged

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

Near Rotterdam in Holland
Offline Offline
Newbie
*
Karma: 0
Posts: 22
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You are much much better off processing your numbers on the fly - this is
called lexical analysis, producing the float values as you go:

Works like a charm!!!! Thanks to you all!!!
Logged

Best regards,

Alban

P.S. sorry for asking silly questions... I'm a mechanical engineer and not an electronics engineer smiley-wink


www.reptile-addict.nl

Pages: [1]   Go Up
Jump to: