CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

freq/phase measurement using multiple interrupts ...HELP!

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Guest








freq/phase measurement using multiple interrupts ...HELP!
PostPosted: Tue Jul 27, 2004 4:11 pm     Reply with quote

Hello, I'm using CCP1 and CCP2 to determine the frequency and phase angle between two signals. Both signals have the same freq (range is 1-100Hz) but can vary in phase wrt each other. This looked like a fairly simple task using CCP1 and CCP2 in capture mode: time between CCP1 captures gives the freq, time between CCP1 and CCP2 gives the phase.

This program works 99% of the time but gives a wild answer every few minutes. The errors seem to result from a late TIMER1 overflow (maybe not late...but definetly out of place). A sample output is below, read as freq(Hz), phase(deg), period(inst cycles) and phase(inst cycles). First at 12Hz, 2.42 deg ...every thing is going fine, and then disaster... notice that the period jumps up by 65536!
Next at a phase angle of 4.46deg apparently only CCP2 gets knocked-off by 2^16.

...
12.00 2.42 416635 2808
12.00 2.42 416635 2808
12.00 2.42 416635 2808
10.36 51.02 482171 68343
14.24 2.87 351099 2807
12.00 2.42 416636 2808
...
12.00 4.46 416635 5167
12.00 4.46 416635 5167
12.00 -52.16 416635 -60369
12.00 4.46 416636 5168
12.00 4.46 416635 5168

So I *think* I know whats happening...I'm just not sure how to avoid it. Any help would really be appreciated. Below is the code. My original program does more things (LCD, alarms, etc) but I removed all that to show the core problem (in case you are wondering why 20MHz, etc). The prog below compiles (PCW 3.202) and runs resulting in the above output. I tried using INT_TIMER1 FAST, but got the same results. What am I doing wrong? Is there something simpler than writing my oun int handler? Thanks.



// *****************************************************
#include <16F876.h>
#device *=16
#fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use delay(clock=20000000)
#use fast_io(C)
#priority timer1, ccp2, ccp1
#use rs232(baud=9600, xmit=PIN_C6)

// *****************************************************
signed int32 lastTime = 0, deltaTime = 0, period;
int16 overTime = 0;
int1 gotCCP1 = FALSE;

union{
int16 t[2]; // CCP1 capture timer - 32bits
int32 time;
} capture1;

union{
int16 t[2]; // CCP2 capture timer - 32bits
int32 time;
} capture2;

// *****************************************************
#INT_TIMER1
timer1_isr()
{ // OVERTIME - Incremented on Timer1 rollover to
overTime++; // increase timer resolution from 16 to 32 bits
}

// ******************************************************
#INT_CCP1
ccp1_isr()
{
capture1.t[1] = overTime;
capture1.t[0] = CCP_1;
period = capture1.time - lastTime;
lastTime = capture1.time;
deltaTime = capture1.time - capture2.time;
gotCCP1 = TRUE;
}

// ******************************************************
#INT_CCP2
ccp2_isr()
{
capture2.t[1] = overTime;
capture2.t[0] = CCP_2;
}

// ******************************************************
void main()
{
float freq, fperiod, phase, dTime;
float cnts2us = 5.0e6; // 1/(counts to microseconds) for 20MHz clock
char outMsg[40];

setup_ccp1(CCP_CAPTURE_RE); // CCP1 - rising edge
setup_ccp2(CCP_CAPTURE_RE); // CCP2 - rising edge
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);// Timer1 interrupt
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_CCP1);
enable_interrupts(INT_CCP2);
enable_interrupts(GLOBAL);

set_tris_C(0xAF); // All inputs except C4 and C6

while(TRUE) { // Start main program loop (endless)

while(!gotCCP1); // Wait for CCP1 interrupt
gotCCP1 = FALSE;

dTime = deltaTime;
fperiod = period;
freq = cnts2us / fperiod;
phase = (dTime / fperiod) * 360.0;
if (phase > 180.0) phase-=360.0; // Scale from 0-360 to +/-180

sprintf(outMsg,"%04.2f %04.2f %ld %ld\n\r",
freq,phase,period,deltaTime);
printf("%s",outMsg);
}
}

[/code]
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jul 27, 2004 5:05 pm     Reply with quote

Quote:
This program works 99% of the time but gives a wild answer
every few minutes.

See the following thread. It has sample code which shows
how to check for Timer1 overflow inside the CCP isr.
http://www.ccsinfo.com/forum/viewtopic.php?t=906

A related thread which talks about setting CCP pre-scaler
values and extending Timer1.
http://www.ccsinfo.com/forum/viewtopic.php?t=17806
c_merk



Joined: 27 Jul 2004
Posts: 1

View user's profile Send private message

PostPosted: Thu Jul 29, 2004 8:43 am     Reply with quote

Thanks PCM...You the MAN!
I added the timer1 check (TMR1IF) per your suggestion in both CCP int routines and that seems to do the trick. It's been going hours without a glitch! Code fragment is below. The output did not become well-behaved until testing for 3(or less) MSB counts on the CCP_1 register ( ...capture1.d[1] <=3), which surprised me because that seems to be a long time for a short ISR. I do have three interrupts contending for attention ...perhaps that explains it.
Your help is really appreciated.

...
#INT_CCP1
ccp1_isr()
{
static int32 lastTime=0;
int16 overTCopy;

capture1.t[0] = CCP_1;
overTCopy = overTime;
if (TMR1IF) {
if ( capture1.d[1] <=3) overTCopy++;
overTime++;
TMR1IF = 0;
}
capture1.t[1] = overTCopy;
period = capture1.time - lastTime;
lastTime = capture1.time;
if ((deltaTime = capture1.time - capture2.time)>0) gotCCP1 = TRUE;
}
...
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group