Arduino Forum

Using Arduino => Programming Questions => Topic started by: Nebula on Jan 02, 2012, 07:44 pm

Title: dtostrf() help
Post by: Nebula on Jan 02, 2012, 07:44 pm
Hi everyone,

I've written this code to send two floating points over the serial as a string, separated by a semi-colon. At the moment this code returns values like:
0.182710.4698 ; 10.4698
0.411215.7008 ; 15.7008
0.730820.9269 ; 20.9269

Which is basically XvalueYvalue ; Yvalue, whereas what I actually want is Xvalue ; Yvalue. How would I make it print in this way?

This is the code so far (ignore the maths, that's to convert servo angle and ping distance to an x and y value):

Code: [Select]
#include <Servo.h>
#include <math.h>

Servo myservo;

float xval;
float yval;
float rad;

int distance = 3;  //This is just to test the code, I'll add ping code later
int deg = 0;

char x [6];
char y [6];


void setup(){
 
 myservo.attach(9);
 Serial.begin(9600);
 
}


void loop(){
 while (deg <180){
   myservo.write(deg);
   rad = deg * 0.0174532925;
   xval = 300 - ((distance * cos(rad))*100);  
   yval = (distance * sin(rad)) * 100;
   dtostrf(xval, 6, 4, x);// This is where I get confused, I read that the 6 is the length of the number
   dtostrf(yval, 6, 4, y); // and that the 4 is the number of numbers after decimal point? I'm sure this is wrong?
   Serial.println(String(x) + " ; " + String(y));
   deg++;
 }

}


Thanks.
Title: Re: dtostrf() help
Post by: dc42 on Jan 02, 2012, 07:54 pm
1. Your character buffers x and y are 1 character too short, they need to be at least 1 character longer than the number of characters you are writing to them (to allow for the trailing null). Declare them as [7] instead of [6].

2. Don't use the String class (IMO it should not be part of the Arduino library). It will work OK when used in simple ways like this, but do something more complicated and you are likely to run out of RAM. Use this instead:

Code: [Select]

Serial.print(x);
Serial.print(" ; ");
Serial.println(y);
Title: Re: dtostrf() help
Post by: PaulS on Jan 02, 2012, 07:58 pm
Why are you using dtostrf() at all? The Serial.print() function is perfectly capable of sending a float to the serial port.
Title: Re: dtostrf() help
Post by: Nebula on Jan 02, 2012, 09:08 pm
@ dc42, thanks for the help, I never thought of writing out this way, that makes life much simpler!

@PaulS, I only needed them to try and write all the values as one string - writing them as floating point values works just as well when I'm using dc42's method of printing the values.

Thanks for the help :)
Title: Re: dtostrf() help
Post by: jamilm9 on Jan 04, 2012, 07:45 am
I have a question about dtostrf(). I am trying to get a temperature sensor (lm35) to send data using a ethernet shield to thingspeak. To send data to thingspeak, it must be a string.
Right now, I am converting a float to a long to a string. This however removes the decimal points (I think). I am trying to use dtostrf() to convert my float directly to a string so that there are decimal points.
Code: [Select]
int reading = analogRead(sensorPin);
  float voltage = reading * 5.0;
  voltage /= 1024.0; 
int  temperatureC = (voltage) * 100;
String temperatureS = dtostrf(temperatureC, 2, 2, 10);
String temperature = (tem, DEC);

However it fails to compile because it says "invalid conversion from 'int to 'char*'
Does anyone know how I can fix this?
Thank You
Title: Re: dtostrf() help
Post by: PaulS on Jan 04, 2012, 11:25 am
So, the first question is why you are using dtostrf to convert an int to a string. The dtostrf() function is to convert a double (or float) to a string.

The second question is whether or not you have read the documentation on dtostrf. It appears not.

Code: [Select]
char * dtostrf (double __val, signed char __width, unsigned char __prec, char *__s)
Quote
The dtostrf() function converts the double value passed in val into an ASCII representationthat will be stored under s. The caller is responsible for providing sufficient storage in s.

Conversion is done in the format "[-]d.ddd". The minimum field width of the output string (including the '.' and the possible sign for negative values) is given in width, and prec determines the number of digits after the decimal sign. width is signed value, negative for left adjustment.

The dtostrf() function returns the pointer to the converted string s.

10 is not a buffer that dtostrf can write to, is it?
Title: Re: dtostrf() help
Post by: jamilm9 on Jan 04, 2012, 06:15 pm
Sorry for the error. I accidentally had it converting a integer. I am pretty new to arduino programing and I am wondering if you would be able to tell me what to put after my float in the dtostrf()
If it is supposed to be dtostrf(FLOAT,WIDTH,PRECSISION,BUFFER);
I know the FLOAT in my case would be temperatureC but what would the WIDTH, PRECSISION and BUFFER be?
I read the dtostrf() documentation but I don't understand what it means.
Thank you for the help.
Title: Re: dtostrf() help
Post by: PaulS on Jan 04, 2012, 06:45 pm
WIDTH is the number of characters to use in the output. For a value in the range 0.000 to 5.000, the width should be the precision +2. More is OK.

PRECISION is the number of characters after the decimal point. For temperature, 1 would be sufficient.

BUFFER is where the write the characters to.

Code: [Select]
char buffer[10];
dtostrf(temperatureC, 5, 1, buffer);


There is no reason to make a String out of buffer.

Code: [Select]
String temperature = (tem, DEC);
This is rubbish. It looks like you took Serial.print(tem, DEC), and stripped the Serial.print off the front. You can't do that, and produce anything meaningful.
Title: Re: dtostrf() help
Post by: jamilm9 on Jan 04, 2012, 07:11 pm
Thank you for your help. I finally got it to work. This is the code which worked for me.
Code: [Select]
int reading = analogRead(sensorPin);
  float voltage = reading * 5.0;
  voltage /= 1024.0; 
float  temperatureC = (voltage) * 100;
char buffer[10];
String tem = dtostrf(temperatureC, 5, 2, buffer);
String temper = (tem);


Here is the chart: https://www.thingspeak.com/channels/1531/charts/2

Once again, thank you.
Title: Re: dtostrf() help
Post by: PaulS on Jan 04, 2012, 08:11 pm
What kind of temperature sensor are you using that discerns temperature variations as small as 0.01 degrees?

Why are you converting the char array to a String object?

Why are you then copying that String object?
Title: Re: dtostrf() help
Post by: davebaldwin on May 25, 2014, 11:58 pm
I am trying to use dtostrf to print out values to a Nokia 5110 LCD.

Here's a snippet of my code:
Code: [Select]

/* Get distance to the destination */
double distance_meters = TinyGPSPlus::distanceBetween(tinygps.location.lat(), tinygps.location.lng(), DEST_LATITUDE, DEST_LONGITUDE);
/* get bearing to destination */
double bearing = TinyGPSPlus::courseTo(tinygps.location.lat(), tinygps.location.lng(), DEST_LATITUDE, DEST_LONGITUDE);

Serial.print("Distance to dest: ");
Serial.println(distance_meters);     

// generate chars for easy printing
int dist_m_int = (int)distance_meters;
float dist_km = distance_meters / 1000.0;   
int dist_km_int = (int)dist_km;   
int bearing_int = (int)bearing;

// generate char arrays for printing to LCD screen
char m_buffer[sizeof(dist_m_int)+1];
char km_buffer[sizeof(dist_km_int)+1];
char brng_buffer[sizeof(bearing_int)+1];

dtostrf(distance_meters, 1, 0, m_buffer);
dtostrf(dist_km, 1, 0, km_buffer);
dtostrf(bearing, 1, 0, brng_buffer);



What I'm seeing (and can verify in the serial monitor) is that the distance_meters value coming out of the GPS function is reasonable (say, ~2017 kilometres), but then m_buffer seems to get a value of ~20137. I've tried this for several different locations (i.e. different distances) and I am consistently getting values in the char buffer that are off by a factor of 10.

However, brng_buffer content, however, is exactly as expected. Which seems ridiculous to me since the instructions processing the distance_meters and bearing values look to be exactly the same.

Any ideas?  I've been stuck on this for a couple of days.  Thanks in advance.
Title: Re: dtostrf() help
Post by: PaulS on May 26, 2014, 01:52 am
Frankly, printing a float to zero decimal places looks pretty stupid. Just use ints if you don't want the accuracy of the float.
Title: Re: dtostrf() help
Post by: davebaldwin on May 26, 2014, 02:28 am

Frankly, printing a float to zero decimal places looks pretty stupid.

Thanks!

Just use ints if you don't want the accuracy of the float.

Use ints where? The dtostrf function documentation indicates a double (same as float) is required as the first argument. Can I pass in an int instead?
I am using the sizeof(int var) to size the char buffers because I only want to see integers on the LCD.
Title: Re: dtostrf() help
Post by: PaulS on May 26, 2014, 02:38 am
Quote
Can I pass in an int instead?

You could, but why?

Quote
I am using the sizeof(int var) to size the char buffers because I only want to see integers on the LCD.

Why, then, do you need to use floats? Why do you need to use dtostrf()? Just use the print() method of the LCD class to print to the LCD, whether you are printing floats or ints.
Title: Re: dtostrf() help
Post by: davebaldwin on May 26, 2014, 02:41 am
The LCD library I'm using won't print floats. I need to pass in a character array.
Title: Re: dtostrf() help
Post by: PaulS on May 26, 2014, 04:10 am
Quote
The LCD library I'm using won't print floats.

But, you don't want to print floats.
Title: Re: dtostrf() help
Post by: Nick_Pyner on May 26, 2014, 04:16 am

The LCD library I'm using won't print floats. I need to pass in a character array.


That is either nonsense, or time to move to a proper library. It is definitely time to be more forthcoming with your code.

If you want to print floats, you should be able to so - without dtostrf().
I have never been able to understand why there has ever been a need for this float to string conversion stuff, or why anybody thinks they need it now. I can only assume it is some nasty legacy from the past when Arduino was incapable of handling floats.

The only time I have ever seen a need for Arduino to feed strings was when a receiving non-Arduino programme demanded it  I'm not aware of any hardware device that demands to be fed with strings.

Another thread is here   http://forum.arduino.cc/index.php?topic=212255.msg1558900#msg1558900
Title: Re: dtostrf() help
Post by: mrthekod on Jul 13, 2015, 12:29 pm
I used dtostrf to pass an integer to a routine I wrote. It requires a char array that I then use chop each letter into vertical stripes to display on an LED cube.

Worked a treat for me. Kept me away from using String.
Title: Re: dtostrf() help
Post by: PaulS on Jul 13, 2015, 12:35 pm
Quote
I used dtostrf to pass an integer to a routine I wrote.
Why would you use double to string, formatted to deal with an integer?
Title: Re: dtostrf() help
Post by: mrthekod on Jul 13, 2015, 12:42 pm
Because it worked perfectly, I was planning on looking in to other more appropriate options later.

What would you use to tun an int into char array? I'm guessing there is itostrf, I didn't bother checking as this worked, and it was 4am, I was grumpy and I was calling this a win.
Title: Re: dtostrf() help
Post by: odometer on Jul 13, 2015, 12:48 pm
I used dtostrf to pass an integer to a routine I wrote.
Why? There are other ways, such as the sprintf function.
http://www.cplusplus.com/reference/cstdio/sprintf/ (http://www.cplusplus.com/reference/cstdio/sprintf/)
(Tip: Arduino won't let you use sprintf on floats, but integers are OK.)
Title: Re: dtostrf() help
Post by: odometer on Jul 13, 2015, 12:52 pm
What would you use to tun an int into char array? I'm guessing there is itostrf, I didn't bother checking as this worked, and it was 4am, I was grumpy and I was calling this a win.
I might, too, if it were 4 a.m. and I were grumpy.

But for myself, I use sprintf() or else arithmetic. And by arithmetic, I mean use division and modulus to get at the values of the digits, then add '0' (with single quotes) to each digit to convert it to a character.
Title: Re: dtostrf() help
Post by: chupo_cro on Feb 08, 2017, 12:42 am
I have never been able to understand why there has ever been a need for this float to string conversion stuff, or why anybody thinks they need it now. I can only assume it is some nasty legacy from the past when Arduino was incapable of handling floats.
Because sometimes you have to build the string so you can calculate the length to be able to make a POST request as mentioned in:

http://forum.arduino.cc/index.php?topic=85523.msg641844#msg641844 (http://forum.arduino.cc/index.php?topic=85523.msg641844#msg641844)
Title: Re: dtostrf() help
Post by: jimLee on Feb 08, 2017, 04:21 am
Umm, you do realize your answering a question that was asked 2-3 years ago, right?

-jim lee
Title: Re: dtostrf() help
Post by: chupo_cro on Feb 11, 2017, 08:29 pm
Quote from: jimLee (http://"http://\"http://forum.arduino.cc/index.php?msg=3121408"") Wed Feb 08 2017 04:21:34 GMT+0100 (Central European Standard Time)
Umm, you do realize your answering a question that was asked 2-3 years ago, right?

-jim lee
Yes I do. Is that a problem? I've found this thread when I was looking for some info about using floats with sprintf() and dtostrf() on avrlibc so there is a chance someone in the future will read this thread to find some useful infromation. I think the purpose of forum posts is (among the others) to be used as a knowledge base.

In fact, I created the account 2 years ago when I noticed a thread which was full of wrong informations (it was something related to millis() if I remember correctly) but then in the and I did not post anything.