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] PIC16F877A: how to set a time limit for my DC motor to run on?

Status
Not open for further replies.
Guys, the timer is running, but i think its running awfully quick no matter what value for my timer i am setting! I have been troubleshooting for awhile now, but no differences. Please do look into this for me? Thank you.

Code:
void timer1(unsigned long data1)
{
//Timer1 Registers Prescaler= 8 - TMR1 Preset = 3036 - Freq = 10.00 Hz - Period = 0.100000 seconds
T1CKPS1 = 1;   // bits 5-4  Prescaler Rate Select bits
T1CKPS0 = 1;   // bit 4
T1OSCEN = 1;   // bit 3 Timer1 Oscillator Enable Control bit 1 = on
T1SYNC = 1;    // bit 2 Timer1 External Clock Input Synchronization Control bit...1 = Do not synchronize external clock input
TMR1CS = 0;    // bit 1 Timer1 Clock Source Select bit...0 = Internal clock (FOSC/4)
TMR1ON = 1;    // bit 0 enables timer
TMR1H = 11;             // preset for timer1 MSB register
TMR1L = 220;             // preset for timer1 LSB register
TMR1IF = 0;
TMR1IE = 1;

if (TMR1IF == 1)
{
TMR1IF=0;
counter++;
if(counter>=data1)
{
counter=0;
}
}
}

this is the piece of code i am using to demonstrate the the timer:

Code:
void tenminutes(void)
{		
	
	lcd_clr() ;								// clear LCD screen 				
	lcd_goto(0) ;							// set the position of message to be displayed
	send_string("Drying In        ");			// send message to be displayed
	lcd_goto(20);							// set the position of message to be displayed
	send_string("Process");
	for(;;)
		{
		timer1(10000);
		lcd_goto(27);
		send_string(".");
		timer1(10000);
		lcd_goto(28);
		send_string(".");
		timer1(10000);
		lcd_goto(29);
		send_string(".");
		timer1(10000);
		lcd_goto(27);
		send_string(" ");
		timer1(10000);
		lcd_goto(28);
		send_string(" ");
		timer1(10000);
		lcd_goto(29);
		send_string(" ");
		}	
}
 

You've got it all wrong.

You're not supposed to call the interrupt routine.
It occurs on it's own when Interrupts are enabled and a timer is configured.
 

I have been working on one more with reference to this website FAQ for PIC micros and Hi-Tech C

Code:
void init_timer1(void)
{
//Timer1 Registers Prescaler= 8 - TMR1 Preset = 3036 - Freq = 10.00 Hz - Period = 0.100000 seconds
T1CKPS1 = 1;   // bits 5-4  Prescaler Rate Select bits
T1CKPS0 = 1;   // bit 4
T1OSCEN = 1;   // bit 3 Timer1 Oscillator Enable Control bit 1 = on
T1SYNC = 1;    // bit 2 Timer1 External Clock Input Synchronization Control bit...1 = Do not synchronize external clock input
TMR1CS = 0;    // bit 1 Timer1 Clock Source Select bit...0 = Internal clock (FOSC/4)
TMR1ON = 1;    // bit 0 enables timer
TMR1H = 11;             // preset for timer1 MSB register
TMR1L = 220;             // preset for timer1 LSB register
TMR1IE = 1;
GIE = 1;
PEIE=1;
while (1)
{
}
}

void interrupt_isr(void)
{
if (TMR1IF)
{
TMR1IF=0;
}
}

void timer1(unsigned long data1)
{
do{
counter++;
if (counter>=data1)
{
counter=0;
}
}while(TMR1IF);
}

Code:
void tenminutes(void)
{		
	init_timer1();
	lcd_clr() ;								// clear LCD screen 				
	lcd_goto(0) ;							// set the position of message to be displayed
	send_string("Drying In        ");			// send message to be displayed
	lcd_goto(20);							// set the position of message to be displayed
	send_string("Process");
	for(;;)
		{
		timer1(10);
		lcd_goto(27);
		send_string(".");
		timer1(10);
		lcd_goto(28);
		send_string(".");
		timer1(10);
		lcd_goto(29);
		send_string(".");
		timer1(10);
		lcd_goto(27);
		send_string(" ");
		timer1(10);
		lcd_goto(28);
		send_string(" ");
		timer1(10);
		lcd_goto(29);
		send_string(" ");
		}	
}

the result: nothing actually displayed on my LCD. It just jumps back to main menu all the time i select it. Is there an explanation?

You're not supposed to call the interrupt routine.
It occurs on it's own when Interrupts are enabled and a timer is configured.
Then, how does i know that when it interrupts and it will execute my codes? I feel that's the missing link right now. I'm trying to relate to my executing codes right now, and it's not working well.
 

Hi,
Then, how does i know that when it interrupts and it will execute my codes? I feel that's the missing link right now. I'm trying to relate to my executing codes right now, and it's not working well.
Whenever the timer overflows after a fixed time, the interrupt occurs on its own. When you clear the flag and exit the ISR the next interrupt occurs after the defined time.
This is how I would do things:
First initialize Timer 1, by setting prescaler to 8 and keeping timer off like:
Code:
T1CON = 0x30; //PRESCALER = 8, TIMER KEPT OFF
I would use the CCP module, or atleast the Compare module from there. Using the CCP module, CCPR1[H:L] I would set compare value at 62499. This would set the compare at every 100ms. Initialization:
Code:
CCP1CON = 0x0B; //Compare, generate interrupt and clear timer
CCPR1H = 0xF4; //F423 is hex for 62499
CCPR1L = 0x23; //These set the compare value at 62499
Then turn PEIE, GIE, CCP1IE on.
Code:
INTCONbits.GIE = 1; //Enable global interrupts
INTCONbits.PEIE = 1; //Enable peripheral interrupt
PIE1bits.CCP1IE = 1; //Enable CCP interrupt
PIR1bits.CCP1IF = 0; //Clear CCP flag
Enable timer:
Code:
T1CONbits.TMR1ON = 1;

The interrupt will now occur every 100ms.

In the ISR have a register that increments.
Code:
varinc = varinc + 1;

Whenever, varinc = 600, 60 seconds elapsed. Clear varinc and increment another variable to show that a minute has passed. To increment by ten minutes, just increase the minutes counter by 10. Do your work as required, by checking the values of varinc and the minutes counter.

Hope this helps.
Tahmid.
 

Tahmid,

Wouldn't it be better to have the highest timebase you can possibly make (500ms instead of 100ms) so that your MCU spends less time processing interrupts?

For example: in order to count one second, 10 interrupts need to occur with a 100ms time base, and only 2 if you have the 500ms time base.
 

Tahmid,

Wouldn't it be better to have the highest timebase you can possibly make (500ms instead of 100ms) so that your MCU spends less time processing interrupts?

For example: in order to count one second, 10 interrupts need to occur with a 100ms time base, and only 2 if you have the 500ms time base.

Yes, it would, but you can't get 500ms with TMR1 at 20MHz. At 20MHz, 65536 * 8 * (1/5MHz[since clock is divided by 4]) = roughly around 105ms. Prescaler max for Timer1 is 8, that's what limits it. That's why I chose 100ms. If you get 500ms, that would be better, but you can't get that at 20MHz clock.

Hope this helps.
Tahmid.
 

Ah, my mistake. I kept thinking it's 4MHz because I used that in the example, and then went with it. :D
 

@Tahmid & jumper2high, I thank you for your responses, but I have spent a good deal of time troubleshooting, but my results are poor.

I am using MPLAB to do the compilation, but when i used Tahmid's setting's

Code:
INTCONbits.GIE = 1; //Enable global interrupts
INTCONbits.PEIE = 1; //Enable peripheral interrupt
PIE1bits.CCP1IE = 1; //Enable CCP interrupt
PIR1bits.CCP1IF = 0; //Clear CCP flag
T1CONbits.TMR1ON = 1;

and do compilation, it gave me errors about issues with the INTCONbits. and T1CONbits. and PIE1bits. and PIR1bits. and needing me to use struct/union, so i removed all of it to look like this, and the compilation succeeded:

Code:
GIE = 1; //Enable global interrupts
PEIE = 1; //Enable peripheral interrupt
CCP1IE = 1; //Enable CCP interrupt
CCP1IF = 0; //Clear CCP flag
TMR1ON = 1;

will this still function in my code? If it does, then i believe my problem is still around. I tried my best to follow what Tahmid has guided me on, so i produced these codes and included it under my PIC's initialization function. Because a friend of mine gave me this link PIC Timer Calculator, it helped me to produce a similar setting to Tahmid's one too i think.

Code:
//Timer1 Registers Prescaler= 8 - TMR1 Preset = 3036 - Freq = 10.00 Hz - Period = 0.100000 seconds
	T1CKPS1 = 1;   // bits 5-4  Prescaler Rate Select bits
	T1CKPS0 = 1;   // bit 4
	T1OSCEN = 1;   // bit 3 Timer1 Oscillator Enable Control bit 1 = on
	T1SYNC = 1;    // bit 2 Timer1 External Clock Input Synchronization Control bit...1 = Do not synchronize external clock input
	TMR1CS = 0;    // bit 1 Timer1 Clock Source Select bit...0 = Internal clock (FOSC/4)
	TMR1ON = 0;    // bit 0 enables timer
	TMR1H = 11;             // preset for timer1 MSB register
	TMR1L = 220;             // preset for timer1 LSB register
	GIE = 1; //Enable global interrupts
	PEIE = 1; //Enable peripheral interrupt
	TMR1IE = 1;

Will this work in my codes? If it does, that means my problem is still around. Here is the ISR i develop based on Tahmid's guide, i hope its correct:

Code:
void interrupt_isr(void)
{
if(TMR1IF==1)
{
varinc = varinc + 1;
if (varinc >= 600)
{
counter++;
varinc = 0;
}
}
}

and here is my code that i tried to see whether everything is working:

Code:
void tenminutes(unsigned int data1)
{
TMR1ON = 1;
data1 = 1;
if (counter<data1)
{
	motor_1 = 1;
	motor_speed = 115;	
	lcd_clr();			// clear LCD screen 				
	lcd_goto(0) ;		// set the position of message to be displayed
	send_string("Drying In");	// send message to be displayed
	lcd_goto(20);		     // set the position of message to be displayed
	send_string("Process.");
}
else if (counter>=data1)
{
	motor_1 = 0;
	motor_speed = 0;
	lcd_clr() ;				// clear LCD screen 				
	lcd_goto(0) ;		// set the position of message to be displayed
	send_string("Drying Is");	// send message to be displayed
	lcd_goto(20);		// set the position of message to be displayed
	send_string("Complete!");
}
}

although i have written 10 minutes, i just wanted to see how it will work in 1 minute first, that's why i written data1 = 1. I am not sure what is not correct, but all i know is the result:

The motor doesn't turn at all.
But my LCD display shows me:
Drying In
Process.
But it DOESN'T change to Drying Is Complete even after 1 minute. Still the motor is not turning up to now.

Please help me point out my mistakes? Honestly at the moment, my morale has been shot down after trials and trials of adjustments, but I will to keep trying. Please help me, thank you.
 

Unfortunately, Desmond, as much as we both wanted to help you, there's so much you'd need to learn it'd be impossible condensing it into one topic.
 

@jumper2high, i understand there's plenty for me to learn, but i really have tried to do what i could. i am new in this and it has been plenty of nights that i am forced to stay so late up, just to be able to correspond with you guys frequently. i hope that if you may ease my burden, please help me correct my codes, where i will realize my mistakes clearer, so i can move on to complete this project of mine. Please.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top