Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Converting a ADC value to decimal and put it on the LCD

Status
Not open for further replies.

SneaKSz

Member
Hello , I've can read successfully the value of a ADC input and also write data to the LCD, only the binary to decimal is the part where I am getting mad.

Code:
#include <p18f14k50.h> 
#include <xlcd.h>
#include <delays.h>
//#include <usart.h>
//#include <htc.h>
//#include <pic18f1xk50.h> 
# include <string.h>


	#pragma config    CPUDIV = NOCLKDIV
	#pragma config    USBDIV = OFF  
	#pragma config    FOSC = HS
	#pragma config    PLLEN = OFF 
	#pragma config    FCMEN = OFF
	#pragma config    IESO = OFF 
	#pragma config    PWRTEN = ON
	#pragma config    BOREN = ON
	#pragma config    BORV = 30
	#pragma config    WDTEN = OFF
	#pragma config    WDTPS = 1
	#pragma config    MCLRE = ON
	#pragma config    HFOFST = ON 
	#pragma config    STVREN = ON 
	#pragma config    LVP = OFF
	#pragma config    BBSIZ = OFF 
	#pragma config    XINST = OFF
	#pragma config    CP0 = ON 
	#pragma config    CPB = ON 
	#pragma config    CPD = ON 
	#pragma config    WRT1= ON 
	#pragma config    WRTB = ON 
	#pragma config    WRTC = ON 
	#pragma config    WRTD = ON 
	#pragma config    EBTRB = ON
	


    #define LCD_PORT	LATC		//	;set constant LEDPORT = 'PORTB'
    #define LCD_TRIS	TRISC		//	;set constant for TRIS register
	
				//;LCD handshake lines
	#define LCD_RS LATCbits.LATC4
	#define LCD_RW LATCbits.LATC6
	#define LCD_E  LATCbits.LATC7

	unsigned char   D0;// low decimal of the decimal value 
	unsigned char  D1;
	unsigned char   D2;
	unsigned char   D3;
	unsigned char lcdc[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
// array with correct hex code for 0,1,2,3,4,5,6,7,8,9
	unsigned int H; // high byte ADRESH
	unsigned int L; 
void Conversion( float ); 
void Output();
void LCD_Init();
void ADC_Init();
void ADC_Go();
void LCD_Char(unsigned char);
void LCD_Cmd(unsigned char);
void writeEE(unsigned char addrH,unsigned char addrL,unsigned char data);
void main(void)
{
unsigned long ad_val;
float ADCV;

	OSCCON =62; //set internal clock to 4MHz
  	LCD_TRIS = 0;  //	set PortC all outputs
  	LCD_PORT = 0;		//all outputs are low 
	TRISBbits.TRISB4=1;// input
	ANSELHbits.ANS10=1;////Set RB4 to analog (ANS10) 
	Delay10KTCYx(30); // wait 100ms ,t = 333ns => 100ms = 300.000 cycles
	LCD_Init(); // init the LCD
	ADC_Init(); // init the ADC

while(1)
{

	ADC_Go(); // get binary value
	ad_val = H;// store high byte
	ad_val = (H << 8 )| L; // add both bytes together 
	ADCV = (float) (ad_val )*(4.8828125); // get a correct value with reference to 5V.(5000/1024)
	Conversion ( ADCV); // get each decimal of ADCV
	Output();
//	LCD_Char(0x56);'V'
}
}


void Conversion ( float value)
{
unsigned int test = value; // float => int
D3=value/1000; // high decimal 
D2 = (test - (D3*1000.0))/100;// secong highest  decimal
D1= (test) - ((D3*1000.0)+(D2*100.0)); 
D1=D1/10;//second lowest 
D0= (test) - ((D3*1000.0)+(D2*100.0)+(D1*10)); // lowest decimal 
}

void Output()
{

LCD_Char(lcdc[D3]); // get the correct LCD char end send it to the LCD 
LCD_Char(lcdc[D2]);
LCD_Char(lcdc[D1]);
LCD_Char(lcdc[D0]);

}


void ADC_Init()
{
		ADCON2 = 0b10101110 ;//right justify, Frc/64 , 12Tad
		ADCON1=0b00000000 ;//ADC ref = Vdd,Vss boven- en onderste venster
	//	LATBbits.LATB4=1;//Set RB4 to analog (ANS10) 
		ADCON0 = 0b00101001 ;//AN10, ADC on
}		

void ADC_Go()
{
	ADCON0bits.GO =1 ;//Start conversion
//ADCPoll:
	while(ADCON0bits.DONE==1); //Is conversion done?
	//	; Result is complete - store 2 MSbits in
	H=ADRESH;
	L=ADRESL;
}

void writeEE(unsigned char addrH,unsigned char addrL,unsigned char data)
{
  	EEADRH = addrH;
  	EEADR =addrL;
  	EEDATA = data;

  	  	//following as per spec. sheet
  	EECON1bits.EEPGD =0;
  	EECON1bits.CFGS =0;
  	EECON1bits.WREN =1; 
 	INTCONbits.GIE = 0;
  	EECON2 = 0x55;
  	EECON2 = 0xAA; 
 	EECON1bits.WR = 1;
  	INTCONbits.GIE = 1;
  	EECON1bits.WREN = 0;
}

The delay routine works fine , its only the binary to decimal routine : the while (1) and Conversion ( ADCV). The LCD_Char() routine works perfect , I think the conversion() routine doesnt work , I want to get each decimal of the 10 bit ADC value by using INT's and store them in Dx , and then use that number to locate the correct hex number in the array lcdc . Then I send this number to LCD_Char().

When I use this program I get a weird characterson the output that doesn't change when I change the voltage on the ana input.

Can someone spot this minor mistake ?

Thanks in advance !
 
You're assigning a float to an int without converting it first. That's the problem.

Hi thanks for your reply , so I need to typecast it to int
Code:
unsigned int test = (int) value; // float => int

Long time ago I had java/c++
 
I can't see anything wrong with your code but it does seem overly complicated. Why not use the built in function itoa()? I also don't like (especially the C18 implementation) of floats.

Try simplifying it to,
Code:
unsigned char buffer[5], i;
    ADC_Go();                   //do conversion
    ad_val=(ADRESH<<8)+ADRESL;  //get value
    ad_val*=(4.8828125*256);    //scale it
    ad_val+=128;                //rounding
    ad_val/=256;                //adjust back to int
    itoa((int)ad_val,buffer);   //convert it
    i=0;                        //print it
    while(buffer[i]){
        LCD_Char(buffer[i]);
        i++;
    }
You don't state your clock speed so I couldn't check you acquisition and conversion times were correct but it is unusual to get static readings so it maybe hardware related.

Edit, missed the float to int error. See, told you I didn't like them.:D
Edit2, Just tried this and it worked as expected.
Code:
    ADCV=1234.5678;
    ad_val=ADCV;
Mike.
 
Last edited:
I can't see anything wrong with your code but it does seem overly complicated. Why not use the built in function itoa()? I also don't like (especially the C18 implementation) of floats.

Try simplifying it to,
Code:
unsigned char buffer[5], i;
    ADC_Go();                   //do conversion
    ad_val=(ADRESH<<8)+ADRESL;  //get value
    ad_val*=(4.8828125*256);    //[COLOR="Red"]scale it[/COLOR]
    ad_val+=128;                //[COLOR="Red"]rounding[/COLOR]
    ad_val/=256;                //[COLOR="Red"]adjust back to int[/COLOR]
    itoa((int)ad_val,buffer);   //convert it
    i=0;                        //print it
    while(buffer[i]){
        LCD_Char(buffer[i]);
        i++;
    }
You don't state your clock speed so I couldn't check you acquisition and conversion times were correct but it is unusual to get static readings so it maybe hardware related.

Edit, missed the float to int error. See, told you I didn't like them.:D
Edit2, Just tried this and it worked as expected.
Code:
    ADCV=1234.5678;
    ad_val=ADCV;
Mike.

thanks for your reply , there are some parts of your code that I don't understand. I marked it in red.

So if the ADC(ADRESH:ADRESL) value would be like : 0000 0001 0100 0001 ( dec:321) . The max binary value is 1023 , so ADC value * 5000/1024 , now 5000 ( dec ) is 5v . And then I don't get the *256 ?

maybe you can help me out on this one?

Thanks !
 
I did the same calculation that you did only I moved the decimal place 8 bits left so the bottom 8 bits are the fractional part. So multiplying the 4.8... by 256 gave me 1250 (5000/1024*256). Adding 128 is the same as adding 0.5 to round the number and then the final division by 256 gets the required value as an integer. So, 321 would give, 321*1250=401250, +128 gives 401378 and divide by 256 gives 1567. I assume that 321 is equivalent to 1567mV. It is just a way to do it without floating point maths.

Mike.
 
floating point conversion

hi 2 all,
I have written adc program and displaying ascii values on lcd display but I want to display in floating points(in degrees).I tried but I don't know how to write conversion program.any body please help me about it.

Regards,
Jyothi
 
Hi 2 all,
Here I got a problem while interfacing 0808 with 8051 controller,I wanted to convert ascii value to floating point on serial and lcd.I don't have any idea about this one, I tried but I didn't get output.can any body help me. Here I am using 8bit adc and I have given refernce voltage as 2.5 volts.I have wriitten function of floating conversion is as follows.

#include<reg51.h>
#include<stdio.h>

#define adc_data P2 //ADC data port
#define lcd_data P1 //LCD data port

//-----------------------------------------------------------------------------------------
// ADC and LCD port defination here
//----------------------------------------------------------------------------------------------

sbit rs=P3^5; //rs for lcd
sbit en=P3^4; //en for lcd

sbit ADDR_2=P0^0; // CHANNEL SELECTION PORT
sbit ADDR_1=P0^1;
sbit ADDR_0=P0^2;

sbit ALE=P0^4; //ADDRES LATCH ENABLE
//sbit CLOCK=P0^7; //CLOCK GENERATED FOT THE ADC0808 AT THIS PIN

sbit SOC = P0^3; //START OF CONVERSION
sbit EOC = P0^5; //END OF CONVERSION
sbit OE = P0^6; //READ ENABLE

sbit led = P3^1;

//-----------------------------------------------------------------------------------------
// ALL FUNCTION PROTOTYPES HERE
//----------------------------------------------------------------------------------------------
void init_serial();
void send(unsigned char);
void ser_string(unsigned char*);

void lcd_init();
void lcdcmd(unsigned char);
void lcddata(unsigned char);
void lcd_string(unsigned char*);
void LCD_DELAY(unsigned int);
void Conversion( float );
void MSDELAY(unsigned int time);

void convertion(unsigned char);
unsigned char adc_read(void );
unsigned char adc_read(void );
// void channel_sel(unsigned char ch);

unsigned char sen_red,temp_val;
unsigned char D0,D1,D2,D3,D4;
float ADCV;
//-------------------------------------------------------------------------------------------------
// Serial communication function
//-------------------------------------------------------------------------------------------------
void init_serial()
{
SCON=0x50; // serial control register
TMOD=0x20; //timer initialisation(timer1-mode1)
TH1=0xFD; //set baud rate of 9600
TR1=1; //run timer 1 for serial comunication
}
void send(unsigned char t)
{
SBUF=t;
while(TI==0);
TI=0;
}

void ser_string(unsigned char *p)
{
while(*p!='\0')
{
send(*p++);
}
}

//------------------------------------------------------------------------------------------
//LCD program function
//------------------------------------------------------------------------------------------
void lcd_init()
{
//4-bit interface
lcdcmd(0X3;
LCD_DELAY(500);
lcdcmd(0X0E); //Dispaly on cursor blinking
LCD_DELAY(500);
lcdcmd(0X01); // clear lcd
LCD_DELAY(500);
lcdcmd(0X06); // increment cursor
LCD_DELAY(500);
lcdcmd(0X80); // go to first line
LCD_DELAY(500);

}
void lcdcmd(unsigned char a)
{
lcd_data=a;
rs=0;
en=1;
LCD_DELAY(5);
en=0;
}


void lcddata(unsigned char a)
{
lcd_data=a;
rs=1;
en=1;
LCD_DELAY(5);
en=0;
LCD_DELAY(5);
}

void LCD_DELAY(unsigned int i)
{
unsigned int j,k;
for(k=0;k<=1;k++)
for(j=0;j<i;j++);
}

void lcd_string(unsigned char *ptr)
{
while(*ptr)
{
lcddata(*ptr);
ptr++;
}
}
//---------------------------------------------------------------------------------------------
// ADC convertion function
//---------------------------------------------------------------------------------------------
void Conversion ( float value)
{
unsigned int test = value; // float => int
D3=value/1000; // high decimal
D2 = (test - (D3*1000.0))/100;// secong highest decimal
D1= (test) - ((D3*1000.0)+(D2*100.0));
D1=D1/10;//second lowest
D0= (test) - ((D3*1000.0)+(D2*100.0)+(D1*10)); // lowest decimal
send(D3);LCD_DELAY(500);
send(D2);LCD_DELAY(500);
send(D1);LCD_DELAY(500);
send(D0);LCD_DELAY(500);

lcddata(D3);LCD_DELAY(500);
lcddata(D2);LCD_DELAY(500);
lcddata(D1);LCD_DELAY(500);
lcddata(D0);LCD_DELAY(500);
}

//-----------------------------------------------------------------------------------------------------------------
//main function starts here
//-----------------------------------------------------------------------------------------------------------------
void main()
{
unsigned char adc_val;


EOC=1; // MAKE EOC PIN INPUT PIN

ALE=0;
OE=0;
SOC=0;

init_serial(); // serial intialisation
ser_string("welcome\n\r");

lcd_init(); // lcd initialisation
lcdcmd(0x80); // lcd clear
lcd_string("welcome");
LCD_DELAY(500);

while(1)
{
ADDR_2 =1;
ADDR_1 =1; // BY DEFAULT SELECT CHANNEL 1
ADDR_0 =1;

lcdcmd(0x01);
lcdcmd(0x80);
lcd_string("ADC CONV VALU:");
ser_string("ADC CONV VALU\n\r");
adc_val=adc_read();
ADCV = (float) (adc_val )*(9.7656); // get a correct value with reference to 2.5V.(2500/256)
Conversion ( ADCV);
//Convert(sen_red);
}

}

//}
//-------------------------------------------------------------------------------------------------
// ADC read function
//-------------------------------------------------------------------------------------------------
unsigned char adc_read(void)
{
unsigned char value;

MSDELAY(1);
ALE=1; // sending high to low pulse
MSDELAY(1);
SOC=1; // SOC starts
MSDELAY(1);
ALE=0;
SOC=0;
while(EOC==0); // wait until conversion ends
OE=1;
LCD_DELAY(50);
//LCD_DELAY(500);
value=adc_data;
OE=0;
return (value);
}
//-------------------------------------------------------------------------------------------------
// DELAY function
//-------------------------------------------------------------------------------------------------
void MSDELAY(unsigned int time)
{
unsigned int i,j;
for(i=0;i<time;i++)
for(j=0;j<1275;j++);
}

Here I am geting adc value in ascii correctly but I want to convert it into floating point .can any body help me please
Regards,
Jyothi.
 
Status
Not open for further replies.

Latest threads

Back
Top