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.

PIC Kit LCD Enable pin & PWM trouble

Status
Not open for further replies.

SilverWingz

New Member
I am working on a PIC 16F877A Kit.
The objective is to drive a motor using a pwm and to receive and display the feedback from the quadrature encoder on the LDC module.

Here is the code for feedback display:
Code:
//Program accepts feedback from Rotary encoder at PORTB,translates to "Count" and displays at LCD

#include<htc.h>

#define _XTAL_FREQ 20000000

#define	RGSL RC1	/* LCD register select        */
#define   RW RC0	/* LCD read/write mode select */
#define   EN RC2	/* LCD read/write enable      */

/* function definitions */
void LCD_INIT(void);/* LCD initialistion */
void LCD_COMM(char COMM);


void main()
{
	LCD_INIT();							// lcd initialization               
	LCD_COMM(0xC0);						// second row selection for display 
	
	int old_val=0;
	int new_val=0;
	int out=0;
	int count=0;
	int t_cnt=0,o_cnt=0,h_cnt=0;

	TRISB=0b11111111;			// configure PORTB pins as input 
	PORTB=0b00000000;			//initialise PORTB as zero

	while(1)
	{	
		old_val=new_val;					//storing previous state for comparison
		new_val=(2*RB1)+RB0;				//getting decimal from encoder binary o/p
		switch(new_val)						
		{
			case 0:
			if (old_val==1)					//increase count for clockwise turn
			out=-1;
			else							//decrease count for anti-clock turn
			out=1;							//count++,count=count+1 etc not working inside switch case
			break;

			case 1:
			if (old_val==3)
			out=-1;
			else
			out=1;
			break;
		
			case 2:
			if (old_val==0)
			out=-1;
			else
			out=1;
			break;

			case 3:
			if (old_val==2)
			out=-1;
			else
			out=1;
			break;
		}
		if(old_val!=new_val)			//do nothing if no change
		{
		o_cnt=o_cnt+out;
		count=count+out;
		if(count<0)
		{
			o_cnt=0;
			t_cnt=0;
			h_cnt=0;
		}
		if(o_cnt>9)
			{
				o_cnt=0;
				t_cnt=t_cnt+1;
				if(t_cnt>9)
				{
					t_cnt=0;
					h_cnt=h_cnt+1;
					if(h_cnt>9)
					{
						h_cnt=0;

					}
				}
			}
		if(o_cnt<0)
			{
				o_cnt=9;
				t_cnt=t_cnt-1;
				if(t_cnt<0)
				{
					t_cnt=9;
					h_cnt=h_cnt-1;
					if(h_cnt<0)
					{
						h_cnt=9;
					}
				}
			}
		//DISPLAY HUNDREDS COUNT
		RGSL=1;				/* data register select     */
		RW=0;				/* register write select    */
		EN=1;				/* write enable ie,H->L     */
		PORTD=h_cnt|0x30;
		__delay_us(30);			/* delay for write          */
		EN=0;				/* disable write            */
		//DISPLAY TENS COUNT
		RGSL=1;				/* data register select     */
		RW=0;				/* register write select    */
		EN=1;				/* write enable ie,H->L     */
		PORTD=t_cnt|0x30;
		__delay_us(30);			/* delay for write          */
		EN=0;				/* disable write            */
		//DISPLAY ONES COUNT
		RGSL=1;				/* data register select     */
		RW=0;				/* register write select    */
		EN=1;				/* write enable ie,H->L     */
		PORTD=o_cnt|0x30;
		__delay_us(30);			/* delay for write          */
		EN=0;				/* disable write            */
		//LEFT SHIFT
		RGSL=0;				/* command register select  */
		RW=0;				/* register write select    */
		EN=1;				/* write enable ie,H->L     */
		PORTD=0X10;			/* move command to LCD port */
		__delay_us(30);		/* delay for write          */
		EN=0;				/* disable write            */
		//LEFT SHIFT
		RGSL=0;				/* command register select  */
		RW=0;				/* register write select    */
		EN=1;				/* write enable ie,H->L     */
		PORTD=0X10;			/* move command to LCD port */
		__delay_us(30);		/* delay for write          */
		EN=0;				/* disable write            */
		//LEFT SHIFT
		RGSL=0;				/* command register select  */
		RW=0;				/* register write select    */
		EN=1;				/* write enable ie,H->L     */
		PORTD=0X10;			/* move command to LCD port */
		__delay_us(30);		/* delay for write          */
		EN=0;				/* disable write            */
		}

	}

}
//Initialises LCD
void LCD_INIT(void)
{
	TRISC=0x00;			/* set PORTC pins as output  */
	TRISD=0x00;			/* set PORTD pins as output  */

	LCD_COMM(0X38);		/* 8-bit two line display selection */
	LCD_COMM(0X0C);		/* display on cursor off            */
	LCD_COMM(0X06);		/* auto-address increment           */
	LCD_COMM(0X01);		/* clear display                    */  
}
//Initalise command transfer
void LCD_COMM(char COMM)
{
	RGSL=0;				/* command register select  */
	RW=0;				/* register write select    */
	EN=1;				/* write enable ie,H->L     */
	PORTD=COMM;			/* move command to LCD port */
	__delay_us(30);			/* delay for write          */
	EN=0;				/* disable write            */
}
This,by itself works just fine

The problem i ran into,was when i tried integrating a PWM generation along with this code.
Code:
void PWM_INIT(void)
{


	PR2 = 0b10011011 ;
	T2CON = 0b00000111 ;
	CCPR1L = 0b00001111 ;
	CCP1CON = 0b00101100 ;
}

The kit i own has RC1 & RC2 Hardwired as the LCD module's RS and Enable Pins respectively.Which,ofcourse,happen to be my CCP1 & CCP2 pins(Talk about inconvenient)
Hence,Generating a PWM while trying to display the dynamic change of the encoder feedback goes out the window.

I was wondering if there was any soft way to work around this hard impediment.
Time multiplexing the display with the pwm maybe?I dont mind if pwm gets jittery due to it,its just for demonstration purpose(i tried,but display was still not agreeable.)

Any suggestions?
 
Can you drop it in or is it a surface mount device... It has a enhanced CCP I think you can use different pins..


Ian to the rescue as always :)
no,i'm afraid thr is nothing i can do with with the hardware...as for enhanced CCP,i am not sure i follow you.dont remember reading anyting like that in the datasheet
could u elaborate a bit please?
it'd be a lifesaver if i could shift the pwm to another pin.
 
I take it you need half bridge? Without changing the hardware we're a bit stuck... Short of unpicking the pcb and inserting a 2:4 multiplexer, there is not much left unless you go down the software PWM approach... 1.2khz will be possible at around 7 bits precision..

I think the PWM outputs are pretty much fixed in the pic16f877a ( quite an old chip now )... At least with the pic16f887 you can have single output on P1C and P1D...
 
This is what i tried:

software multiplex the pwm generation and display.

Code:
LCD INIT
LCD COMM
PWM INIT
start pwm(i.e. CCP1CON = 0b00101100 ;)

ENCODER POLLING LOOP()
{
update encoder position
stop PWM(CCP1CON = 0b00000000 ;)
display hundreds count
display tens count
display ones count
left shift cursor
left shift cursor
left shift cursor
re-start pwm
}

This led to unexpected left shift operstions(way more than in code)

hence i tried without the left shifts to figure out exactly how the code was being interpreted by the controller

i was expecting a count setuence like this:
Code:
000,001,002,003,004....
however,the display was
Code:
0001,1002,2003,3004
i.e,the previous 'ones count' was being repeated during the start of the display sequence.

any ideas as to why this happened?
everything else works as expected: pwm works,encoder feedback is counted properly
as long as i can get the display fixed,out should work out fine.

can some experienced hand give any ideas as to why this is happening?
 
Last edited:
display 3 digits,then shift cursor left thrice that was what i was doing initially without the pwm
effectively overwrites the previously printed 3 digits in the next cycle,if you see where i was going with that.worked just fine before i introduced the pwm

once pwm was introduced(even when time multiplexed with display), everything went bonkers
 
Last edited:
Ok! so are you still using the hardware PWM? It WILL interfere with the LCD.... every time you use the PWM whatever is on the LCD port will be clocked as a command or data depending on the state of CCP1 and CCP2.

Look at the LCD datasheet and see what condition to leave the LCD data port as to not cause too much bother... ie... 0 is return to home and clear screen. 1 is move cursor.. etc...
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top