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

CCP2 capture problem

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



Joined: 28 Aug 2007
Posts: 99
Location: New Zealand

View user's profile Send private message

CCP2 capture problem
PostPosted: Thu Apr 10, 2008 9:34 pm     Reply with quote

I am using CCP setup to capture a rising edge but it seems to be very inacurate. Am i doing something wrong?

here is my code. when i have tested it the serial isr have not been used.

i used a frequency generator for the interupt varing from 10 to 1000 Hz of a motor RPM of 600 to 60000 RPM.


Code:
#include <16F877a.H>
#device icd=true
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
#use rs232(baud = 19200, xmit=PIN_C6, rcv = PIN_C7, ERRORS)

#include <Variables.c>
#include <Flex_LCD420.c>
#include <Initialize.c>
#include <Button_Scan.c>
#include <Display_LCD.c>
#include <Serial_Output.c>
#include <Sort_Input.c>
#include <Set_PID.c>
#include <Flash_LED.c>

#include <input.c>
#include <string.h>

//=====================================================================

#int_rda
void serial_isr()
   {
      i = 0;
     
      for(i = 0; i < 32; i++) // if Set i upper limit to Serial_Array_Size(21) then will
                              //exit as soon as full and do not need return
         {
            value = getc();
            Serial_Input[i] = value;
         }
      Display_Update = 1;    // Update LCD
   }   
   
#int_ccp2
void isr()
   {     
      Rise = CCP_2;       // Capture rising edge
         if (Rise < 125)
               {Rise = 125;}
         if (Rise > 60000)
               {Rise = 60000;}
      Actual_Speed = 75000/Rise;  // [ 60s * (clock/4) / div_by ] / Pulse - must devide by 100 coz of rounding next line
      Actual_Speed = Actual_Speed * 100; // Rounding to nearest 100
         if (Actual_Speed != Old_Speed)
               {  Speed_Update = 1;
                  PWM_Update = 1; }
      Old_Speed = Actual_Speed;
      set_timer1(0);       // Reset timer
   } 
   
//=====================================================================

void main()
   {
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   setup_timer_2(T2_DIV_BY_16, 155, 1); //(1/4000000)*4*16*156=400.6Hz PWM
   
   setup_ccp1(CCP_PWM);   // Configure CCP1 as a PWM
   setup_ccp2(CCP_CAPTURE_RE);    // Configure CCP2 to capture fall   
   
   enable_interrupts(int_rda);
   enable_interrupts(INT_CCP2);
   enable_interrupts(GLOBAL);
   
   Initialize();
   
         while(1)
            {       
               Flash_LED();           
               Button_Scan(); // Scan button matrix
   
                  if (Speed_Update == 1)
                     {
                        Display_LCD();
                        Speed_Update = 0;
                     }
                       
                  if (Display_Update == 1)
                     { 
                        Sort_Input_Array();
                           Display_LCD();
                              Serial_Output_Array();
                           Display_Update = 0;
                     }
                     
                  if (PWM_Update == 1)
                     {                     
                        Set_PID();
                           set_pwm1_duty(PWM_Duty);
                        PWM_Update = 0;
                     }
            }
   }
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 11, 2008 12:10 am     Reply with quote

You're not using interrupts in the normal way. Interrupts are supposed
to be a short, quick event that doesn't delay the main process or
other interrupts. But in your #int_rda routine, you lock-up the PIC
inside the routine for 32 character times. That's about 16 ms. You can't
service any other interrupts (such as the CCP) during that time.
Your CCP interrupt has some time-consuming math operations in it.

Look at the Ex_Sisr.c example file, to see how to get one character
for each RDA interrupt, and put it into a buffer.

Most of the CCP code could be moved to main().
http://www.ccsinfo.com/forum/viewtopic.php?t=29963
umka



Joined: 28 Aug 2007
Posts: 99
Location: New Zealand

View user's profile Send private message

PostPosted: Sat Apr 12, 2008 2:02 am     Reply with quote

Cheers PCM

so this is the code that i got working accurately.

Code:
#int_ccp2
void CCP2_isr()
   {     
      Current_CCP2 = CCP_2;       // Capture rising edge
         ISR_CCP2_Delta = Current_CCP2 - Old_CCP2;
            Old_CCP2 = Current_CCP2;
               CCP2_Update = 1;  // Set Flag
   } 
   


and then i do the RPM calculation in a the main routine when the CCP2_Update flag has been set

Code:
void Calculate_Speed()
   {
      disable_interrupts(GLOBAL);
         Main_CCP2_Delta = ISR_CCP2_Delta;
            enable_interrupts(GLOBAL);
       
         Actual_Speed = 750000/Main_CCP2_Delta;  // [ 60s * (clock/4) / div_by ]
         Actual_Speed = Actual_Speed * 10; // Rounding to nearest 10
         
            if (Actual_Speed != Old_Speed)
                  { PWM_Update = 1; }
                     
         Old_Speed = Actual_Speed;
      CCP2_Update = 0;
   }


do i need to do the disable interupts then get int16 value and store as new variable and then enable interupts.
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