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.

Read Battery Voltage to display on LCD

Status
Not open for further replies.

flyingCOW

New Member
Hi,

Im currently doing my school project. My task is to read the battery voltage and to display on LCD in percentage.
I'm using P18f4520 ADC AN0 channel to get the voltage from the batteries. And I'm using 4 LifePO4 batteries connected in series.

Total voltage of the batteries is about approx. 14.5V. Min V is 2.5V, and Max V is 3.7V.
I also use the voltage divider to get approx 4.6 - 4.9V, so that it won't damaged the pic18f4520 of the AN0 port.

The LCD only display the Battery Status on the first line, but the percent on the second line still 0%

Below are the codes:

Code:
#include <p18f4520.h>
#include <delays.h>
void Init_LCD(void);			// Initialize the LCD
void W_ctr_8bit(char);			// 8-bit Control word for LCD
void W_data_8bit(char);			// 8-bit Text Data for LCD
void Delay_1kcyc(void);			// 1000 cycles delay, 1ms

#define LCD_DATA	PORTD
#define LCD_RS   	PORTBbits.RB1   	// RS signal for LCD
#define LCD_E    	PORTBbits.RB2   	// E signal for LCD
#define LED         PORTCbits.RC0 

unsigned char LCD_TEMP, i,j,k,m;
char MESS[15] = "BATTERY STATUS"; 
char MESS1[5];
int result;
void main(){

ADCON0=0b00000001;
ADCON1=0b00001110;			// Set ports A,B & E as digital I/O
ADCON2=0b10000011;
TRISA=0b11111111;
TRISB = 0b11111001;		// RB1 & 2 for LCD interface RS & E
TRISD = 0;				// Port D as LCD data output
TRISC = 0;
Init_LCD();				// Init LCD 8-bit interface,multiple line
while(1)
{
	Delay10TCYx(5);		// Acquisition time 10us (>=5us)
			ADCON0bits.GO = 1;		// Start ADC 
		while(ADCON0bits.DONE);	// ADC completed?
		result = ADRESH*256+ADRESL ;	// Mask the lower nibble of the ADC result
		result= result/10.2;
		itoa(result,MESS1);

W_ctr_8bit(0b11000000);
for(i=0;i<MESS1[i];i++)
W_data_8bit(MESS1[i]);

  		 W_data_8bit('%');
		 W_data_8bit(' ');
		 W_data_8bit(' ');
		
  	W_ctr_8bit(0b10000000);
for(i=0;i<14;i++)
	W_data_8bit(MESS[i]);
		
}
}

/* LCD display initialization */
void Init_LCD(){								
	W_ctr_8bit(0b00111000);		// Function Set - 8-bit, 2 lines, 5X7
 	W_ctr_8bit(0b00001100);		// Display on, cursor on
	W_ctr_8bit(0b00000110);		// Entry mode - inc addr, no shift
	W_ctr_8bit(0b00000001);		// Clear display  
	W_ctr_8bit(0b00000010);		// Return cursor to home position
}

/* Write control word to LCD */
void W_ctr_8bit(char x){ 						
   LCD_RS	= 0;				// Logic ‘0’
   LCD_E	= 1;				// Logic ‘1’
   LCD_DATA = x;
   LCD_E	= 0;				// Logic 0’
   Delay10TCYx(50);			// 1ms delay
}

/* Write text data to LCD */
void W_data_8bit(char x){ 
   LCD_RS	 = 1;				// Logic ‘1’
   LCD_E	 = 1;				// Logic ‘1’
   LCD_DATA  = x;
   LCD_E	 = 0;				// Logic ‘0’
   Delay10TCYx(50);			// 1ms delay
}

Need advice. Thanks


Regards,
Daniel
 
Last edited:
one question to ask, for my hardware pic18f4520 I use RC for the circuit oscillation, or do i need the crystal for circuit oscillation for the ADC to work?
 
Last edited:
Try the following changes:
Code:
	ADCON2=0b00001011;  // **changed for left justify (8-bits) and TAD for RC**

Code:
	Delay10TCYx(5);		// Acquisition time 10us (>=5us)
	ADCON0bits.GO = 1;		// Start ADC 
	while(ADCON0bits.DONE);	// ADC completed?
	result = ADRESH; // **changed for 8-bit read only
	result = (result*10)/25;
	// itoa(result,MESS1); // **commented out**
 
	W_ctr_8bit(0b11000000);
	// for(i=0;i<MESS1[i];i++) // **commented out**
	W_data_8bit(result);  // **changed to display only one result**
  	W_data_8bit('%');
	W_data_8bit(' ');
	W_data_8bit(' ');
 
Try the following changes:
Code:
	ADCON2=0b00001011;  // **changed for left justify (8-bits) and TAD for RC**

Code:
	Delay10TCYx(5);		// Acquisition time 10us (>=5us)
	ADCON0bits.GO = 1;		// Start ADC 
	while(ADCON0bits.DONE);	// ADC completed?
	result = ADRESH; // **changed for 8-bit read only
	result = (result*10)/25;
	// itoa(result,MESS1); // **commented out**
 
	W_ctr_8bit(0b11000000);
	// for(i=0;i<MESS1[i];i++) // **commented out**
	W_data_8bit(result);  // **changed to display only one result**
  	W_data_8bit('%');
	W_data_8bit(' ');
	W_data_8bit(' ');

THanks for reply.

I have tried the changes you told me, but now it display weird character follow by the %.. something like *% on the LCD
 
Changing from RC to crystal Osc, needs to do some ganges in your code.
 
Changing from RC to crystal Osc, needs to do some ganges in your code.

Code:
#include <p18f4520.h>
#include <delays.h>
void Init_LCD(void);			// Initialize the LCD
void W_ctr_8bit(char);			// 8-bit Control word for LCD
void W_data_8bit(char);			// 8-bit Text Data for LCD
void Delay_1kcyc(void);			// 1000 cycles delay, 1ms
 
#define LCD_DATA	PORTD
#define LCD_RS   	PORTBbits.RB1   	// RS signal for LCD
#define LCD_E    	PORTBbits.RB2   	// E signal for LCD
#define LED         PORTCbits.RC0 
 
unsigned char LCD_TEMP, i,j,k,m;
char MESS[15] = "BATTERY STATUS"; 
char MESS1[5];
int result;
void main(){
 
ADCON0=0b00000001;
ADCON1=0b00001110;			// Set ports A,B & E as digital I/O
ADCON2=0b10000011;
TRISA=0b11111111;
TRISB = 0b11111001;		// RB1 & 2 for LCD interface RS & E
TRISD = 0;				// Port D as LCD data output
TRISC = 0;
Init_LCD();				// Init LCD 8-bit interface,multiple line
while(1)
{
	Delay10TCYx(5);		// Acquisition time 10us (>=5us)
			ADCON0bits.GO = 1;		// Start ADC 
		while(ADCON0bits.DONE);	// ADC completed?
		result = ADRESH*256+ADRESL ;	// Mask the lower nibble of the ADC result
		result= result/10.2;
		itoa(result,MESS1);
 
W_ctr_8bit(0b11000000);
for(i=0;i<MESS1[i];i++)
W_data_8bit(MESS1[i]);
 
  		 W_data_8bit('%');
		 W_data_8bit(' ');
		 W_data_8bit(' ');
 
  	W_ctr_8bit(0b10000000);
for(i=0;i<14;i++)
	W_data_8bit(MESS[i]);
 
}
}
 
/* LCD display initialization */
void Init_LCD(){								
	W_ctr_8bit(0b00111000);		// Function Set - 8-bit, 2 lines, 5X7
 	W_ctr_8bit(0b00001100);		// Display on, cursor on
	W_ctr_8bit(0b00000110);		// Entry mode - inc addr, no shift
	W_ctr_8bit(0b00000001);		// Clear display  
	W_ctr_8bit(0b00000010);		// Return cursor to home position
}
 
/* Write control word to LCD */
void W_ctr_8bit(char x){ 						
   LCD_RS	= 0;				// Logic ‘0’
   LCD_E	= 1;				// Logic ‘1’
   LCD_DATA = x;
   LCD_E	= 0;				// Logic 0’
   Delay10TCYx(50);			// 1ms delay
}
 
/* Write text data to LCD */
void W_data_8bit(char x){ 
   LCD_RS	 = 1;				// Logic ‘1’
   LCD_E	 = 1;				// Logic ‘1’
   LCD_DATA  = x;
   LCD_E	 = 0;				// Logic ‘0’
   Delay10TCYx(50);			// 1ms delay
}

From the code above, I change the ADCON2=0b10000100; I using 4MHz for the crystal osc.
 
Last edited:
What is this line;
result= result/10.2;
surely your compiler gives you a wirning or an error here!

You have defined "result" as type int but /10.2 requires float math. The compiler will probably round it to this; result = result / 10

If you want a proper /10.2 using int variable you can do it like this;
result = (result * 5) / 51;
 
What is this line;
result= result/10.2;
surely your compiler gives you a wirning or an error here!

You have defined "result" as type int but /10.2 requires float math. The compiler will probably round it to this; result = result / 10

If you want a proper /10.2 using int variable you can do it like this;
result = (result * 5) / 51;

I'm able to get the battery reading when using RC osc for the code i use.
But when use crystal osc it only show 0%. It's not reading anything from RA0.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top