Serial.read() decimals... ????

I'm trying to output decimals to the serial monitor such as 30.0003 as an example... Instead, my code is outputting 30.3 ..

I know why, the code adds the value of '0' then subtracts '0' from it.. so there is nothing left.. as long as there is any number but '0' directly to the right of the decimal point, it works.. but I'm lost on how to keep the '0's to the right of the decimal point until any other number is read...

// Example of receiving numbers by Serial
// Author: Nick Gammon
// Date: 31 March 2012

const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

void setup ()
 { 
 Serial.begin (9600);
 Serial.println ("Starting ...");
 } // end of setup
 
 
void processNumbers (const long n, const long a )
 {
 Serial.print (n);
 Serial.print ('.');
 Serial.println (a);
 
 }  
 
void processNumber (const long n)
 {
 Serial.println (n);
 }  // end of processNumber
 
void processInput ()
 {
 static long receivedNumber = 0;
 static long decN = 0;
 static boolean negative = false;
 static boolean dec = false;
 
 byte c = Serial.read ();
 
 switch (c)
   {
     
   case endOfNumberDelimiter:  
   if(dec){
     if (negative)
       processNumbers (- decN, receivedNumber);
     else
      processNumbers (decN, receivedNumber); 
   }else{
     if (negative) 
       processNumber (- receivedNumber); 
     else
       processNumber (receivedNumber); 

   // fall through to start a new number
   case startOfNumberDelimiter: 
     receivedNumber = 0; 
     decN = 0;
     dec = false;
     negative = false;
     break;
     
   case '0' ... '9': 
     receivedNumber *= 10;
     receivedNumber += c - '0';
     break;
     
   case '-':
     negative = true;
     break;
     
   case '.':
     dec = true;
     decN = receivedNumber;
     receivedNumber =0;
     break;
   
     
   } // end of switch  
 }  // end of processInput
 }
 
void loop ()
 {
 
 if (Serial.available ())
   processInput ();
   
 // do other stuff here
 } // end of loop

That code you have, is reading input, not output.

What code are you using to try to output, because that ain't it.

michinyon:
That code you have, is reading input, not output.

What code are you using to try to output, because that ain't it.

the serial monitor and Serial.print & Serial.println

void processNumbers (const long n, const long a )
 {
 Serial.print (n);
 Serial.print ('.');
 Serial.println (a);
 
 }  
 
void processNumber (const long n)
 {
 Serial.println (n);
 }  // end of processNumber

Where did you get that code from? I can't find code by Nick Gammon that has a processNumbers function in it. That is where the problem lies. If you input <13.003>, the code calls processNumbers(13,3) which then prints 13.3 because there's no information there about how many zeros are before the '3'.
i.e. entering <13.3> <13.03> <13.003> etc. will all print 13.3

Pete

Are you trying to print floating point numbers, to two separate integers ?

That second piece of code you posted, is code to help you debug the first piece of code, which is code for converting incoming numbers, expressed as ascii text, into actual numbers. That second piece of code you posted, is not a useful method of outputting numbers in any useful context.

You need to be aware that there are some shortcomings in the arduino concerning printing floating point numbers, and methods that you use in other languages and platforms may have unexpected defective results.

el_supremo:
Where did you get that code from? I can't find code by Nick Gammon that has a processNumbers function in it. That is where the problem lies. If you input <13.003>, the code calls processNumbers(13,3) which then prints 13.3 because there's no information there about how many zeros are before the '3'.
i.e. entering <13.3> <13.03> <13.003> etc. will all print 13.3

Pete

I put that function in trying to read decimals.... I know why it isn't working... I just don't know how to fix it lol...

michinyon:
Are you trying to print floating point numbers, to two separate integers ?

That second piece of code you posted, is code to help you debug the first piece of code, which is code for converting incoming numbers, expressed as ascii text, into actual numbers. That second piece of code you posted, is not a useful method of outputting numbers in any useful context.

You need to be aware that there are some shortcomings in the arduino concerning printing floating point numbers, and methods that you use in other languages and platforms may have unexpected defective results.

I am trying to work around the float "shortcomming" to send serial data to a windows form.. but I can't get it working in the serial monitor so there is no need to send it to the form...

I need to send a number, as example, -30.00045... I can read and send them as a string, but I need to do math with the numbers at some point.... I'm just lost...

float value=atof(inputString.c_str()); converts my string to a decimal but only 2 points to the right...

like I said, I'm lost and really hate to send the string value to the computer to do the math then send it back again..

When printing a floating point number, specify the number of digits past the decimal place thusly:

float x=9.12345;
Serial.println(x,5);  //will print 5 places after the decimal

It often helps to read up on the functions you are using: Serial.print() - Arduino Reference

If you want to send Ascii characters representing a decimal number to an Arduino and then have the Arduino use it as a floating point number use the function atof().

See this demo.

...R

jremington:
When printing a floating point number, specify the number of digits past the decimal place thusly:

float x=9.12345;

Serial.println(x,5);  //will print 5 places after the decimal




It often helps to read up on the functions you are using: http://arduino.cc/en/Serial/Print

Thanks for the information about passing the second condition to the print function.. for some reason, I had overlooked it..

The problem I'm having is when I convert the string to float with 6 digits to the right, it drifts a few numbers on the last digit....

when I run the code below and input 37.250673, I get a converted value of 37.250671 and printing the string gives me 37.250673 which is the actual input..

String inputString = "";
void setup() {
  
  Serial.begin(9600);
  
  inputString.reserve(200);
}


void loop() {
  
  
  while (Serial.available()) {
    char inChar = (char)Serial.read(); 
    // see if a . is included.. 
   
    if(inChar == '\n'){
      
      
     float value=atof(inputString.c_str());
     
     Serial.println(value,6);
     Serial.println(inputString);
     value =0;
      
      
      inputString = "";
    }
    else
      inputString += inChar;
  }
}

@ Robin2, I'm looking over that demo now.. Thanks for posting it..

What I am trying to do is receive serial input from a computer of a Latitude and a Longitude on an ending point. Then using a gps shield to generate the starting position, pass on the numbers to the functions below.. which returns the heading degree and distance between the points..

double deg2rad(double deg) {
  return (deg * pi / 180);
}

float getHeading(float fLat, float fLng, float tLat, float tLng)
{
    float fLat1 = deg2rad(fLat);
    float fLng1 = deg2rad(fLng);
    float tLat1 = deg2rad(tLat);
    float tLng1 = deg2rad(tLng);

    float value= atan2(sin(fLng1-tLng1)*cos(tLat1), cos(fLat1)*sin(tLat1)-sin(fLat1)*cos(tLat1)*cos(fLng1-tLng1));         
    return rad2deg(value);

}
double rad2deg(double rad) {
  return (rad * 180 / pi);
}
double distanc(double lat1, double lon1, double lat2, double lon2, char unit) {
  double theta, dist;
  theta = lon1 - lon2;
  dist = sin(deg2rad(lat1)) * sin(deg2rad(lat2)) + cos(deg2rad(lat1)) * cos(deg2rad(lat2)) * cos(deg2rad(theta));
  dist = acos(dist);
  dist = rad2deg(dist);
  dist = dist * 60 * 1.1515;
  switch(unit) {
    case 'M':
      break;
    case 'K':
      dist = dist * 1.609344;
      break;
    case 'N':
      dist = dist * 0.8684;
      break;
  }
  return (dist);
}

Again, Thanks for your time and help!

The problem I'm having is when I convert the string to float with 6 digits to the right, it drifts a few numbers on the last digit....

That sounds about right for 32 bit floating point.

I guess that will have to be close enough lol.. it's only a few feet difference on both values... Thank you for your replies!