View previous topic :: View next topic |
Author |
Message |
ferrarilib
Joined: 11 Jun 2005 Posts: 38
|
ccp Questions |
Posted: Thu Jun 30, 2005 2:16 am |
|
|
i am doing rpm counter and i am using cpp metode
#INT_CCP1
ccp1_isr()
{
Value=CCP_1-oldValue;
oldValue=CCP_1;
gotCCP1 = TRUE;
}
void main()
{
float freq;
char i;
Value=0;
oldValue=0;
gotCCP1 = TRUE;
setup_ccp1(CCP_CAPTURE_RE); // CCP1 - rising edge
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);// Timer1 interrupt
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
set_tris_C(0xAF); // All inputs except C4 and C6
while(TRUE) { // Start main program loop (endless)
while(!gotCCP1) // when is false stop and return 0.
{
Value=0;
}
freq=1.0/((float)Value*2e-6);
printf("Freq%f\r\n",freq);
gotCCP1 = FALSE;
}// while
}
but when i dont input signal the the output insn' t 0 but sametime the frequency sametime 0 !
there is sameone that can help me ?
how i can know when cpp interput is not used ?
thanks |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Thu Jun 30, 2005 3:25 am |
|
|
How is the variable 'value' defined? If the timer overflows between two rising edges (which it will), the line 'Value=CCP_1-oldValue;' may result in an incorrect value. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Thu Jun 30, 2005 4:08 am |
|
|
You have forgotten to clear the CCP1 interrupt before you enabled it. The interrup flag may already be set which means you will have an interrupt event occur immediately the interrupt is enabled. In this case the first reading is rubbish..
Also you are fighting your own interrupt handler with value being set in the mainline and in the interrupt handler. This is why you are getting silly values. I suspect what you meant to do was:
Code: |
while(TRUE) { // Start main program loop (endless)
while(!gotCCP1) // when is false stop and return 0.
;
disable_interrupt(INT_CCP1);
freq=1.0/((float)Value*2e-6);
gotCCP1 = FALSE;
enable_interrupt(INT_CCP1);
printf("Freq%f\r\n",freq);
}// while
} |
_________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
ferrarilib
Joined: 11 Jun 2005 Posts: 38
|
|
Posted: Thu Jun 30, 2005 4:12 am |
|
|
int16 Value,oldValue ;
but i don't undestand .
can you do example how works ?
thanks |
|
|
ferrarilib
Joined: 11 Jun 2005 Posts: 38
|
|
Posted: Thu Jun 30, 2005 4:26 am |
|
|
the problem is that when i dont have more interrupt the count stop
i have thy this too
while(TRUE) { // Start main program loop (endless)
disable_interrupts(INT_CCP1);
freq=1.0/((float)Value*2e-6);
gotCCP1 = FALSE;
enable_interrupts(INT_CCP1);
printf("Freq%f\r\n",freq);
}
but when the frequency is 0 reurrn always the last valure
|
|
|
Ttelmah Guest
|
|
Posted: Thu Jun 30, 2005 4:35 am |
|
|
I'd say the key problem is here:
Code: |
while(!gotCCP1) // when is false stop and return 0.
{
Value=0;
}
|
The problem is that lines of code take _time_.
Now imagine that you are sitting in this loop. The entire loop probably takes about 6 instructions. Immediately after the instruction testing for gotCCP being false, gotCCP goes true. The code will still execute the section corresponding to 'false' (it was false when tested...), and will _clear_ the value. Then on the next test, gotCCP is seen as 'true', and the code passes to the 'print', with a zero value...
Change the logic.
Use something like:
Code: |
if (gotCCP) {
freq=1.0/((float)Value*2e-6);
printf("Freq%f\r\n",freq);
gotCCP1 = FALSE;
}
|
If you want to print something when gotCCP is not true, then simply add an 'else', and print a message. Don't clear value.
Best Wishes |
|
|
ferrarilib
Joined: 11 Jun 2005 Posts: 38
|
|
Posted: Thu Jun 30, 2005 5:23 am |
|
|
Ttelmah wrote: | I'd say the key problem is here:
Code: |
while(!gotCCP1) // when is false stop and return 0.
{
Value=0;
}
|
The problem is that lines of code take _time_.
Now imagine that you are sitting in this loop. The entire loop probably takes about 6 instructions. Immediately after the instruction testing for gotCCP being false, gotCCP goes true. The code will still execute the section corresponding to 'false' (it was false when tested...), and will _clear_ the value. Then on the next test, gotCCP is seen as 'true', and the code passes to the 'print', with a zero value...
Change the logic.
Use something like:
Code: |
if (gotCCP) {
freq=1.0/((float)Value*2e-6);
printf("Freq%f\r\n",freq);
gotCCP1 = FALSE;
}
|
If you want to print something when gotCCP is not true, then simply add an 'else', and print a message. Don't clear value.
Best Wishes |
thanks !
But i have tired this too:
while(TRUE) { // Start main program loop (endless)
//val=get_timer1()-old;
//old=get_timer1();
if(gotCCP1)
{
freq=1.0/((float)Value*2e-6);
printf("Freq%f\r\n",freq);
gotCCP1 = FALSE;
}
else
{
printf("Freq%f\r\n",mio);
}
}// while
where mio =0;
and return
Freq34.435260\0D
Freq.000000\0D (why is 0 ?)
Freq.000000\0D (why is 0 ?)
Freq34.435260\0D
when capture and when not capture is good !
Freq.000000\0D
Freq.000000\0D
Freq.000000\0D
|
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Thu Jun 30, 2005 5:39 am |
|
|
Do this and tell us the results
Code: |
if(gotCCP1)
{
disable_interrupt(INT_CCP1) // MUST DO THIS
freq=1.0/((float)Value*2e-6);
enable_interrupt(INT_CCP1) // MUST DO THIS
printf("Here at A - Freq%f\r\n",freq);
gotCCP1 = FALSE;
}
else
{
printf("Here at B Freq%f\r\n",mio);
}
|
_________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Ttelmah Guest
|
|
Posted: Thu Jun 30, 2005 6:00 am |
|
|
I think I'd clear gotCCP, before re-anabling the interrupt. This woul allow it to again 'log' an edge that occured during the print time.
Best Wishes |
|
|
ferrarilib
Joined: 11 Jun 2005 Posts: 38
|
|
Posted: Thu Jun 30, 2005 6:08 am |
|
|
asmallri wrote: | Do this and tell us the results
Code: |
if(gotCCP1)
{
disable_interrupt(INT_CCP1) // MUST DO THIS
freq=1.0/((float)Value*2e-6);
enable_interrupt(INT_CCP1) // MUST DO THIS
printf("Here at A - Freq%f\r\n",freq);
gotCCP1 = FALSE;
}
else
{
printf("Here at B Freq%f\r\n",mio);
}
|
|
capture :
ere at B Freq .000000 ( ? )\0D
\0A
Here at B Freq .000000 ( ?)\0D
\0A
Here at A - Freq34.435260\0D
\0A
Here at B Freq .000000\0D (?)
i think that afther do last instruction go to while (TRUE) and restart another without take valure from interrupts !
i must insert a delay time because the frequency captured is low !
and the interrupt dont have time for set variable .
so works fine :
while(TRUE) { // Start main program loop (endless)
delay_ms (100); this permit wait interrupt
if(gotCCP1)
{
//disable_interrupts(INT_CCP1); // MUST DO THIS don 't cange nothing in output
freq=1.0/((float)Value*2e-6);
// enable_interrupts(INT_CCP1); // MUST DO THIS
printf("Here at A - Freq%f\r\n",freq);
gotCCP1 = FALSE;
}
else
{
printf("Here at B Freq%f\r\n",mio);
}
}// while
now i must set 2e-6
i have 8000000 clock and do 2000000 of cicle so i think that is correct do
freq=1.0/((float)Value*2e-6); ? is good ?
thanks |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Thu Jun 30, 2005 6:46 am |
|
|
Ttelmah wrote: | I think I'd clear gotCCP, before re-anabling the interrupt. This woul allow it to again 'log' an edge that occured during the print time.
Best Wishes |
Definately - my brain was out of gear :-) _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Last edited by asmallri on Thu Jun 30, 2005 7:11 am; edited 1 time in total |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Thu Jun 30, 2005 6:59 am |
|
|
If you are going to use interrupts then you MUST leave the enable and disable statements in place. Interrupts WILL corrupt the results, maybe not now, maybe not tomorrow, but it is as sure as night follows day.
Code: |
while(TRUE) { // Start main program loop (endless)
// the following line is not required unless for some reason you want multiple interrupts to occur
// delay_ms (100); this permit wait interrupt
if(gotCCP1)
{
disable_interrupts(INT_CCP1); // MUST DO THIS don 't cange nothing in output
freq=1.0/((float)Value*2e-6);
gotCCP1 = FALSE;
enable_interrupts(INT_CCP1); // MUST DO THIS
printf("Here at A - Freq%f\r\n",freq);
}
else
{
// I don't know why the following line is here as no interrupt
// will have occurred to change anything from last reading
// printf("Here at B Freq%f\r\n",mio);
}
}// while
|
Quote: |
now i must set 2e-6
i have 8000000 clock and do 2000000 of cicle so i think that is correct do
freq=1.0/((float)Value*2e-6); ? is good ?
thanks |
I don't understand the question. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
ferrarilib
Joined: 11 Jun 2005 Posts: 38
|
|
Posted: Thu Jun 30, 2005 7:16 am |
|
|
asmallri wrote: | If you are going to use interrupts then you MUST leave the enable and disable statements in place. Interrupts WILL corrupt the results, maybe not now, maybe not tomorrow, but it is as sure as night follows day.
Code: |
while(TRUE) { // Start main program loop (endless)
// the following line is not required unless for some reason you want multiple interrupts to occur
// delay_ms (100); this permit wait interrupt
if(gotCCP1)
{
disable_interrupts(INT_CCP1); // MUST DO THIS don 't cange nothing in output
freq=1.0/((float)Value*2e-6);
gotCCP1 = FALSE;
enable_interrupts(INT_CCP1); // MUST DO THIS
printf("Here at A - Freq%f\r\n",freq);
}
else
{
// I don't know why the following line is here as no interrupt
// will have occurred to change anything from last reading
// printf("Here at B Freq%f\r\n",mio);
}
}// while
|
Quote: |
now i must set 2e-6
i have 8000000 clock and do 2000000 of cicle so i think that is correct do
freq=1.0/((float)Value*2e-6); ? is good ?
thanks |
I don't understand the question. |
?
you tell to me that if i am mesure the frequency with period is not stable ?
my question is now i have clock pic to 8Mhz
and i must know frequency in hz
f=1/T ---> T= period
freq=1.0/((float)Value*2e-6);
2e-6 is the factor for have frequency in hz |
|
|
Ttelmah Guest
|
|
Posted: Thu Jun 30, 2005 3:17 pm |
|
|
What is the likely range of input frequencies involved?.
Remember that Timer1, is only a 16bit counter, so the maximum interval between clock edges that can be handled by the approach you are using here, corresponds to just over 30Hz (at 8MHz). If your frequency drops below this, you really need to add a timer1 interrupt, and increment a 'carry' bit, and use 32bit values for the count.
Conversely, if the frequency is relatively high, there will be significant 'jitter' in the measurement. If (for example), the time is about 0.1mSec/cycle, unless the clock is synchronous to the internal processor clock, values will jump between perhaps 199,and 201 counts, and the frequency measure will show about 1% fluctuation, even if the clock is perfectly stable.
Something seems to be 'screwy' about your maths.
As shown, a frequency of 10000Hz, will give counts around 200, and should be converted, by using:
freq=2E6/Value;
For the same count value, your conversion would give:
1/(200*2E-6) = 2500...
The single division will also need less maths time.
Best Wishes |
|
|
ferrarilib
Joined: 11 Jun 2005 Posts: 38
|
|
Posted: Fri Jul 01, 2005 12:36 pm |
|
|
thanks now i undastand and my project start go on ..
yes i have implement with timer1 (#INT_TIMER1) so i have carry bite. and i have used union variable for do it to 32 bit.
I have resolve the problem whitout delay but with
if(period>2000000)
{
period=0;
}
in the CCP1 function (interrupts) so dont give to me error
and all is good now. So when the cicle is down 2000000 (1hz) the counter give to me 0. |
|
|
|