Problem conversion char to float

Hi everyone,

I’m having some issues converting a char that I’m reading into a float.
The char (inData) is always of a form like 2.65 or 1.89 or 4.56 or …
These are actually voltages ranging from 0 to 5v.

When I serial print inData before I use “atof”, the values are perfectly fine. But after the conversion when I serial print f. Then it has “dropped” the two decimals. So instead of 2.65 it would just state 2.00

What could I be doing wrong?

Thanks in advance!

float getFloatFromSerialMonitor(){   
  char inData[4];
  float f;
  int x=0;
  while (x<1){
  if (Serial.available()) {
    delay(5);                         
    int i=0;
    while (Serial.available() > 0) {
     char inByte = Serial.read();
      inData[i]=inByte;
      i+=1;
      x=2;
    }
    f = atof(inData);
    Serial.println(f);
  }
  }
   return f;
   
  }

Is inData correctly zero terminated ?

UKHeliBob: Is inData correctly zero terminated ?

I don' think so, because there's only room for 4 charactars in inData. So I kinda "cut off" part of the incoming serial data?

How would I zero terminate it?

The first time you use the function and use the input say 2.6 (only 3 characters) it works OK ?

Maybe change:

char inData[4];

to

char inData[5] = {0};

and stop variable "i" getting too large.

I don' think so, because there's only room for 4 charactars in inData

That is what I was alluding to

How would I zero terminate it?

First make the array large enough to accept the number of characters expected plus 1 for the terminating zero. Then, after you receive a character and increment the index to the array put '\0' in the new position.

UKHeliBob:
That is what I was alluding to
First make the array large enough to accept the number of characters expected plus 1 for the terminating zero. Then, after you receive a character and increment the index to the array put ‘\0’ in the new position.

So you mean something like this? (You’ve probably noticed by now that I’m not very experienced programming. Sorry about that)

Note: The amount of characters that there are available to read is more than the ones I chose to read. Is that a problem? So I only want to read the first 4 characters and then zero-terminate it.

float getFloatFromSerialMonitor(){  
  char inData[5];
  float f;
  int x=0;
  while (x<1){
  if (Serial.available()) {
    delay(5);                       
    int i=0;
    while (Serial.available() > 0) {
     char inByte = Serial.read();
      inData[i]=inByte;
      i+=1;
      x=2;
      inData[5] = '\0';     
        
      }
    }
   //Serial.println(inData);
    f = atof(inData);
    Serial.println(f);

So you mean something like this?

What I actually meant was

      inData[i]=inByte;
      i+=1;
      x=2;
      inData[i] = '\0';

which is a more general way of doing the same thing and puts the termination character in the last position in the string whatever its length is assuming, that is, that the array is declared large enough

Incidentally, your method of reading the string is not very robust. Although it is unlikely, what would happen if receipt of the message took longer than 6 milliseconds ?

UKHeliBob: What I actually meant was

      inData[i]=inByte;
      i+=1;
      x=2;
      inData[i] = '\0';

which is a more general way of doing the same thing and puts the termination character in the last position in the string whatever its length is assuming, that is, that the array is declared large enough

I just tried this but it didnt work. I still don't have accurate values. Just 1.00 or 2.00 ...

UKHeliBob: Incidentally, your method of reading the string is not very robust. Although it is unlikely, what would happen if receipt of the message took longer than 6 milliseconds ?

Yeah, the "reading part", I took from someone else. If there's a better way, I'd be glad to hear.

The actual reason I want to convert the char to float is because I have to do some "math" with the values. These are values from 0 to 5v, but I want to analogwrite them. So they have to be converted to 0-255. For that I'd do: analogval = ((255 * inData)/5) but that doesnt work. Because then it says: error: invalid operands of types 'int' and 'char [5]' to binary 'operator*'

So I thought they had to be float. So thats why I'm trying to convert them to float.

If I could just leave them as a char but still convert them to 0-255. Then that would be perfect for me as well.

I just tried this but it didnt work. I still don’t have accurate values. Just 1.00 or 2.00 …

OK. Insert this before you do the atof()

  for (int c = 0; c < strlen(inChar); c++)
  {
    Serial.print(c);
    Serial.print(" : ");
    Serial.println(inData[c]);
  }

What does it output ?

I just found what was causing all the trouble.

Apparently the values that I was reading had a comma instead of a point. So they were like 2,56 or 0,55 or 1,55 instead of 2.56 or 0.55 or 1.55

So when I tried to use atof on that, it didn’t know how to handle the comma I assume.
So I replaced the comma with a point and that solved it!

Thanks a lot for the help!

float getFloatFromSerialMonitor(){    
  char inData[5];
  float f;
  int x=0;
  while (x<1){
  if (Serial.available()) {
    delay(5);                       
    int i=0;
    while (Serial.available() > 0) {
     char inByte = Serial.read();
      inData[i]=inByte;
      i+=1;
      x=2;
      inData[1] = '.';
      inData[i] = '\0';     
    }
    f = atof(inData);
    }
    }
  return f;
}

Yeah, the "reading part", I took from someone else. If there's a better way, I'd be glad to hear.

Serial input basics.