Author Topic: PIC16 XC8 CCP Capture module issues?  (Read 1719 times)

0 Members and 1 Guest are viewing this topic.

Offline nexusTopic starter

  • Regular Contributor
  • *
  • Posts: 217
  • Country: us
PIC16 XC8 CCP Capture module issues?
« on: February 07, 2021, 03:30:27 am »
Hi all,

Almost ready to call my first pic project done... its been a long road and lots of lessions learned. I've been developing on the second rev of a custom 16F1788 board I made.

Last issue I'm running into is an issue using one of the CCP modules to Capture. Since this project is for a fan controller, I have PWM going out to the fan on CCP1 and the fan tachometer signal on CCP2. I've got the PWM on CCP1 working no problem. I'm just struggling to get CCP2 to capture the tachometer period so I can calculate RPM and display it.

I've read and reread the datasheet as well as found some helpful examples.
One such example I've referenced heavily is page 16 of this: http://ww1.microchip.com/downloads/en/Appnotes/00003381A.pdf

According to the datasheet, CCP modules use Timer1 (16 bits) in capture and compare modes. I believe I'm setting up the CCP2 and TMR1 registers correctly for my intentions:

Code: [Select]
Tach_Initialize() {
 //CCP modules use TMR1 as timebase in both capture and compare modes
 
 TMR1CS1 = 0; //Timer 1 clock source is instruction clock (Fosc/4)
 TMR1CS0 = 0;

 T1CONbits.nT1SYNC = 1; //
 
 T1CKPS1 = 1; //Timer 1 prescale value is 1:4
 T1CKPS0 = 0;
 
 TMR1ON = 1; // Timer1 always on
 TMR1GE = 0;
 
 //CCP2 config
 
 CCP2M3 = 0; //Capture on rising edge of CCP2 input (RB3)
 CCP2M2 = 1;
 CCP2M1 = 0;
 CCP2M0 = 1;
 
 CCPR2H = 0x00; //initialize CCP2 high and low registers to zero
 CCPR2L = 0x00;
 
 CCP2IF = 0; // Clear CCP2 interrupt request bit
 CCP2IE = 1; // Enable CCP2 peripheral interrupt
}

I also initialize RB3 as follows:

Code: [Select]
TRISB = (1<<3); //set RB3 as input
APFCON1 = (1<<0); //set bit 0 (RB3) as CCP2 in alternate pin register 1

The rest of my configs for general setup are as follows:
Code: [Select]
// CONFIG1
#pragma config FOSC = INTOSC      // INTOSC oscillator
#pragma config PLLEN = ON         //PLL ON
#pragma config WDTE = OFF            // WDT disabled
#pragma config PWRTE = OFF         // Power-up Timer disabled
#pragma config MCLRE = OFF           // MCLR/VPP pin function is MCLR
#pragma config CP = OFF                 // Code protection is disabled
#pragma config CPD = OFF              //  Data Memory Code Protection disabled
#pragma config BOREN = OFF         // Brown-out Reset disabled
#pragma config CLKOUTEN = OFF  // Clock Out  disabled.
#pragma config IESO = OFF             // Internal/External Switchover disabled
#pragma config FCMEN = OFF         // Fail-Safe Clock Monitor is disabled

// CONFIG2
#pragma config WRT = OFF            // Flash Memory Self-Write Protection off
#pragma config PLLEN = ON          // PLL Enable (4x PLL enabled)
#pragma config STVREN = OFF     // Stack Overflow /Underflow reset disabled
#pragma config BORV = LO           // Brown-out Reset Voltage Selection
#pragma config LVP = OFF            // Low-Voltage Programming disbled

finally, I have an ISR which runs a few things, including the display update and a rotary encoder scan, into which ive also added the fan tachometer routine I mimicked from that microchip resource:

Code: [Select]
void __interrupt() display_encoder  (void) {
   
if(INTCONbits.T0IF && INTCONbits.T0IE) {// if timer flag is set & interrupt enabled
TMR0 -= 250;

//display routine...
//encoder routine...
//fan tachometer 
       
    ccp2val =(CCPR2H <<8)^CCPR2L;
    //or
    //    ccp2val = CCPR2L;
    //    ccp2val|= CCPR2H*256U;
 
    prevCapt1 = currentCapt1;
    currentCapt1 = ccp2val;
   
    if(currentCapt1 > prevCapt1) {
        fan1_tmr_val = currentCapt1 - prevCapt1; // Find tach period
    }
    else // Timer1 rolled over
    {
        fan1_tmr_val=(0xFFFF-prevCapt1)+currentCapt1;
    }
   
 fan1_spd = timer_const / fan1_tmr_val;
 
 CCP2IF = 0; //clear CCP2 interrupt flag
 T0IF = 0;      // clear timer0 interrupt flag
 
  }
}

however, even following the example closely and double and triple checking the datasheet to make sure CCP2 and TMR1 are configured correctly, I can't get any sensible numbers to display in correlation the fan speed. I have my scope hooked up across the tachometer input (RB3) which is an open collector that pulls low twice per fan rev. The square wave is perfectly fine, so I know signal is getting to RB3.

For reference, at low fan speeds the frequency is around 70hz (14.4ms period) and around 50% is 267hz or a 3.7ms period. Even though I'm using the TIMER_CONST in the example, I should at least get a value on my display even if it is totally incorrect. So far, nothing shows up when I try to display fan1_spd (I've verified that my display routine works with other numeric values).

Not sure where I'm making a mistake?
« Last Edit: February 07, 2021, 03:43:23 am by nexus »
 

Offline nexusTopic starter

  • Regular Contributor
  • *
  • Posts: 217
  • Country: us
Re: PIC16 XC8 CCP Capture module issues?
« Reply #1 on: February 07, 2021, 06:20:31 am »
A few more hours of suffering and I found a well enough documented example that worked: https://www.microchip.com/forums/m837075.aspx

Hope that link is helpful for others as well. I will be making the project open source soon! Schematic and some test setup pics attached.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

- - -
-->