# Number Breakdown

#### TucsonDon

##### Member
I have a ADC result that I am converting to a float. I want to display on a 4 digit 7 segment display via a BCD decoder. How do I break the float into 100’s, 10’s, 1’s and 10th’s to convert to BCD for the decoder

#### Nigel Goodwin

##### Super Moderator
Why do you want to convert it to a float?, the original value from the ADC isn't a float, and the display isn't a float - so why?.

You might also consider mentioning what language you're using?. If it's PIC assembler you could check my tutorials.

#### gophert

##### Well-Known Member
I have a ADC result that I am converting to a float. I want to display on a 4 digit 7 segment display via a BCD decoder. How do I break the float into 100’s, 10’s, 1’s and 10th’s to convert to BCD for the decoder
Try to avoid float. If you have a 10-bit ADC value (0-1023 counts), and a 5v reference voltage, then I assume you want to display volts.

So if you measure 330 counts, you'd calculate 5 * 330 / 1023 = 1.651 volts. However,
You can also say 5000 * 330 / 1023 = 1651

Int t = result / 1000

Int h = (result - t * 1000) / 100

Int tens = ((result - t * 1000) - 100 * h) / 10

Int ones = result % 10

Then you add the decimal point to the first digit.

Last edited:

#### tumbleweed

##### Active Member
So if you measure 330 counts, you'd calculate 5 * 330 / 1023 = 1.651 volts. However,
You can also say 5000 * 330 / 1023 = 1651
Not to be too picky, but I think maybe your calculator needs a new battery.

Also two things... technically you should be dividing by 1024, not 1023,
and you must make sure that 5000 * ADREADING doesn't overflow the data type you're using.

#### nsaspook

##### Well-Known Member
I have a ADC result that I am converting to a float. I want to display on a 4 digit 7 segment display via a BCD decoder. How do I break the float into 100’s, 10’s, 1’s and 10th’s to convert to BCD for the decoder
Don't be afraid to to use floats sparingly if the system has the resources, timing is not critical and fractional scaling is a requirement to make a standard internal data integer storage type (10th's of X parameter) for later processing.

#### TucsonDon

##### Member
nsaspook not sure I understand your point

#### nsaspook

##### Well-Known Member
nsaspook not sure I understand your point
A quick example with made-up numbers:
Read your ADC at some calibrated temp, offset and scale that binary result to a calibrated float (1234.0 10th's of) of the required decimal reading of the needed temperature standard. You can use that float directly or convert it to a properly sized integer to extract the 100’s, 10’s, 1’s and 10th’s to convert to BCD using the modulus operator.
C:
#include <stdio.h>
int main()
{
int n = 7569;
int th,h,t,u;  // Thousands,hundreds,tens,units

u=n%10;
t=(n/10)%10;
h=(n/100)%10;
th=n/1000;
printf("Thousands = %d , Hundreds = %d , Tens = %d , Units = %d\n",th,h,t,u);

return 0;
}

#### Nigel Goodwin

##### Super Moderator
Nigel Goodwin & gophert in am using the ADC to read temperature from a thermistor to a tenth of a degree. Nigel Goodwin I'm using c in MPLab
So no need whatever for floats - which are MUCH slower, take MUCH more memory (neither of which are really a problem in your case) and also less accurate - just do it in integers and manually add a decimal point in the display routine - as in my assembler tutorial routines.

Here's a little clip of how I do it in C - the 4 digit number is split into the four separate digits and printed to the LCD in turn, adding the decimal point in the right place. LCD_charD simply converts the number to ASCII

C:
LCD_charD(Thou);
LCD_charD(Hund);
LCD_charD(Tens);
LCD_char(46);                //decimal point
LCD_charD(Ones);

void LCD_charD(unsigned char ch)
{
ch+=0x30;
LCD_char(ch);                           // convert to ascii
}

#### nsaspook

##### Well-Known Member
All integers with 7 or fewer decimal digits, and any 2n for a whole number −149 ≤ n ≤ 127, can be converted exactly into an IEEE 754 single-precision floating-point value.

#### Pommie

##### Well-Known Member
I did this recently and it's practically identical to nsaspook's, slightly modified to meet your needs,
Code:
/*
* assuming the value is to be converted to 5V
* with 1 decimal place
*/
uint32_t total;
uint8_t tenths,units,tens,hund;
total=dat*5000;         //multiply by millivolts
total>>=10;             //divide by ADC resolution (1024)
tenths=total%10+0x30;
total/=10;
units=total%10+0x30;
total/=10;
tens=total%10+0x30;
total/=10;
hund=total+0x30;
}
Mike.
Edit, just realized the above will give the ascii character. For the individual numbers delete the 0x30 on each line.

#### rjenkinsgb

##### Well-Known Member
That's pretty much how I'd do it; the only change I would suggest is using another variable, an INT or unsigned int (16 bit value) to store the result of the ten bit shift, and for the maths from then on;
eg. Pommie's code, tweaked slightly:

C:
/*
* assuming the value is to be converted to 5V
* with 1 decimal place
*/
uint32_t total;

unit16_t totint;

uint8_t tenths,units,tens,hund;
total=dat*5000;         //multiply by millivolts

totint = total >> 10;             //divide by ADC resolution (1024)

tenths=totint%10+0x30;
totint/=10;
units=totint%10+0x30;
totint/=10;
tens=totint%10+0x30;
totint/=10;
hund=totint+0x30;
}
The number being worked on is back into a suitable range for 16 bit maths after the bit shift, so avoiding the 32 bit calculations should make it rather faster and the code more compact.

#### Pommie

##### Well-Known Member
Yup, that'll make it quicker and and use less memory.

Mike.

#### tumbleweed

##### Active Member
Code:
uint32_t total;
uint16_t dat;

total=dat*5000;         //multiply by millivolts
With most 8-bit C compilers that isn't going to give you a (correct) 32-bit result... it'll do a 16x16 multiply to get a 16-bit result and then promote that to 32-bit.

Tell it you want a 32-bit result...
Code:
total=dat*5000ul;         //multiply by millivolts

#### TucsonDon

##### Member
rjenkinsgb & Pommie thanks for your information but I am reading the ADC through a thermistor for temperature, so not sure how to apply it.

C:
double TempConversion (int TempResult)
{
double Temp;

Temp = log(10000.0*((1024.0/TempResult-1)));
//         =log(10000.0/(1024.0/RawADC-1)) // for pull-up configuration
Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
Temp -= 273.15;            // Convert Kelvin to Celcius
return Temp;
}
I am taking the result and type casting to a float to display remotely on a LCD and locally on a four digit 7 segment(that I'm driving w/ a BCD decoder) display to the tenth of a degree.

#### gophert

##### Well-Known Member
rjenkinsgb & Pommie thanks for your information but I am reading the ADC through a thermistor for temperature, so not sure how to apply it.

C:
double TempConversion (int TempResult)
{
double Temp;

Temp = log(10000.0*((1024.0/TempResult-1)));
//         =log(10000.0/(1024.0/RawADC-1)) // for pull-up configuration
Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
Temp -= 273.15;            // Convert Kelvin to Celcius
return Temp;
}
I am taking the result and type casting to a float to display remotely on a LCD and locally on a four digit 7 segment(that I'm driving w/ a BCD decoder) display to the tenth of a degree.
Stop thinking of it as a float. You can display as a string and cram a decimal point anywhere you want.

#### Pommie

##### Well-Known Member
I think with those equations I'd stick to float. To display it, multiply by 10, cast to integer and use the code above.

Mike.

#### rjenkinsgb

##### Well-Known Member
If you have a device with more than 2K program memory spare, pre-calculate the result for each of the 1024 possible ADC results using a program on a PC or a spreadsheet etc., to give a four digit result in 10ths of a degree for every value.

Save those as four BCD digits per 16 bit word in a look-up table array.
(I format look-up tables in a header file I can include - I use them for such as sine tables or other conversions that have a finite input range that's not too large, fonts etc).

Then in the device program, just use the ADC result as an index in to the table and display the four digits from that word location with a decimal point before the last.
No longs, floats or complex maths in the device at all.