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] LCD display flickrign problem. Urgent help required.

Status
Not open for further replies.

Qaisar Azeemi

Full Member level 5
Joined
Feb 11, 2011
Messages
315
Helped
16
Reputation
32
Reaction score
15
Trophy points
1,298
Location
Peshawar, Pakistan, Pakistan
Activity points
3,829
Hi,

i want to display data detected by ADC0808 on my 14x2 LCD but by doing this i am facing a problem that the data at my lcd display is not still to see as in Digital Multi-meters. here is the video link that shows my problem. i want to eliminate the flickring on screen.


and here is my code.

Code:
#include <reg52.h>


 #define Port P2  // control port
 #define adc_input P1
 #define data_port P0  // data from microcontroller to LCD
 #define sec 50

 sbit ADC_A=Port^0;	//ADC
 sbit ADC_B=Port^1;	//ADC
 sbit RS=Port^7;  		//LCD
 sbit E=Port^5;		   //LCD
 sbit RW=Port^6;		  //LCD
 sbit SC=Port^4;   //ADC
 sbit CLK=Port^3;  //ADC
 sbit ALE=Port^2;  //ADC

unsigned int test_intermediate3=0, test_final=0;
unsigned int test_intermediate1[10], test_intermediate2[3]={0,0,0};
unsigned char temp[]={"Temp: "}, vna[]={"Volt:    Amp:  "},  hnm[]={"  hr   min     %"}, bnc[]={"Backup:  %Charge"};


		 //------------------- . --------------------------

		void delay(unsigned int msec)
		{
			int i,j;
			for(i=0; i==msec; i++)
				for(j=0; j==1275; j++);

		}




		//---------------- timer 0 interrupt----------------

		void timer0() interrupt 1
		{
		   		
					CLK=~CLK;		// Toggle port bit p3.5
					TR0=0;         // stop timer
					TH0=0xff;	    // 500hz clock for adc
					TL0=0xff;
					TR0=1;			// start timer
		}




		//.................. LCD .................


		void lcd_cmd( unsigned int item )
		{
			data_port=item;  //command on data port p0 of lcd
			RS=0; // selecting command register of lcd
			RW=0;
			E=1;
			delay(1);
			E=0;
		//	return;
		}




		void lcd_data( unsigned int item )
		{
			data_port=item;  //data on data port p0 of lcd
			RS=1; // selecting data register of lcd
			RW=0;
			E=1;
			delay(1);
			E=0;
		//	return;
		}










	  //----------- custom character Generation for Degree symbol-----------

	  void shape()
	  {
	  		
			lcd_cmd(64); 		// first location in CGRAM
			delay(sec);
			lcd_data(2);
			delay(sec);
			lcd_data(5);
			delay(sec);
			lcd_data(2);
			delay(sec);
			lcd_data(0);
			delay(sec);
			lcd_data(0);
			delay(sec);
			lcd_data(0);
			delay(sec);
			lcd_data(0);
			delay(sec);
			lcd_data(0);
			delay(sec);

			return;
	  }


	  //-------------------- for volt symbol-----------------

	   void shape2()
	  {
	  		
			lcd_cmd(72); 		// first location in CGRAM
			delay(sec);
			lcd_data(0);
			delay(sec);
			lcd_data(0);
			delay(sec);
			lcd_data(17);
			delay(sec);
			lcd_data(17);
			delay(sec);
			lcd_data(17);
			delay(sec);
			lcd_data(10);
			delay(sec);
			lcd_data(4);
			delay(sec);
			lcd_data(0);
			delay(sec);

		//	return;
	  }

	 //---------------------- for current symbol-------------------

	  void shape3()
	  {
	  		
			lcd_cmd(80); 		// first location in CGRAM
			delay(sec);
			lcd_data(0);
			delay(sec);
			lcd_data(0);
			delay(sec);
			lcd_data(4);
			delay(sec);
			lcd_data(10);
			delay(sec);
			lcd_data(17);
			delay(sec);
			lcd_data(31);
			delay(sec);
			lcd_data(17);
			delay(sec);
			lcd_data(0);
			delay(sec);

		//	return;
	  }
								





	  //..... Converting binary value of ADC to ASCII value of LCD for Temprature........




	  void convert()
	  {
	  		int s,i;
			lcd_cmd(0xc0);
		
			delay(sec);

	 													 // Farnheit conversion

			for(i=0; temp[i]!='\0' ; i++)
				{
					lcd_data(temp[i]);
					delay(sec);
				}

			 
			test_final=(((9*test_intermediate3)/5)+32);
			
			s=test_final/100;
			test_final=test_final%100;

			lcd_cmd(0xc5);
			delay(sec);
			if (s!=0)
				{
				lcd_data(s+48);	//c5
				delay(sec);
				}
			else
				{
				lcd_cmd(0x06);
				delay(sec);
				}


		  s=test_final/10;
		  test_final=test_final%10;

		  lcd_data(s+48);	   //c6
		  delay(sec);
		  lcd_data(test_final+48);	//c7
		  delay(sec);
		  lcd_data(0);				 // space for degree symbol
		  delay(sec);
		  lcd_data('F');
		  delay(sec);
		  lcd_data(' ');
		  delay(sec);


		//------------------- for Celcius scale----------------

		  test_final=test_intermediate3;

		 // lcd_cmd(0xc1);  // set cursor to second line.
		 
	//	 delay(sec);

	//	 for(i=0; temp[i]!='\0' ; i++)
	//			{
	//				lcd_data(temp[i]);
	//				delay(sec);
	  //
		//		}

		  s=test_final/100;
			test_final=test_final%100;

			lcd_cmd(0xcB);
			delay(sec);
			if (s!=0)
				{
				  lcd_data(s+48);	// 1st digit MS
					delay(sec);
				}
			else
				{
				  lcd_cmd(0x06);
					delay(sec);
				}



		  s=test_final/10;			 // 2nd digit
		  test_final=test_final%10;	 // 3rd digit LS

		  lcd_data(s+48);  //89
		  delay(sec);
		  lcd_data(test_final+48);	 //88
		  delay(sec);
		  lcd_data(0);		   // space for degree symbol
		  delay(sec);
		  lcd_data('C');
		  delay(sec);
		  lcd_data(' ');
		  delay(sec);
		 }







		 // Converting binary value of ADC to ASCII value of LCD for volts


		 void  Convert2()
		 {
		 	int s;
	 //.................... Voltage conversion ............................

					 
		 test_final=test_intermediate3/3;
			
			s=test_final/100;
			test_final=test_final%100;

			 lcd_cmd(0x85);
			delay(sec);
			if (s!=0)
				{
				lcd_data(s+48);
				delay(sec);
				}
			else
				{
				lcd_cmd(0x06);
				delay(sec);
				}


		  s=test_final/10;
		  test_final=test_final%10;

		  lcd_data(s+48);	   
		  delay(sec);
		  lcd_data(test_final+48);	
		  delay(sec);
		  lcd_data(1);
		  delay(sec);
		 }

		//-------------------..................-------------------

		 void  Convert3()
		 {
		 	int s;
	//.................... current conversion ............................

					 
		 test_final=test_intermediate3/5;
			
			s=test_final/100;
			test_final=test_final%100;

			  lcd_cmd(0x8D);
			delay(sec);
			if (s!=0)
				{
				lcd_data(s+48);
				delay(sec);
				}
			else
				{
				lcd_cmd(0x06);
				delay(sec);
				}


		  s=test_final/10;
		  test_final=test_final%10;

		  lcd_data(s+48);	   
		  delay(sec);
		  lcd_data(test_final+48);
		  delay(sec);
		  lcd_data(2);
		  delay(sec);
		 }

	  
	  
	  
	  
	  
	  
	  
	  //.........--------.......Main Program.......-------........

		

		   void main()
		   {

		   		int i,j,k,l,m,n;
				adc_input=0xff; // making p1 as input port
				TMOD=0x01;	   // timer 0,  mode 1
				TH0=0xff;	    // 500hz clock for adc
				TL0=0xff;
				TR0=1;         // timer start

				IE=0x82;		// interrupt enable ; timer interrupt and globle interrupt.
				
				lcd_cmd(0x38);		// initializing LCD module
				delay(sec);

				lcd_cmd(0x0c);
				delay(sec);

				lcd_cmd(0x01);
				 delay(sec);

				lcd_cmd(0x06);
				delay(sec);

				lcd_cmd(0x90);
			    delay(sec);

	//;;;;;;;;;;;;-----------------------;;;;;;;;;;;;;;;;;
	//..........- Back up and %Charge display ----........

				lcd_cmd(0x90);
			    delay(sec);

			for(i=0; bnc[i]!='\0' ; i++)
				{
					lcd_data(bnc[i]);
					delay(sec);
				}							


	//;;;;;;;;;;;;;;-------------------------;;;;;;;;;;;;;;;;;
	//.............- hour and minute display ------............

		lcd_cmd(0xD0);									   
		
			delay(sec);

	 													

			for(i=0; hnm[i]!='\0'; i++)
				{
					lcd_data(hnm[i]);
					delay(sec);
				}

	//;;;;;;;;;;;;;;-----------;;;;;;;;;;;;;;;
				

				while(1)
				{

				//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Temprature samples;;;;;;;;;;;;;;;;;;;;;;


						for(j=0;j<3;j++)
						{
							for(i=0;i<10;i++)
							{
								   ADC_A=0;
								   ADC_B=0; // channel 0 is selected   ; pin 26 of ADC

									delay(200);
								
									ALE=0;
									SC=0;
									delay(1);

									 ALE=1;
									 delay(1);
									 SC=1;
									 delay(1);

									 ALE=0;
									 delay(1);
									 SC=0; 
									 delay(1000);
																		 
									 test_intermediate1[i]=adc_input/10;
								
							}


							for(i=0;i<10;i++)
							test_intermediate2[j]+=test_intermediate1[i];
						}


						test_intermediate2[0]=test_intermediate2[0]/3;
						test_intermediate2[1]=test_intermediate2[1]/3;
						test_intermediate2[2]=test_intermediate2[2]/3;

						test_intermediate3=test_intermediate2[0] + test_intermediate2[1] + test_intermediate2[2];

					

						convert();
						shape();

						delay(1000);
						delay(1000);
						delay(1000);

			 //;;;;;;;;;;;;;;;;;  Voltage samples;;;;;;;;;;;;;;;;;;;;;;;;;


		    lcd_cmd(0x80);
		
			delay(sec);

	 													 // voltage conversion

			for(i=0; vna[i]!='\0'; i++)
				{
					lcd_data(vna[i]);
					delay(sec);
				}


					 //..................................................  ..........


					  	for( k=0;k<3;k++)
						{
							for(l=0;l<10;l++)
							{
								   ADC_A=1;
								   ADC_B=0; // channel 1 is selected

									delay(200);
								

									ALE=0;
									SC=0;
									delay(1);

									 ALE=1;
									 delay(1);
									 SC=1;
									 delay(1);

									 ALE=0;
									 delay(1);
									 SC=0; 
									 delay(1000);
																		 
									 test_intermediate1[i]=adc_input/10;
								
							}


							for(i=0;i<10;i++)
							test_intermediate2[j]+=test_intermediate1[i];
						}


						test_intermediate2[0]=test_intermediate2[0]/3;
						test_intermediate2[1]=test_intermediate2[1]/3;
						test_intermediate2[2]=test_intermediate2[2]/3;

						test_intermediate3=test_intermediate2[0] + test_intermediate2[1] + test_intermediate2[2];
						 
						
						 Convert2();
						 	shape2();

							delay(1000);
							delay(1000);
							delay(1000);

						   //;;;;;;;;;;;;;;;;;  Current samples;;;;;;;;;;;;;;;;;;;;;;;;;

					  	for( m=0;m<3;m++)
						{
							for( n=0;n<10;n++)
							{
								   ADC_A=0;
								   ADC_B=1; // channel 2 is selected

									delay(200);
								

									ALE=0;
									SC=0;
									delay(1);

									 ALE=1;
									 delay(1);
									 SC=1;
									 delay(1);

									 ALE=0;
									 delay(1);
									 SC=0; 
									 delay(1000);
																		 
									 test_intermediate1[i]=adc_input/10;
							}



							for(i=0;i<10;i++)
							test_intermediate2[j]+=test_intermediate1[i];
						}


						test_intermediate2[0]=test_intermediate2[0]/3;
						test_intermediate2[1]=test_intermediate2[1]/3;
						test_intermediate2[2]=test_intermediate2[2]/3;

						test_intermediate3=test_intermediate2[0] + test_intermediate2[1] + test_intermediate2[2];
						
						 Convert3();
						 	shape3();
							delay(1000);
							delay(1000);
							delay(1000);

				}
		   }


the second problem in my code is that i have used the LCD address 90H in order to display "Backup: %Charge" but it is not displaying on that location ... i dont know why?? but if i write the same string with in the vna[] aray with sixteen spaces (vna[]={"Volt: Amp: backup: %charge"} ) it started display the string "Backup: %Charge" in third line. the address for the first line of 16x4 lcd is 80---8f
for 2nd line it is c0---cf ; for 3rd line it is 90----9f and for 4th line it is d0----df.

please guide me about my both problems.

any help will be appritiated.

thank you
 

Hi,

i want to display data detected by ADC0808 on my 14x2 LCD but by doing this i am facing a problem that the data at my lcd display is not still to see as in Digital Multi-meters. here is the video link that shows my problem. i want to eliminate the flickring on screen.

Use a lower refresh rate, 3-4 times per second are more than enough.
 

i solved the two basic problems.......

1) i mistakenly written the routine to display volt and amp within while(1) loop... i cut it out of here and paste it in main function out of while loop. thus flickrig is eleminated. it flickred due to repeatedly display the string and data on the same place.

2)i just write the display routines in a sequence according to address of LCD. i.e; 1st for line 1 and then for 2 and so on up to line4 .

................................;;;;;;;;;;;;;;;;;; ......................................


NOW the problem is that the changing analog value on one pin of ADC is causing to change the value of 2nd pin ... i checked it out in proteus simulator and practically on my Hardware...... please help me about this new problem.. i think it is programming problem.
 

Often this is caused by not having enough capacitance on the pin going to the A/D input combined with having too short an acquisition time. A really easy thing I have done it in the past is to take 2-3 readings of the same a/d channel (without changing the a/d channel) and use the last one. Also waiting a few milliseconds between samples (after you change the channel number) lets the internal capacitances settle.
 

i am taking 10 samples of each ADC input and using its average in my program ... but the problem is the same and changing analog signal on one input causig a change in the displayed value of second input........ :-(
 

Any of the inputs going over 5V or under 0V? I have had A/D converters go nuts if the mux inputs get over driven.

One other comment - in the summing of the 10 samples, do not divide by 10 first. typecast the 8-bit a/d value to 16 bits, then add it to a 16-bit sum. You can divide the sum at the end without truncating bits in the a/d result. You also should add 5 (which is 1/2 of 10) to the summation before you divide by 10; that will give you a rounded result.
 

Any of the inputs going over 5V or under 0V? I have had A/D converters go nuts if the mux inputs get over driven.

One other comment - in the summing of the 10 samples, do not divide by 10 first. typecast the 8-bit a/d value to 16 bits, then add it to a 16-bit sum. You can divide the sum at the end without truncating bits in the a/d result. You also should add 5 (which is 1/2 of 10) to the summation before you divide by 10; that will give you a rounded result.

what is the technicality in summing first and then dividing the sum by 10???

because in basic mathematics if you know LCM and Average; both methods give same result if we divide individual values 1st and then take sum of thos divided values. or we take sum of individual values first and then divide the sum to a value, both will give the same result.
 

If you are working with integers and not floats you will get a different result because of the truncated decimals.
 

plz check my this routine... i want to select one output at a time. just like rotation of 4 bit data (1000B). but it is giving random selection; with interrupt signal all bits goes high and then any one bit got selected randomly.... i dont know what acctually the problem is???????

Code:
#define select P3

 sbit v28=select^4;
 sbit v14=select^6;
 sbit v7=select^5;
 sbit off=select^7;


	void switching() interrupt 0
		   {

					if(count==0)
						{
							 off=0;  v7=1; v28=0; v14=0;
							 count++;
						}
					else	
					if(count==1)	
						{ 
							v7=0; v14=1; v28=0; off=0; 
							count++;
						}
					else
					if(count==2)
					    {
							v14=0; v28=1; v7=0;  off=0; 
							 count++;
						}

					else
						{ 
						
							count=v28=v14=v7=0; off=1; 
							
						}



		   		/*  if(v28==0 && v14==0 && v7==0 && off==1)
				  		{ off=0;  v7=1; v28=0; v14=0; }
					
				    else
                        if(v28==0 && v14==0 && v7==1 && off==0)
                              { v7=0; v14=1; v28=0; off=0; }
					
					else
						if(v28==0 && v14==1 && v7==0 && off==0)
						      { v14=0; v28=1; v7=0;  off=0; }
					
					else
					   { v28=v14=v7=0; off=1; }	 */
						
		   
		   }


and here is the immage of my circuit.

adc problem.png
 
Last edited:

Vcc is not connected to VDD (pin2 of the LCD ) and I think your leds have no Vcc either
 

change 'count=v28=v14=v7=0; off=1;'
to 4 separate statements.

---------- Post added at 16:05 ---------- Previous post was at 15:48 ----------

in integer math 28 divided by 10 is 2 not 2.8; (can't express the .8)
so sum of 10 samples of 28/10 = 20 not 28;
also I wrote typecast so that you would remember that you were doing it for a specific reason. The compiler will usually autocast it for you, but inexperienced programmers should use explicit typecasting so they remember to check the variable types (I promise, it was a lesson that I learned the hard way, haha).

so your code should be something like:
for(i=0;i<10;i++)
test_intermediate2[j]+=(unsigned long)test_intermediate1;
... (don't divide test_intermediate2[] by 10 either)
test_intermediate3=test_intermediate2[0] + test_intermediate2[1] + test_intermediate2[2]+15; // add half the divisor for rounding
test_intermediate3=test_intermediate2[0]/30;
final_result = (unsigned int)test_intermediate3;

If you do it as above, you will remember when you mixed variables. It's really nice to do it so that when you copy the code into another section or another project, you will remember what "tricks" you used.
 

change 'count=v28=v14=v7=0; off=1;'
to 4 separate statements.

---------- Post added at 16:05 ---------- Previous post was at 15:48 ----------

in integer math 28 divided by 10 is 2 not 2.8; (can't express the .8)
so sum of 10 samples of 28/10 = 20 not 28;
also I wrote typecast so that you would remember that you were doing it for a specific reason. The compiler will usually autocast it for you, but inexperienced programmers should use explicit typecasting so they remember to check the variable types (I promise, it was a lesson that I learned the hard way, haha).

so your code should be something like:
for(i=0;i<10;i++)
test_intermediate2[j]+=(unsigned long)test_intermediate1;
... (don't divide test_intermediate2[] by 10 either)
test_intermediate3=test_intermediate2[0] + test_intermediate2[1] + test_intermediate2[2]+15; // add half the divisor for rounding
test_intermediate3=test_intermediate2[0]/30;
final_result = (unsigned int)test_intermediate3;

If you do it as above, you will remember when you mixed variables. It's really nice to do it so that when you copy the code into another section or another project, you will remember what "tricks" you used.


Thank you very much dear steveelliott. i have changed it to 4 separate statments but the result is the same ...during interrupt all the bits of port 3 got high and after interrupt it selects any one of the bit High Randomly.. not according to coad..... :-( ... how to solve this problem..???

and you are quite right in your coading int data type will just ignore the desimal points and give erroneous result. and i will make these changes in my program today...
 

Here's what's wrong-
The bit change instructions are Read-modify-write. The read the port value, set the new bit back, then write the new value back. Because the PIC is pipelined, the port hasn't written the new value back before it reads the next Read-Modify-write.

Insert a dummy instruction between each bit set like this:
off=0;
count++;
count--;
v7=1; count++;
count--;
v28=0; count++;
count--;
v14=0;
 

you can also try inserting delay between two different ADC inputs
 

the problem is solved :)

the problem was with the interrupt.. we must force the interrupt to go high in order to disable it.. so it will be able to select the required pin correctly....

i am very thank ful to all who help me.

best regards
Qaisar azeemi
 

good to see that your problem is solved .

Good luck !
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top