2

I am currently working on a project where i take a frequency, and i want the code to take that value and use a formula to work out its mmh2O level. I use the Serial Monitor to input the values, but i have a problem. When writing the values e.g. "44.62352548","44.49151522". The value that is sent is wrong and displayed wrong. enter image description here

I know the code i have written does not support this many signigicant figures from a float. And i have tried a few things to try and solve it but i cannot crack it.

I have tried using dtostrf() command, but i have never used this before and dont understand. Somebody from the arduino Forums had helped me out but it didnt seem to work. I have also tried formatting aswell, and that did not seem to work.

If anyone has any help and advice it would be much appreciated.

float level;
float myValue;

String msg1 = "Enter Frequency (type 0 to exit): "; 
String msg2 = "Your Frequency is: ";

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  Serial.print(msg1);

  while (Serial.available() == 0);
  {
     
  }
  myValue = Serial.parseFloat();
  if (myValue == 0.0)
  {
    Serial.end();
  }
  else
  { 
    freqConversion();
  }
}

 void freqConversion()
{
  level = (myValue-44.712)/-0.0285493333;
  Serial.println(myValue);
  Serial.print(msg2);
  Serial.println(level);
}
3
  • What do you mean by “The value that is sent is wrong and displayed wrong”? What did you expect? What was displayed instead? Commented Dec 4, 2020 at 13:32
  • added image of the result Commented Dec 4, 2020 at 13:36
  • no images please ... add the text and format as code
    – jsotola
    Commented Dec 4, 2020 at 15:10

1 Answer 1

2

You have hit a bug in the implementation of parseFloat().

This function reads the number you send as an integer, ignoring the decimal point, and stores it in a long. It then multiplies it by a scaling factor (a power of 0.1) in order to get the correct value. The problem is, if you provide too many significant digits, the integer overflows, and you get garbage. For example "44.64978683" is interpreted as

(long) 4464978683 * 0.00000001

but (long) 4464978683 overflows and rolls over to 170011387, hence the result you get.

Simple workaround: do not provide so many significant digits. They are irrelevant anyway given the resolution of a float.

Edit: I did not find any bug report for this issue, so I submitted my own to the Arduino dev team.

Update: Per request of a maintainer, I submitted a pull request with a failing unit test revealing this bug. We then worked on a fix, which has now been merged to master. It should be published on the next release of ArduinoCore-API.

Note, however, that the AVR core does not yet use the common API repository. In the meantime, it may be worth submitting a pull request to ArduinoCore-avr that cherry-picks the fix from ArduinoCore-API.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.