Extract digits from a float to seperate integers

Hey!

I am going to send battery voltage 3.20 - 4.20 voltage with two decimal places over serial. To do this I need to send each digit (3, 2, 0 = 3.20) for example as three seperate bytes. I know I can use the library to extract the integer part and the fractional parts but how can I make 0.20 into "2" and "0"?

Thanks!

Just use serial.print. Conveniently for you, for floats it defaults to two decimal places.

wildbill:
Just use serial.print. Conveniently for you, for floats it defaults to two decimal places.

I am going to send it over Bluetooth-serial so I can't do it that way:)

Use sprintf() to write the float into a char buffer with the desired number of decimal places.

but how can I make 0.20 into "2" and "0"?

Simple arithmetic.

Marius1992:
I am going to send it over Bluetooth-serial so I can't do it that way:)

Why not ?
Which Arduino are you using ?

 . // Shift the decimal point right two digits and round off to an integer.
  int value = (voltage * 100.0) + 0.5; 
  // Extract each digit with the 'modulo' operator (%)

  char hundredsDigit = '0' + ((value / 100) % 10);
  char tensDigit =  '0' + ((value / 10) % 10);
  char onesDigit =  '0' + (value % 10);

gfvalvo:
Use sprintf() to write the float into a char buffer with the desired number of decimal places.

Oops, forget that idea as sprintf's handling of floats is disabled by default. Use dtostrf().

Or, if your BlueTooth library inherits from Stream, just use print() as suggested by @wildbill.

Marius1992:
I am going to send it over Bluetooth-serial so I can't do it that way:)

I have very little experience with BT but the little I have used SoftwareSerial which I thought had the same methods as Serial?

So:

SoftwareSerial BTserial(2,3);

...and later can't you go:

BTserial.print(foo);

?

johnwasser:

 . // Shift the decimal point right two digits and round off to an integer.

int value = (voltage * 100.0) + 0.5;
 // Extract each digit with the 'modulo' operator (%)

char hundredsDigit = '0' + ((value / 100) % 10);
 char tensDigit =  '0' + ((value / 10) % 10);
 char onesDigit =  '0' + (value % 10);

This is exactly what I needed, thank you!

The things is I am extracting the data as bytes in an iOS app and it recognizes the different data in a string of data with command bytes, so I need to deconstruct the info for the app to understand it in my protocol. Thank you all!

int value = (voltage * 100.0) + 0.5;

(a) Couldn't find the reason of adding 0.50?
(b) Couldn't find the reason of multiply by 100.0 and not by 100?

char hundredsDigit = '0' + ((value / 100) % 10);
char tensDigit = '0' + ((value / 10) % 10);
char onesDigit = '0' + (value % 10);

Any good reason to choose data type char instead of byte?

(a) Couldn't find the reason of adding 0.50?

Rounding. (up)

Any good reason to choose data type char instead of byte?

Because that's the correct type for an ASCII character

AWOL:
Rounding. (up)

When I remain with the given input range of 3.20 - 4.20, I don't see any need of rounding up as the the range will turn to 320 - 420 after being multiplied by 100.0.

If someone thinks the input range 3.20 - 4.20 as 3.200 - 3.299 - 4.197 - 4.200, then we need rounding up (3.299*100.0 = 329.9 + 0.5 = 330).

GolamMostafa:
When I remain with the given input range of 3.20 - 4.20, I don't see any need of rounding up as the the range will turn to 320 - 420 after being multiplied by 100.0.

Note that the range 3.20 to 4.20 contains all the numbers in between, including 3.99999... I guessed that the OP would want to round to the nearest value with two decimal places (4.00) rather than truncate to 3.99.

GolamMostafa:
(b) Couldn't find the reason of multiply by 100.0 and not by 100?

In order to hold decimal places, 'voltage' must be a float (or double) variable. Using the integer literal '100' would not prevent the promotion from integer to float so either way the multiplication is by 100.0. It is more self-documenting to use the float literal '100.0' rather than to rely on the readers knowledge that a) 'voltage' is a float and b) the '100' will therefore be promoted to float.

johnwasser:
In order to hold decimal places, 'voltage' must be a float (or double) variable. Using the integer literal '100' would not prevent the promotion from integer to float so either way the multiplication is by 100.0. It is more self-documenting to use the float literal '100.0' rather than to rely on the readers knowledge that a) 'voltage' is a float and b) the '100' will therefore be promoted to float.

With example, we can justify the inclusion of the factor 0.5 in your equation. I have been trying to find out a data which when multiplied by 100 will not lead to expected/correct result.