Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Displaying float value with more than 4 decimal points on LCD

Status
Not open for further replies.

ADGAN

Full Member level 5
Joined
Oct 9, 2013
Messages
295
Helped
4
Reputation
8
Reaction score
4
Trophy points
18
Activity points
1,837
Hi! I want to display a float value with more than 4 decimal points on the LCD display. I'm using MikroC pro. I tried floattostr function but it only displays one decimal point. After that it shoes like ' e-2'. The sprintf function is also not available since I'm using PIC16F887.
 

The sprintf function is also not available since I'm using PIC16F887.
I dont know much about mikroc (i tried it briefly a few years back), but i dont think the availability of sprintf() is limited by which PIC you are using.

Mikroc has sprintf. Use it
 

hi ,
how much programming would you like to ad for this section ? There are other ways to do this when fancy functions are not available ......
for example :
let's say you have V=12.3456; and some variables declared : char a,b,d1,d2,d3,d4; float n;
then you do a=V/10; b=V-(10*a); n=(V-(10*a)-b)*10000; d1=n/1000;d2=(n-(d1*1000))/100; d3=(n-(d1*1000)-(d2*100))/10;d4=n-(d1*1000)-(d2*100)-(d3*10);
(cast is done automatically) ,
so now you actually have a=1,b=2,d1=3,d2=4,d3=5,d4=6, and to display them in ascii character format you just send them in order to the lcd after adding 48 to each .
Of course this is not the best way for the little mcu (specially when other fast tasks needed ), but if you like math .... make a complicated program.
 
Last edited:
  • Like
Reactions: ADGAN

    ADGAN

    Points: 2
    Helpful Answer Positive Rating
Isn't there a function that I can use for this task. It would be much easy. I found this in the internet.

Code:
int float_to_char(char *buff, int start_pos, float fnum, short dec)
{
    long i;
    int pos, k;
   
    if(fnum < 0) {
        buff[start_pos++] = '-';
        fnum *= -1;
    }
   
    i = fnum;
   
    pos = long_to_char(buff, start_pos, i);
    buff[pos++] = '.';

    fnum -= i;
    fnum *= pow10l(dec);
    i = fnum;

    pos += dec;
    for(k = dec; k > 0; k--){
        buff[--pos] = 48 + (i % 10);
       
        i /= 10;
    }

    return pos + dec;
}

int long_to_char(char *buff, int start_pos, long inum)
{
    char n, k;
    long div = 1000000000;

    if(inum < 0) {
        buff[start_pos++] = '-';
        inum *= -1;
    }

    for(k = 0; k < 10; k++)
    {
        n = (inum / div) % 10;

        if(n > 0) break;

        div /= 10;
    }

    buff[start_pos++] = 48 + n;
    k++;
    div /= 10;

    for(; k < 10; k++)
    {
        n = (inum / div) % 10;
        buff[start_pos++] = 48 + n;

        div /= 10;
    }

    return start_pos;
}

long pow10l(short p)
{
    switch(p)
    {
        case 1: return 10l;
        case 2: return 100l;
        case 3: return 1000l;
        case 4: return 10000l;
        case 5: return 100000l;
        case 6: return 1000000l;
        case 7: return 10000000l;
        case 8: return 100000000l;
        case 9: return 1000000000l;
        default: return 1;
    }
}

https://www.mikroe.com/forum/viewtopic.php?f=88&t=24842

But the problem is it this values goes all around the display.
 

Isn't there a function that I can use for this task. It would be much easy. I found this in the internet.

Code:
int float_to_char(char *buff, int start_pos, float fnum, short dec)
{
    long i;
    int pos, k;
   
    if(fnum < 0) {
        buff[start_pos++] = '-';
        fnum *= -1;
    }
   
    i = fnum;
   
    pos = long_to_char(buff, start_pos, i);
    buff[pos++] = '.';

    fnum -= i;
    fnum *= pow10l(dec);
    i = fnum;

    pos += dec;
    for(k = dec; k > 0; k--){
        buff[--pos] = 48 + (i % 10);
       
        i /= 10;
    }

    return pos + dec;
}

int long_to_char(char *buff, int start_pos, long inum)
{
    char n, k;
    long div = 1000000000;

    if(inum < 0) {
        buff[start_pos++] = '-';
        inum *= -1;
    }

    for(k = 0; k < 10; k++)
    {
        n = (inum / div) % 10;

        if(n > 0) break;

        div /= 10;
    }

    buff[start_pos++] = 48 + n;
    k++;
    div /= 10;

    for(; k < 10; k++)
    {
        n = (inum / div) % 10;
        buff[start_pos++] = 48 + n;

        div /= 10;
    }

    return start_pos;
}

long pow10l(short p)
{
    switch(p)
    {
        case 1: return 10l;
        case 2: return 100l;
        case 3: return 1000l;
        case 4: return 10000l;
        case 5: return 100000l;
        case 6: return 1000000l;
        case 7: return 10000000l;
        case 8: return 100000000l;
        case 9: return 1000000000l;
        default: return 1;
    }
}

https://www.mikroe.com/forum/viewtopic.php?f=88&t=24842

But the problem is it this values goes all around the display.

this is not fast, and uses more of memory
 

Ok thanks then I'll your way
 

hello

with C18 MPLAB i use this

Code:
#ifndef Byte
#define Byte unsigned char
#endif
#ifndef Word
#define Word unsigned int
#endif
#ifndef DWord
#define DWord unsigned long
#endif

float f1,f2,f3;
Byte CRam1[32];
Word EAx;


 unsigned char *fltToa (float x, unsigned char *str,char precision)
{
/* converts a floating point number to an ascii string */
/* x is stored into str, which should be at least 30 chars long */
unsigned char *adpt;
int ie, i, k, ndig;
double y;
adpt=str;
ndig = ( precision<=0) ? 7 : (precision > 22 ? 23 : precision+1);
ie = 0;
/* if x negative, write minus and reverse */
if ( x < 0)
  {
  *str++ = '-';
  x = -x;
  }
 else  *str++ = ' '; // rajoute espace pour le signe + 
 
/* put x in range 1 <= x < 10 */
if (x > 0.0) while (x < 1.0)
  {
  x *= 10.0;		// a la place de =*
  ie--;
  }
while (x >= 10.0)
  {
  x = x/10.0;
  ie++;
 }

// in f format, number of digits is related to size 
 ndig += ie;				// a la place de =+
//round. x is between 1 and 10 and ndig will be printed to
// right of decimal point so rounding is ... 
for (y = i = 1; i < ndig; i++)
  y = y/10.;
x += y/2.;					
if (x >= 10.0) {x = 1.0; ie++;} 
if (ie<0)
  {
   *str++ = '0'; *str++ = '.';
   if (ndig < 0) ie = ie-ndig;
   for (i = -1; i > ie; i--)  *str++ = '0';
  }
for (i=0; i < ndig; i++)
  {
  k = x;
  *str++ = k + '0';
  if (i ==  ie ) *str++ = '.';
  x -= (y=k);	
  x *= 10.0;	
  }
*str = '\0';
return (adpt);
}
 




void main()
{

.........


	//T°Ext LM335 2730mV at 0°C:
	EAx=Mesure_ADC(0);
	f1=(float) (EAx)*0.40000-273.0;  // Vref = 4.096V
// *fltToa (float x, unsigned char *str,char precision)
	 k=fprintf(_H_USART,"T°Ext:%4d  %s°C ;",EAx,fltToa(f1,CRam1,2));

.......

so, you can adjust nb of decimal...
nota: _H_USART is UART RS232 output,
but the resulting string is in CRam table, ready to use with a LCD..
 

Here is a "brute-force" method for displaying a float variable to lcd

Code:
//Display float value with 3 decimal places to LCD.
void FloatToLCD(float fval)
{
	unsigned int value_x1000;
	char digit;
                                                         //Ex. fval = 34.576
	value_x1000 = (unsigned int)(fval * 1000);	 // value_x1000 = 34576

	digit = (value_x1000/10000)%10;		
	lcd_putch('0'+digit);				         //Display '3'
	digit = (value_x1000/1000)%10;
	lcd_putch('0'+digit);				         //Display '4'
	lcd_putch('.');						 //Display '.'
	digit = (value_x1000/100)%10;
	lcd_putch('0'+digit);				         //Display '5'
	digit = (value_x1000/10)%10;
	lcd_putch('0'+digit);				         //Display '7'
	digit = (value_x1000)%10;
	lcd_putch('0'+digit);				         //Display '6'
	return;
}
 

Thanks for the reply everybody. But I want to display more than 3 decimal places.

@paulfjujo
How do I use your function in the main?
 

As an alterantive solution to handmade floatoascii, you can convert your float number to a decimal fixed point number, e.g. multiply with 10000 for 4 fractional digits and use LongintToStr() for the conversion, then manually insert a decimal point.
 

I want to display a variable not a constant therefore I would not know the value.
 

every way that solves your problem is ok...
You say that with the method you find on the net , the display is filled continuously ... i suspect that happens because you not clear the display at the beginning of the display sequence .
I suggest that before you update the displayed data , you should do a clear screen sequence. I don't remember exactly the instruction to most commonly used lcd's , but i know that there is an instruction that performs clear screen and returns the cursor to the begin of the first line. If the display is still dizzy , put a delay in your program loop. In practice if your loop is executed very quickly, it may be a problem too, because the refresh rate of the display is to quick (it's own mcu needs some time to do the work...).
best regards

z

Ps: the code in post 8 uses the same idea , modify it for your needs and you have the solution :lol:
 
Last edited:

Thanks for the reply. Not the whole display. after printing 0.0000 in the next column again it prints 0.0000 then goes to next line. I'm clearing the display at the very beginning.
 

Thanks for the reply. Not the whole display. after printing 0.0000 in the next column again it prints 0.0000 then goes to next line. I'm clearing the display at the very beginning.
______________
| 0.0000 0.0000 |
|0.0000 0.0000 |
|_____________|
?

anyway , the solution is simple , after displaying 0.0000 put a break instruction to stop and get beck to main.

Ps: the modification to the code from post8 should look like this:
(i am not shore about overflows, and i can't remember what does the % operator ):

Code:
void FloatToLCD(float fval)
{
	 int value;
	char digit;
                                         //Ex. fval = 34.5769
	value= fval * 10000;	 // value= 345769
	digit = (value/100000)%10;		
	lcd_putch('0'+digit);				         //Display '3'
	digit = (value/10000)%10;
	lcd_putch('0'+digit);				         //Display '4'
	lcd_putch('.');						 //Display '.'
	digit = (value/1000)%10;
	lcd_putch('0'+digit);				         //Display '5'
	digit = (value/100)%10;
	lcd_putch('0'+digit);				         //Display '7'
	digit = (value/10)%10;
	lcd_putch('0'+digit);				         //Display '6'
        digit = (value)%10;
	lcd_putch('0'+digit);				         //Display '9'
	return;
}
 
Last edited by a moderator:

void FloatToLCD(float fval)
{
int value;
char digit;
//Ex. fval = 34.5769
value= fval * 10000; // value= 345769
.. etc ....

}

value must be a long int , because 345769 overload the capacity of an integer (16bits)
and use of cast before calculus.

Code:
...
unsigned long int value;
value= (unsigned long int) (fval * 10000.0);	 // value= 345769
...

if negative value to treat, use signed long int ..
 

Its only shows the '.'
 

and what does the % operator?

- - - Updated - - -

Its only shows the '.'

try to remove the %10 and do paulfjujo's inications regarding the overflow (i think that cast is donne automatically by the compiler since you have diferent datatypes at the = operator), tel us what happens
 

I'll post the code

Code:
float y = 0.3244;
void FloatToLCD(float fval)
{
	unsigned long int value_x1000;
	char digit;
                                                         //Ex. fval = 34.576
	value_x1000 = (unsigned long int)(fval * 1000);	 // value_x1000 = 34576

	digit = (value_x1000/10000)%10;
	Lcd_chr(4,3,0+digit);				         //Display '3'
	digit = (value_x1000/1000)%10;
	Lcd_chr(4,4,0+digit);				         //Display '4'
	Lcd_chr_cp('.');						 //Display '.'
	digit = (value_x1000/100)%10;
	Lcd_chr(4,6,0+digit);				         //Display '5'
	digit = (value_x1000/10)%10;
	Lcd_chr(4,7,0+digit);				         //Display '7'
	digit = (value_x1000)%10;
	Lcd_chr(4,8,0+digit);				         //Display '6'
	return;
}
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top