Go Down

Topic: [solved] problems with extracting values from Serial communication (Read 468 times) previous topic - next topic

Alban

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 :)

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 :)

Code: [Select]
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??
Best regards,

Alban

P.S. sorry for asking silly questions... I'm a mechanical engineer and not an electronics engineer ;)


www.reptile-addict.nl

groundfungus

#1
Feb 06, 2014, 12:05 am Last Edit: Feb 06, 2014, 12:11 am by groundfungus Reason: 1
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.

MarkT

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: [Select]

#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?
    }
  }
  ..
}

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

zoomkat

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.
Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

Alban


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!!!
Best regards,

Alban

P.S. sorry for asking silly questions... I'm a mechanical engineer and not an electronics engineer ;)


www.reptile-addict.nl

Go Up