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.

[PIC] LCD is BLANK if the ADC voltage is LOWER than 5V

Status
Not open for further replies.

kasamiko

Full Member level 3
Joined
May 23, 2004
Messages
154
Helped
16
Reputation
32
Reaction score
18
Trophy points
1,298
Location
Philippines
Activity points
1,121
Hello guys..need a little help here..

I construct a project for solar lighting using PIC16F877A, it will simply monitor battery and solar voltage via ADC and switch on/off load and charge a battery.
Now ADC was set to 5V, now my problem is if the battery or solar voltage is low or the ADC goes below 5V like 3V, my LCD goes BLANK. :-(

I am attaching the code and and my Proteus file.

CODE:

Code:
#include <pic.h>
#include <math.h>
#include "lcd.h"
#define charge_Batt_1_Solar 0x15
#define charge_Batt_2_Solar 0x0E
#define Batt_Low_Solar 0x07
#define charge_over 0x08
#define charge_Batt_1_AC 0x11
#define charge_Batt_2_AC 0x0A
#define Batt_Low_AC 0x03

void delay(unsigned int time) // Delay 
{
	unsigned int i, j;
	for(i=0;i<time;i++)
	   for(j=0;j<time;j++); 
}
void ADC_Init() // Intialise ADC 
{
  ADCON0 = 0x01;	
  ADCON1 = 0xC4;	//Right justified,AN0,AN1,AN3 are analog input.
  ADRESH = 0;
  ADRESL = 0;
}
unsigned int ADC_Read(unsigned char channel)
{
  ADCON0 &= 0xC7; 		//Clearing the Channel Selection Bits
  ADCON0 |= channel<<3; //Setting the required Bits
  delay(10); 		    //Acquisition time to charge hold capacitor
  ADGO = 1; 			//Initializes A/D Conversion
  while(ADGO == 1); 	//Wait for A/D Conversion to complete
  return (256 * ADRESH + ADRESL); //Returns Result
}
void main(void)
{	unsigned int Solar,Batt_1,Batt_2,temp,unit,a,b,c,d,x,y,z;
	TRISA = 0x0F;		//
	TRISB = 0x00;			// port B as output
	TRISC = 0x00;			// port C as output
	TRISD = 0x00;			// port D as output 
   	lcdint();			// intialised LCD
	cmm(0x01);			// clear display
	cmm(0x80);			// 1'st line of LCD
   	data_str("  SMART CHARGER  ");
        cmm(0xC0);          // 2'nd line of LCD
        data_str("  Version 1.0  ");
	delay(300);
        cmm(0x01);			// clear display
	ADC_Init(); 		// Initialise ADC
while(1)
		{
		  Solar = ADC_Read(0);
		  unit = Solar; // Temperature is conveted to ASCII
		if(unit > 900)
				{ 	Batt_1 = ADC_Read(1);
					Batt_2 = ADC_Read(3);	
			 
			if((Batt_1 < 650)&&(Batt_2 > 850))
				{
				 cmm(0x80);			// 2nd line of LCD
				 data_str("BATT-1  CHARGING");
				 cmm(0xC0);			// 2nd line of LCD
				 data_str("BATT-2 FULL SOL.");
				 PORTC = charge_Batt_1_Solar;
				 delay(100);
				}
        	if((Batt_2 < 650)&&(Batt_1 > 850))
				{
				 cmm(0x80);			// 2nd line of LCD
				 data_str("BATT-2  CHARGING");
				 cmm(0xC0);			// 2nd line of LCD
				 data_str("BATT-1 FULL SOL.");
				 PORTC = charge_Batt_2_Solar;
				 delay(100);
				}
			
			
			 if((Batt_1 > 850)&&(Batt_2 > 850))
				{
				 cmm(0x80);			// 2nd line of LCD
				 data_str("BATT-2      FULL");
				 cmm(0xC0);			// 2nd line of LCD
				 data_str("BATT-1      FULL");
				 PORTC = charge_over;
				 delay(100);
				}
			if((Batt_1 < 650)&&(Batt_2 < 650))
				{
				 cmm(0x80);			// 1st line of LCD
				 data_str("BATT-1    BATT-2");
				 cmm(0xC0);			// 2nd line of LCD
				 data_str("CHARGING    SOL.");
				 PORTC = Batt_Low_Solar;
				 delay(100);
				}
		
			}
			else
			{	 Batt_1 = ADC_Read(1);
				 Batt_2 = ADC_Read(3);	
			 
			 if((Batt_1 < 650)&&(Batt_2 > 850))
				{
				 cmm(0x80);			// 2nd line of LCD
				 data_str("BATT-1  CHARGING");
				 cmm(0xC0);			// 2nd line of LCD
				 data_str("BATT-2 FULL   AC");
				 PORTC = charge_Batt_1_AC;
				 delay(100);
				}
        	if((Batt_2 < 650)&&(Batt_1 > 850))
				{
				 cmm(0x80);			// 2nd line of LCD
				 data_str("BATT-2  CHARGING");
				 cmm(0xC0);			// 2nd line of LCD
				 data_str("BATT-1 FULL   AC");
				 PORTC = charge_Batt_2_AC;
				 delay(100);
				}
			
			
			 if((Batt_1 > 650)&&(Batt_2 > 850))
				{
				 cmm(0x80);			// 2nd line of LCD
				 data_str("BATT-2      FULL");
				 cmm(0xC0);			// 2nd line of LCD
				 data_str("BATT-1      FULL");
				 PORTC = charge_over;
				 delay(100);
				}
			if((Batt_1 < 650)&&(Batt_2 < 650))
				{
				 cmm(0x80);			// 1st line of LCD
				 data_str("BATT-1    BATT-2");
				 cmm(0xC0);			// 2nd line of LCD
				 data_str("CHARGING      AC");
				 PORTC = Batt_Low_AC;
				 delay(100);
				}
			}
	} 	
}


Any help will be appreciated..


WBR
 

Attachments

  • Solar Home Light.rar
    394.7 KB · Views: 138

if the battery or solar voltage is low

Does the power source to the PIC16F877A go low at any time? Which power source does the unit draw from? Battery? Solar? An entirely different source? Forgive the question if you've considered this already.
 

Looking at your code, are you using the 'solar.c" or the "solar_RBT.c"?
Also it is bad coding practice to put executable code into an ".h" file (the lcd.h file in your case) - the ".h" file should declare the functions and global variables that are defined in the corresponding ".c" file but which are referenced from each file that has the ".h" file included.
Looking at the document in your .rar file, it says (last paragraph, page 89) that the microcontroller is always powered by "Batt1.1" which feeds through the 7805 to the Vcc line.
By the sound of it, that means that "Batt1.1" must remain above (something like) 7v to 8V (to account for the minimum input voltage to the regulator). Are you saying that the battery voltage is dropping low so that the regulator cannot deliver the 5V to the PIC?
Looking at the way you can constructed the main loop with all of those "if" statements that contain 'and'ed booleans, I suspect that there are cases that you have not considered - for example, assuming that the ADC channel #0 reads above 900, if the ADC channels #1 and #2 both give a value of 700 then none of the subsequent 'if" statements will be true which means that nothing will be updated on the LCD.
It would be better to rationalise that sort of coding a bit with something like (pseudocode):
Code:
if v1 < some value then
    if v2 < some value then
         output that both V1 and V2 are low
    else if v2 > some value then
        output that v1 is low but v2 is high
    else
        output that v1 is low but v2 is in between
else
    if v2 < some value then
       output that V1 is above some value and v2 is below
...
That way you will not miss various combinations.
Are you initialising the LCD correctly? Many LCD displays I have used require mSec pauses after power up and also after some of the reset commands are issued. It wold seem that everything is being driven by your 'cmm' function that only has 1mSec pauses. Also, once the LCD is initialised, they generally only require uSec pauses between signal transitions.
Susan
 
According to your code that should not happen as there is no LCD Clear Code in while(1) loop. If this is happening then are you also experiencing flickering or a little blinking of display in normal operation ?

If yes, then maybe PIC is resetting and when voltage is less than 3V and does not match with any if() conditions the LCD gets cleared and remains blank.
 
- - - Updated - - -

Does the power source to the PIC16F877A go low at any time? Which power source does the unit draw from? Battery? Solar? An entirely different source? Forgive the question if you've considered this already.

Hi,

The power to PIC16F877A never goes below 5V via LM7805 regulator, since the battery will switch to another source (battery 2) if the battery voltage goes below 11V.



Looking at your code, are you using the 'solar.c" or the "solar_RBT.c"?
Also it is bad coding practice to put executable code into an ".h" file (the lcd.h file in your case) - the ".h" file should declare the functions and global variables that are defined in the corresponding ".c" file but which are referenced from each file that has the ".h" file included.
Looking at the document in your .rar file, it says (last paragraph, page 89) that the microcontroller is always powered by "Batt1.1" which feeds through the 7805 to the Vcc line.
By the sound of it, that means that "Batt1.1" must remain above (something like) 7v to 8V (to account for the minimum input voltage to the regulator). Are you saying that the battery voltage is dropping low so that the regulator cannot deliver the 5V to the PIC?
Looking at the way you can constructed the main loop with all of those "if" statements that contain 'and'ed booleans, I suspect that there are cases that you have not considered - for example, assuming that the ADC channel #0 reads above 900, if the ADC channels #1 and #2 both give a value of 700 then none of the subsequent 'if" statements will be true which means that nothing will be updated on the LCD.
It would be better to rationalise that sort of coding a bit with something like (pseudocode):
Code:
if v1 < some value then
    if v2 < some value then
         output that both V1 and V2 are low
    else if v2 > some value then
        output that v1 is low but v2 is high
    else
        output that v1 is low but v2 is in between
else
    if v2 < some value then
       output that V1 is above some value and v2 is below
...
That way you will not miss various combinations.
Are you initialising the LCD correctly? Many LCD displays I have used require mSec pauses after power up and also after some of the reset commands are issued. It wold seem that everything is being driven by your 'cmm' function that only has 1mSec pauses. Also, once the LCD is initialised, they generally only require uSec pauses between signal transitions.
Susan


Hi,

I'm using the solar_rbt.c code, the other one is the original copy of the code. once I edit something..I save it with other filename just in case..

The whole circuit and code is not mine..I just downloaded it, It's from EFY magazine. I don't have the idea why the author choose that coding style.

Yes the power from circuit is from BATT1, but this battery should never goes below 11V, since the circuit will switch to BATT2 and BATT1 will be connected to solar panel or the AC charger.

If you can provide a much reliable code for ADC will be much appreciated..

WBR



According to your code that should not happen as there is no LCD Clear Code in while(1) loop. If this is happening then are you also experiencing flickering or a little blinking of display in normal operation ?

If yes, then maybe PIC is resetting and when voltage is less than 3V and does not match with any if() conditions the LCD gets cleared and remains blank.


Hi,

No flickering of LCD in any case, but there are instances during power on that only LINE1 of LCD has a character..LINE2 is BLANK.

It's the ADC voltage I'm adjusting RA0, RA1 and RA3. Vcc is stable at 5VDC..


Here is my Proteus file so you can try simulating..


WBR
 

Attachments

  • Solar Lighting.rar
    31.7 KB · Views: 122
Last edited:

Given what you have said (which is a slightly different problem - now it seems that only the 2nd line is 'blank', not the whole LCD) and the fact that you are simply copying the code, I assume that the config settings for the PIC are mainly left at their respective defaults.
My guess is that you are leaving the BOREN (and/or perhaps the WDTEN) config bits set.
Leaving the BOREN set will trigger a brown-out reset if the chip experiences any dip in Vdd, and I'm guessing that you are following the circuit diagram in the PDF file in the original post that does not really have enough decoupling on the supply lines.
Leaving the WDTEN set will cause a reset every few seconds as I can't see anywhere where you reset it in the code.
IF (and it is a big IF) either of those is true, I come back to my previous comment that I don't think you are initialising the LCD correctly. By the look of the codes you are sending to it in the 'lcdint' function, you are using an LCD that contains one of the standard HD44780 controller chips. The data sheet for that chip (at least the one I have) says that after sending the 'Function Set' command (the 0x38 in your case) you should wait at least 4mSec before continuing. However you seem to only be waiting for 1mSec. (Also, you need to wait at least 40mSec after the power to the LCD gets above 2.7V - this may or may not be happening in your case.)
Therefore I would check two things:
1) have you correctly set all of the config bits when you program the PIC?
2) are you getting a reset that is triggering your problem?
Susan
 
Config Bits are set to 3F39.

Snap58.jpg


There are instances that the display are blank both line1 and line2. sometimes only line1 is visible..this only happens if and only if the input voltage at port RA3 is lower than 5V at power up or during reset.

Now connecting BATT2 with voltage lower than 11V the LCD goes blank...but if BATT2 is fully charge (RA3 is 5V) no problem at all.



By the look of the codes you are sending to it in the 'lcdint' function, you are using an LCD that contains one of the standard HD44780 controller chips. The data sheet for that chip (at least the one I have) says that after sending the 'Function Set' command (the 0x38 in your case) you should wait at least 4mSec before continuing. However you seem to only be waiting for 1mSec. (Also, you need to wait at least 40mSec after the power to the LCD gets above 2.7V - this may or may not be happening in your case.)

I'm lost here..You mean the lcd.h?

Code:
void lcdint()
{	
	cmm(0x38);
	cmm(0x0C);
	cmm(0x01);
	cmm(0x06);
	cmm(0x80);

cmm(0x0C); should be? cmm(0x0E);?


BR
 
Last edited:

Thanks for the config settings - both of my guesses were wrong. Pity as that might have explained your problem.
With regard to the LCD comment, the values you are sending are fine. But in the 'cmm' function itself, you only wait about 1mSec after issuing the command before you return. In the code you have displayed, it shows that you then immediately call the function again to send the next value and so the initialisation timing can be too short. (Of course that assumes that the 'delay_ms' function really IS delaying for 1mSec.) You may need to add in some delays after calling the cmm function during the LCD initialisation stage to ensure that yuo meet the timing specs. However you really need to check the data sheet for the LCD you are actually using.
Looking again at your ADC initialisation code, I suggest that you follow the order of events in the data sheet and turn on the A/D module AFTER everything else has been set up. Also, there is no need to set the ADC output registers to zero.
I can't be bothered trying to workout the required A/D acquisition time (see Equation 11-1 in the data sheet) as it relates to your circuit, but I would ask if you are certain that the 'delay' function that you are using is actually giving you the required time. The way you have written the 'delay' function leaves you open the the compiler optimising away the entire function which would mean the Tacq might not be met.
Also, are you absolutely sure that you have NEVER put too high a voltage onto the pins of the PIC? The batteries can be up to 12v and the only thing that stops all of those 12 volts being applied to the pins is the setting of the variable resistor. As the absolute maximum voltage on a pin is Vdd + 0.3V or about 5.3V in your design. That would mean that ANY adjustment of the variable resistors beyond about 1/3 of the way up. Any more and you could destroy the MCU.
Susan
 
seems that the circuit design is a chip killer! just realized it..:(

Turning that pot near the BATT side and you will fry the chip! I'll try to add a series resistors to avoid such mistake.

BTW I wonder if where did the author derived this value?

if(unit > 900)
{ Batt_1 = ADC_Read(1);
Batt_2 = ADC_Read(3);

if((Batt_1 < 650)&&(Batt_2 > 850))

is that the ADC equivalent of solar and battery voltage? if yes how to compute that value?
 

The value of the series resistor (in series with the variable resistor and on the 'battery' side) should probably be about twice the size of the variable resistor. That way the VR will never have more than 1/3 of the 12V across it which means than any position will be "safe". You may want to adjust the VR so that the maximum voltage on the pin is even lower, but that may be of no real advantage to you.
As for the meaning of the "900" and other values, that is really all part of the design and how the "ADC_Read" function works. The setting of the ADFM bit in ADCON1 to 1 means that the result in the ADRESH:ADRESL registers will be right justified so you can read the value as a 10-bit binary number. Therefore it will have a value from 0 to 1023.
The 0 value will correspond to when the input pin has Vref- voltage on it, and the 1023 value when the pin has Vref+ voltage on it. The settings of the PCFG bits (0x04) tells the A/D that Vref+ is Vdd (5V in your case) and Vref- is Vss (0V). The number that the function will return will therefore be the ratio of the input voltage to 5V * 1024.
Once you define the value of the series resistor, you can calculate what the maximum voltage across the variable resistor will be and therefore know what the maximum voltage that can appear on the A/D pin. That value will be the equivalent of the battery voltage begin 12V and you can use the formula just above to work out what value the A/D will return at that voltage.
After that, all of the other values in the program can be calculated - given a battery voltage of 11V, the voltage across the VR will be 'X' volts and that will correspond to an ADC value of 'Y' and that is the value you can put into your program.
By the way, check that the 'Read_ADC' function really is returning the correct value. With the formula you have used, some compilers will take the "256 * ADRESH" part and try to do an 8-bit multiply to get an 8-bit result which will not be what you want. (Some compilers for microcontrollers do not always follow the "normal" rules that many C compilers use for value promotion and try to keep integers in the smallest possible form for longer than expected.) However this is easy to check - set a breakpoint in the on that line, read the ADC output values yourself and see if the calculation is giving the correct result.
Susan
 

Hi Susan,

Thank you so much for that clear explanation..

I'll try to add a 22k series resistors before the trimmer and will try on real circuit later. I hope that it will not affect much of the ADC calculation..


WBR
 

According to your code that should not happen as there is no LCD Clear Code in while(1) loop. If this is happening then are you also experiencing flickering or a little blinking of display in normal operation ?

If yes, then maybe PIC is resetting and when voltage is less than 3V and does not match with any if() conditions the LCD gets cleared and remains blank.

Your code in mikroC is working like charm! I'll try test it on hardware..:popcorn:

Thanks man!
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top