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.

Timing problem in PIC controller

Status
Not open for further replies.

srevish

Member level 2
Joined
Apr 23, 2013
Messages
48
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,661
Dear All,

I am using PIC 16F676 controller for my project. I am using this controller to control the relay. As per the program the relay must be closed at 1.30 mins(90 seconds) but it starts to work from 1.19 mins itself. How can I match this timing.

Kindly help me to solve this problem.
 

You are not giving much information for us to go on.

Things to check:
1. is the clock speed correct and does the real hardware match the setting in software?
2. are you using software delays or one of the hardware timers. If using hardware timers do you have the prescalers set correctly?
3. Is something else being done in the program at the same time that could be interfering with the timing?
4. are you loading the correct values into the timer as the program starts as well as when it is running?

Brian.
 

    V

    Points: 2
    Helpful Answer Positive Rating
You are not giving much information for us to go on.

Things to check:
1. is the clock speed correct and does the real hardware match the setting in software?
2. are you using software delays or one of the hardware timers. If using hardware timers do you have the prescalers set correctly?
3. Is something else being done in the program at the same time that could be interfering with the timing?
4. are you loading the correct values into the timer as the program starts as well as when it is running?

Brian.

Thank you very much for your reply, I am using the software delay. I have given the program below pls make a note of it

void interrupt isr(void)
{
if(TMR1IF)
{
TMR1IF=0;
preload_tmr1();
if(sec_count++>20) //20
{
sec_count=0;
if(!dew_flag)
min_count++;
if(min_count>=266)
min_count=0;
}
if(!switch1)
count++;
if(switch1)
count=0;
tensec_count--;
if(tensec_count==0)
{
sec_7_flag=0;
count=0;
}
if(count>=70)
{
sec_7_flag=1;
tensec_count=200;
count=0;
}
 

That's a hardware delay using Timer 1.
If the speed is wrong it implies the value you load into TMR1 is wrong in the routine "preload_tmr1()" which you haven't posted. The correct value depends on the clock speed so I can't tell you what it should be without knowing it.

Brian.
 

That's a hardware delay using Timer 1.
If the speed is wrong it implies the value you load into TMR1 is wrong in the routine "preload_tmr1()" which you haven't posted. The correct value depends on the clock speed so I can't tell you what it should be without knowing it.

Brian.

Dear Brain, pls make a note on the program mentioned below. It will be very helpful if I receive any suggestions from your end.

#include<htc.h>
#define PB(p,b) ((unsigned)&(p)*8+(b))
#define gen_init() PORTA=0,PORTC=0,TRISA=0x0c,TRISC=0,CMCON=0x07,OSCCAL=0xff,OPTION=0X80,\
INTCON=0,IOCA=0,PIE1=0;T1CON=0x00,VRCON=0;

bit dew_input @ PB(PORTA,2); //
bit switch1 @ PB(PORTA,3); //
bit PIN2_led1 @ PB(PORTA,5); //
bit PIN3_led2 @ PB(PORTA,4); //
bit PIN5_led6 @ PB(PORTC,5);
bit PIN10_led9 @ PB(PORTC,0);
bit Dewpoint_Switch @ PB(PORTA,0); // This is actually pin 13
bit PIN12_led10 @ PB(PORTA,1); //
bit PIN6_40_percent_led3 @ PB(PORTC,4);
bit PIN7_60_percent_led4 @ PB(PORTC,3); //
bit PIN8_80_percent_led5 @ PB(PORTC,2); //
bit PIN9_100_percent_led7 @ PB(PORTC,1); //
#define preload_tmr1() TMR1H=0x15,TMR1L=0x50; //0.5 sec delay
#define init_tmr1() T1CON=0x00,PIE1=0x01,PEIE=1;
#define enable_tmr1 TMR1ON=1;
#define disable_tmr1 TMR1ON=0;
unsigned char sw_count,count,data,tensec_count,sec_count;
unsigned int min_count,min_5_count;
bit sec_7_flag,dew_flag,init_flag,dec_flag;
void eeprom_write1(void)
{
EECON1=0;
EEIF=0;
EEADR=0x05;
EEDATA=sw_count; //LS BYTES pulse_width DATA save
WREN=1;
EECON2=0x55;
EECON2=0xaa;
WR=1;
while(!EEIF);
asm("nop");
}
void eeprom_read1(void)
{
EEADR=0x05;
EEDATA=0;
EECON1=0;
RD=1;
while(RD);
data=EEDATA;
}

void led_set1(void)
{
PIN3_led2=0;
PIN2_led1=0;
PIN5_led6=0;
PIN10_led9=0;
Dewpoint_Switch=1;
PIN12_led10=0;
}
void led_set2(void)
{
PIN3_led2=0;
PIN2_led1=1;
PIN5_led6=0;
PIN10_led9=0;
Dewpoint_Switch=0;
PIN12_led10=1;
}
void led_set3(void)
{
PIN3_led2=1;
PIN2_led1=0;
PIN5_led6=0;
PIN10_led9=0;
Dewpoint_Switch=0;
PIN12_led10=1;
}
void led_set4(void)
{
PIN3_led2=0;
PIN2_led1=0;
PIN5_led6=1;
PIN10_led9=0;
Dewpoint_Switch=0;
PIN12_led10=0;
}
void led_set5(void)
{
PIN3_led2=0;
PIN2_led1=0;
PIN5_led6=0;
PIN10_led9=1;
Dewpoint_Switch=1;
PIN12_led10=0;
}
void interrupt isr(void)
{
if(TMR1IF)
{
TMR1IF=0;
preload_tmr1();
if(sec_count++>20) //20
{
sec_count=0;
if(!dew_flag) //If dew_flag is true it means dew point is good and timing will not be incremented. stretch
min_count++; // Dew point poor and timing incremented
if(min_count>=266)
min_count=0;
}
if(!switch1)
count++;
if(switch1)
count=0;
tensec_count--;
if(tensec_count==0)
{
sec_7_flag=0;
count=0;
}
if(count>=70)
{
sec_7_flag=1;
tensec_count=200;
count=0;
}
switch(sw_count)
{
case 1:
PIN6_40_percent_led3=1;
PIN9_100_percent_led7=0;
if(min_count<=2)
led_set5();
else if(min_count>2 && min_count<30)
led_set1();
else if(min_count==30)
{led_set1();
if(dew_input) {dew_flag=0;}
else {dew_flag=1;}
}
else if(min_count>=31 && min_count<=66)
led_set2();
else if(min_count>66 && min_count<150)
led_set3();
else if(min_count==150)
{
led_set3();
if(dew_input) {dew_flag=0;}
else {dew_flag=1;}
}
else if(min_count>150 && min_count<=186 )
led_set4();
else if (min_count<=240)
led_set1();
break;

case 2:
PIN7_60_percent_led4=1;
PIN6_40_percent_led3=0;
if(min_count<=2)
led_set5();
else if(min_count>2 && min_count<30)
led_set1();
else if(min_count==30)
{
led_set1();
if(dew_input) {dew_flag=0;}
else {dew_flag=1;}
}
else if(min_count>=31 && min_count<=84)
led_set2();
else if(min_count>84 && min_count<150)
led_set3();
else if(min_count==150)
{
led_set3();
if(dew_input) {dew_flag=0;}
else {dew_flag=1;}
}
else if(min_count>150 && min_count<=204 )
led_set4();
else if (min_count<=240)
led_set1();
break;

case 3:
PIN8_80_percent_led5=1;
PIN7_60_percent_led4=0;
if(min_count<=2)
led_set5();
else if(min_count>2 && min_count<30)
led_set1();
else if(min_count==30)
{
led_set1();
if(dew_input) {dew_flag=0;}
else {dew_flag=1;}
}
else if(min_count>=31 && min_count<=102)
led_set2();
else if(min_count>102 && min_count<150)
led_set3();
else if(min_count==150)
{
led_set3();
if(dew_input) {dew_flag=0;}
else {dew_flag=1;}
}
else if(min_count>150 && min_count<=222 )
led_set4();
else if (min_count<=240)
led_set1();
break;

case 4:
PIN9_100_percent_led7=1;
PIN8_80_percent_led5=0;
if(min_count<=2)
led_set5();
else if(min_count>2 && min_count<33)
led_set1();
else if(min_count==33)
{
led_set1();
if(dew_input) {dew_flag=0;}
else {dew_flag=1;}
}
else if(min_count>=34 && min_count<=133)
led_set2();
else if(min_count>134 && min_count<166)
led_set3();
else if(min_count==166)
{
led_set3();
if(dew_input) {dew_flag=0;}
else {dew_flag=1;}
}
else if(min_count>166 && min_count<=266 )
led_set4();

break;
} //end of switch
}
}

void main(void)
{
gen_init();
init_tmr1();
GIE=1;
PIN3_led2=0;
PIN2_led1=0;
PIN5_led6=0;
dew_flag=0;
sec_7_flag=0;
PIN10_led9=0;
//Dewpoint_Switch=0;
PIN12_led10=0;
PIN6_40_percent_led3=0;
PIN7_60_percent_led4=0;
PIN8_80_percent_led5=0;
PIN9_100_percent_led7=0;
preload_tmr1();
min_5_count=0;
sw_count=4;
init_flag=1;
min_5_count=0;
eeprom_read1();
if(data==0xff)
sw_count=4;
else
sw_count=data;
enable_tmr1;

while(1)
{
if(sec_7_flag||init_flag)
{
while(tensec_count||init_flag)
{
init_flag=0;
if(!switch1)
{
while(!switch1);
sw_count++;
if(sw_count>=5)
sw_count=1;
min_count=0;
eeprom_write1();
tensec_count=200;
}
}
}
}
}
 

PLEASE use code tags to make it more readable.

Your problem is in the line "#define preload_tmr1() TMR1H=0x15,TMR1L=0x50; //0.5 sec delay" at the beginning of the program.
Firstly, it isn't a good idea to use #define to declare a function name to be lines of code. It works but the code becomes confusing and some names will cause errors. Create a function with those lines in it instead or just add the lines where needed in the program.

I still can't tell you the correct values to use to get the correct timing because it depends on the clock speed which you haven't told us. The interrupt routine is called when timer 1 has counted up from 0x1550 to 0xFFFF and then rolled over but how long that takes depends on how long each count takes and that is proportional to the clock speed. Please read the data sheet about timer 1 for more information on calculating the prescaler and count values.

Brian.
 

PLEASE use code tags to make it more readable.

Your problem is in the line "#define preload_tmr1() TMR1H=0x15,TMR1L=0x50; //0.5 sec delay" at the beginning of the program.
Firstly, it isn't a good idea to use #define to declare a function name to be lines of code. It works but the code becomes confusing and some names will cause errors. Create a function with those lines in it instead or just add the lines where needed in the program.

I still can't tell you the correct values to use to get the correct timing because it depends on the clock speed which you haven't told us. The interrupt routine is called when timer 1 has counted up from 0x1550 to 0xFFFF and then rolled over but how long that takes depends on how long each count takes and that is proportional to the clock speed. Please read the data sheet about timer 1 for more information on calculating the prescaler and count values.

Brian.

sir, the system clock is 20MHz, I not able to find the clock speed.
 

The clock speed IS the system clock. The way you produce the delays is to trigger an interrupt as timer 1 overflows so how long that takes will depend on how fast it counts and that in turn depends on the clock speed. That's why I needed to know it to check your calculations.

With T1CON set to zero you are using a 1:1 prescaler so the actual count rate is 20MHz/4 = 5MHZ. Pre-loading the timer with 0x1550 means it has to count 0xEA60 (6,000 in decimal) between each interrupt so they occur every 0.012016 seconds (just over 83 times per second). I'm afraid it's almost impossible to follow the rest of your ISR code the way you posted it to see what happens after that. It's difficult to even see where the ISR ends!. I can warn you that it isn't a good idea to do lots of calculations inside the ISR, simply setting a flag and exiting is a better strategy, you can then monitor the flag in the main() code without risk of missing other interrupts.

If you want a more accurate time count, set the Timer 1 prescaler to 1:8 and pre-load it with 0x0BDC. It will then generate an interrupt every 0.1 seconds.

Brian.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top