• AVR Freaks

Hot!RPM Measuring

Page: 12 > Showing page 1 of 2
Author
john_ive
Super Member
  • Total Posts : 217
  • Reward points : 0
  • Joined: 2017/05/22 22:22:08
  • Location: 0
  • Status: offline
2019/09/20 22:17:17 (permalink)
0

RPM Measuring

#include <xc.h>
#define _XTAL_FREQ 8000000

#include "lcd.h" //For LCD display
#define f_timer 8000000

// CONFIG1H
#pragma config OSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 3 // Brown Out Reset Voltage bits (Minimum setting)

// CONFIG2H
#pragma config WDT = OFF // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = OFF // Stack Full/Underflow Reset Enable bit (Stack full/underflow will not cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF // Code Protection bit (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection bit (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF // Code Protection bit (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection bit (Block 3 (006000-007FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF // Write Protection bit (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection bit (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF // Write Protection bit (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection bit (Block 3 (006000-007FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) not protected from table reads executed in other blocks)

void pin_define(void) {
    TRISA = 0b00000000;
    LATA = 0b00000000;

    ADCON1 = 0XFF;
    ADCON0 = 0XFF;
    CMCON = 0X07;

    TRISB = 0b00000011;
    LATB = 0b00000011;

    TRISC = 0b10100100;
    LATC = 0b10100100;

    TRISD = 0b11111100;
    LATD = 0b11111100;

    TRISE = 0b00000001;
    LATE = 0b00000001;
}

unsigned long signal_period, data1, data2;
int rev_pm;

void display_rpm(void);

void main() {
    pin_define();
    lcd_pins();
 
 
 
    PIE1bits.CCP1IE = 1;
    PIR1bits.CCP1IF = 0;
    CCP1CON = 0x04; //Detecting at rising edge
    CCPR1 = 0x00;
    TMR1IF = 0;
    T1CON = 0x82;
    TMR1 = 0;
    TMR1ON = 1;

    while (1) {
        while (!(PIR1bits.CCP1IF));
        PIR1bits.CCP1IF = 0;
        data1 = CCPR1;

        while (!(PIR1bits.CCP1IF));
        PIR1bits.CCP1IF = 0;
        data2 = CCPR1;
        signal_period = data2 - data1;
        rev_pm = f_timer / signal_period;
        rev_pm = rev_pm / 60;
        display_rpm();
        TMR1 = 0;
    }
}

void display_rpm(void) {
    long int a122, b122, c122, d122, e122, f122, i122, j122, k122, l122;

    a122 = rev_pm / 100000;
    b122 = rev_pm % 100000;

    c122 = b122 / 10000;
    d122 = b122 % 10000;

    e122 = d122 / 1000;
    f122 = d122 % 1000;

    i122 = f122 / 100;
    j122 = f122 % 100;

    k122 = j122 / 10;
    l122 = j122 % 10;

    lcd_goto(1, 1);
    lcd_puts("RPM:");
    lcd_put_num(a122);
    lcd_put_num(c122);
    lcd_put_num(e122);
    lcd_put_num(i122);
    lcd_put_num(k122);
    lcd_put_num(l122);
}

 
Hai,I'm using PIC18F4520 to measure the speed of the motor in project.The above code is used to measure the speed of teh motor.While running the above there is no value displayed.It showing only 0(zero) in display..
 
An NPN type inductive proximity sensor is used and GND from the proximity switch is given to CCP1 with 4.7K pullup resistor.
How to solve this issue..?
 
Already I created an same topic,but sorry to create new one.If I tried to write in that topic means,it always showing try again error.
post edited by john_ive - 2019/09/20 22:21:03
#1

39 Replies Related Threads

    ric
    Super Member
    • Total Posts : 24633
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: RPM Measuring 2019/09/20 23:48:41 (permalink)
    0
    Not your immediate problem, but do NOT set CCP1IE.
    You only get away with it because you don't set GIE, otherwise your code would crash.
    Many people wrongly think CCP1IE has to be set to enable CCP1IF. CCP1IF is always active, all CCP1IE does is allow it to generate jumps to the interrupt vector.
     
    Rather then printing the result of all your calculations, display the raw CCPR values you are getting.
    That will show if you're actually getting valid counts. Only when you know that works, start doing calculations on the numbers.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    PStechPaul
    Super Member
    • Total Posts : 2446
    • Reward points : 0
    • Joined: 2006/06/27 16:11:32
    • Location: Cockeysville, MD, USA
    • Status: offline
    Re: RPM Measuring 2019/09/21 00:01:18 (permalink)
    0
    You need to use the debugger to see the value of data1, and data2, and rev_pm. There is not enough information for me to determine what those values might be, and what the actual RPM of the motor is. It seems you are counting clock pulses for one rotation, then getting frequency by 8000000 / signal_period. At 100 RPM, the signal period is 10 mSec, which would be 80,000 counts, and that would be a value of 100. Then you divide by 60 and the result is 1.6667. Then your display routine seems to divide this by 100,000, 10000, 1000, 100, and 10. The results of those divisions will be zero. Also, the CCP register is probably 16 bits, so it will overflow with 80,000 counts.
     
    That should give you enough food for thought to debug your tachometer. I am not able (or willing) to do that for you.

     
    #3
    pcbbc
    Super Member
    • Total Posts : 1388
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/21 02:56:30 (permalink)
    +2 (2)
    Another potential problem once you get all the other issues sorted...

    You do not reset PIR1bits.CCP1IF = 0 BEFORE the first while loop, only AFTER the second one.
    Not necessarily a problem, except you reset TMR1 at the end of the main while loop after a lot of expensive processing.

    Let’s say there is a capture event while you are calculating and displaying your RPM value. That’s actually quite likely as that whole process will take some time to execute. When that happens the current TMR1 value is saved to CCPR1 and CCP1IF is set.
    Then you reset TMR1 to zero, and loop back around the main while. At which point the wait for CCP1IF immediately exits (already set previous to resetting TMR1) and you read CCPR1. But this will NOT be the time elapsed since TMR1 was set to zero, it is the previously captured time.

    Do NOT reset TMR1 in your main loop.
    Declare data1, data2 and signal_period as unsigned 16 bit types (uint16_t).
    The unsigned arithmetic will take care of the timer wrap around.
    Cast the result to uint32_t later if needed.

    It’s quite clear from your choice of sizing of other variables that you have given very little thought to what types are actually necessary. For example display_rpm is using long everywhere when it is only handling display of an int, and for results of calculations that are only single digits (could be char type).

    Correct typing is fundamental to any C programming. Even more so in 8 bit embedded applications.
    #4
    davea
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/23 14:44:14 (permalink)
    +1 (1)
    Why are you making this so hard
    its simple thing to do
    1 get time difference only in CCP1 ISR set a bit or byte when its done
    2 create a circler buffer[16 or 32 or 64] for signal_period  
    3 wait in main for bit or byte to be set then
    clear bit or byte
    add it to the buffer and inc pointer (moving average type)
    wrap pointer at end of buffer
    4 set a time frame that the display can handle (IE: every 150Ms)
    5 do ALL math needed in said time frame 
    6 you only need shift down the buffer total when doing the math
    look at the data in the buffer is it reasonable ?
     
            display_rpm();    you can NOT do this every Rotation !!!!!!
            rev_pm = f_timer / signal_period; nor this
            rev_pm = rev_pm / 60;  or this
          
    #5
    davea
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/23 19:57:11 (permalink)
    0
    Here a bone...

       uint8_t DO_display;
       uint16_t SP_last;
       uint8_t AVG_pointer;
       uint16_t signal_period;
       uint16_t AVG_buffer[16];
       uint32_t AVG_total; // 16 * 65536 = (fits in 24 bits)
       uint16_t AVG_val;
       uint8_t flag;

       while (1) { // TMR1 allways running !!!!
          if (flag != 0) {
             AVG_total -= AVG_buffer[AVG_pointer]; // remove old from buffer and sub from avg
             AVG_buffer[AVG_pointer] = signal_period; // add new to buffer
             AVG_total += signal_period; // add to avg
             ++AVG_pointer;
             AVG_pointer = AVG_pointer & 0x0F; // wrap pointer
             flag = 0;
          }
          // use a timer or CCP2 to set a flag and do math and send to display
          if (DO_display != 0) {
             AVG_val = AVG_total >> 4;
             // do all math and sent to display
             // there will be a min RPM then things will go crazy !
             // IE: counting TIMR1 over flows to fix
             // at Max RPM signal_period should at least 300 or more
             // adjust TMR1 as need (MUST be free running 0 to 65535)
             DO_display = 0;
          }

       } // its not perfect you may have to move AVG stuff into CCP1
    } // and disable its ISR, read "AVG_total" and then re-enable it
    // the AVG will stall when doing math and sending to displav
    // but it realy dont matter as the Buffer should have recycled before
    // the next display period

    void CCP1_CaptureISR(void) {
       uint16_t temp;
       uint8_t CCPr1L = CCPR1L; // read order, low byte then hi byte
       uint8_t CCPr1H = CCPR1H;
       temp = (CCPr1H << 8) | CCPr1L; // FASTEST way
       signal_period = temp - SP_last;
       SP_last = temp; // new last
       Flag++; // new data ready
       //CCP1_PERIOD_REG_T module;
       // Clear the CCP1 interrupt flag
       PIR6bits.CCP1IF = 0;
    }

    post edited by davea - 2019/09/23 19:59:25
    #6
    pcbbc
    Super Member
    • Total Posts : 1388
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/24 00:48:06 (permalink)
    0
    Disable interrupts when reading from the multibyte variable signal_period:
    AVG_buffer[AVG_pointer] = signal_period;

    Otherwise you may read one byte, receive an interrupt, the value is updated, and then read the next byte but of a different value.

    As davea suggests, moving the averaging code to the ISR may be a better option as you will then always have the rolling average of the last 16 readings, even if readings occur faster than you can execute the main loop to process them.
    #7
    davea
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/24 09:24:19 (permalink)
    0
     
    pcbbc
    Disable interrupts when reading from the multibyte variable signal_period:
    AVG_buffer[AVG_pointer] = signal_period;

    please don't confuse the OP
    AVG_total  is the multibyte you want to use
     
    post edited by davea - 2019/09/24 09:26:20
    #8
    pcbbc
    Super Member
    • Total Posts : 1388
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/24 10:19:24 (permalink)
    0
    daveaplease don't confuse the OP
    AVG_total is the multibyte you want to use

    I'm not trying to.  I was referring to the code as you posted (not your suggested modification).  Sorry if that was not clear.
     
    But to that end this entire section needs protecting with a DI/EI sequence (in the code as psoted)...
             AVG_buffer[AVG_pointer] = signal_period; // add new to buffer
             AVG_total += signal_period; // add to avg

    I will admit that I missed the second access of signal_period (adding it to AVG_total) in my first post.
     
    Otherwise there is a risk of reading 2 different signal_period values, or even a half updated value.  Either way it will completely mess with the averaging when that is done in mainline.
     
    I agree, as per your suggestion modification in the code comments, AVG_total would be multibyte that needs protecting when reading in that case.
    #9
    davea
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/24 13:38:31 (permalink)
    0
    yes if it was in the mainline you would have to protect "signal_period"
    and the best way is to (DI) SP_tmp = signal_period; (EI) less time spent in (DI)
     
             AVG_buffer[AVG_pointer] = SP_tmp; // add new to buffer
             AVG_total += SP_tmp; // add to avg
     
    #10
    acharnley
    Super Member
    • Total Posts : 406
    • Reward points : 0
    • Joined: 2016/05/01 06:51:28
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/25 06:32:34 (permalink)
    0
    ric
     
    Many people wrongly think CCP1IE has to be set to enable CCP1IF. CCP1IF is always active, all CCP1IE does is allow it to generate jumps to the interrupt vector.


    This I did not know! Does it apply for all peripherals?
     
    #11
    davea
    Senior Member
    • Total Posts : 158
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/25 07:01:37 (permalink)
    0
    yes. polling 
    and you can also
    do your own software ISR too
          } else if (PIR5bits.CLC1IF) {
             // CLC1IF is used as 100Ms timer (set in CCP1) ---------
     
    #12
    pcbbc
    Super Member
    • Total Posts : 1388
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/25 07:03:58 (permalink)
    0
    acharnleyThis I did not know! Does it apply for all peripherals?

    Yes, all that I know of.  There may be the odd device/peripheral where it does not apply.
     
    Basically it enables you to either poll the device (IE = 0 and check for IF = 1 in mainline) or use interrupts (IE = 1 and check for IE=1 && IF = 1 in ISR).
     
    Also note that this is why the recommended ISR code is:
    if (IE && IF)
    {
        //Service interrupt
        IF = 0; //May not be required for some flags (e.g. UART receive)
    }

     
    Note that your check both IE and IF because IF flag can get set even if IE flag = 0.
    If you do not check both flags then, when IE = 0, your ISR will erroneously service an interrupt for the peripheral on receiving an interrupt for a completely different peripheral.  Trust me, that can lead to some very buggy behaviour!
     
    You can "get away with" checking only IF = 1 in an ISR, but only if you enable interrupts and never subsequently disable them.  In that case the IE = 1 flag check is redundant.
    post edited by pcbbc - 2019/09/25 07:05:16
    #13
    1and0
    Access is Denied
    • Total Posts : 10005
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: RPM Measuring 2019/09/25 08:08:58 (permalink)
    0
    pcbbc
     
     
    You can "get away with" checking only IF = 1 in an ISR, but only if you enable interrupts and never subsequently disable them.  In that case the IE = 1 flag check is redundant.

    ... which is almost always the case, at least in my projects. Once an interrupt is enabled it is rarely needed to be disabled. ;)
     
     
    #14
    pcbbc
    Super Member
    • Total Posts : 1388
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/25 09:18:36 (permalink)
    0
    1and0... which is almost always the case, at least in my projects. Once an interrupt is enabled it is rarely needed to be disabled. ;)

    I agree, and likewise in mine.
     
    However it is worth mentioning, because there are some cases where it is overlooked.  Most commonly with UART transmissions...
     
    TXIF is set when there is no character waiting for transmit in TXREG.  You cannot clear TXIF directly (it is read only).  To clear it you must queue a new byte for transmission.  Therefore it is necessary to disable TXIE once you do not have any more data to send to prevent a continuous interrupt cycle.
     
    But if your ISR is only checking TXIF (and ignoring TXIE), you may erroneously queue a garbage byte for transmission on the next enabled interrupt.  (Although if your tx buffer is correctly implemented it should be empty, so your code should detect that and skip the de-queueing and sending).
    #15
    1and0
    Access is Denied
    • Total Posts : 10005
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: RPM Measuring 2019/09/25 10:26:21 (permalink)
    0
    pcbbc
     
    However it is worth mentioning, because there are some cases where it is overlooked.  Most commonly with UART transmissions...
     

    I found it easier to do UART transmissions by NOT using the interrupt. ;)
     
    #16
    pcbbc
    Super Member
    • Total Posts : 1388
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/25 12:34:41 (permalink)
    +2 (2)
    1and0
    I found it easier to do UART transmissions by NOT using the interrupt. ;) 

    Everything is a lot easier without interrupts.... until you want to multitask!
    I think every other post on here is someone not implementing an ISR correctly.
    But I hear what you are saying.
    #17
    acharnley
    Super Member
    • Total Posts : 406
    • Reward points : 0
    • Joined: 2016/05/01 06:51:28
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/09/26 06:50:56 (permalink)
    0
    pcbbc
    1and0
    I found it easier to do UART transmissions by NOT using the interrupt. ;) 

    Everything is a lot easier without interrupts.... until you want to multitask!
    I think every other post on here is someone not implementing an ISR correctly.
    But I hear what you are saying.



    Assuming you have the speed to poll and don't need to prioritise. I find the PIC16 even at 32MHz is quite slow whenever computations are required and ISR's are essential for more real-time level performance.
    #18
    john_ive
    Super Member
    • Total Posts : 217
    • Reward points : 0
    • Joined: 2017/05/22 22:22:08
    • Location: 0
    • Status: offline
    Re: RPM Measuring 2019/10/12 21:43:14 (permalink)
    0
    Thanks for everyones support,
    Now I got the result.
     
    This code is used to measure the RPM of an motor,everything is working fine,when the motor is operated with full speed it working fine,we can measure required rpm of 665RPM,
    But when the motor is operated at low speed of 500rpm,at starting it showing the 700rpm,even the machine is running at 500RPM,at this time if the controller is reset by RESET switch means,it starting show the 500RPM,
     
    I dono whats the problem was...
     

     
      TRISCbits.TRISC2 = 1; //configure as input pin
        CCP1CON = 0b0101; //Capture on every rising edge
        CCPR1 = 0x00; /* Clear CCPR1 register for counting*/
        T1CON = 0x31; //1:8 prescaler & timer1 ON
        TMR1IE = 1; //Enables the TMR1 overflow interrupt
     


     
    void __interrupt() isr() {
        unsigned int ccp_now;
        unsigned int ccp_prev;

        if (TMR2IF == 1) {
       TMR2IF = 0;
        }
     
        if (CCP1IF == 1) {
            ccp_now = (CCPR1H << 8) + CCPR1L;
        }
        if (check_ccp == 0) {
            ccp_diff = ccp_now - ccp_prev;
            ccp_prev = ccp_now;
            check_ccp = 1;
        }
        CCP1IF = 0;
    }
     


     
    if (check_ccp == 1) {
            rp1 = ccp_diff;
            rp2 = (int) (60000.0 / (0.008 * ccp_diff));
            rpm = (float) rp2 / 12.0;


            a122 = rpm / 100000;
            b122 = rpm % 100000;

            c122 = b122 / 10000;
            d122 = b122 % 10000;

            e122 = d122 / 1000;
            f122 = d122 % 1000;

            i122 = f122 / 100;
            j122 = f122 % 100;

            k122 = j122 / 10;
            l122 = j122 % 10;

            lcd_goto(1, 10);
            lcd_puts("RPM:");
            lcd_put_num(a122);
            lcd_put_num(c122);
            lcd_put_num(e122);
            lcd_put_num(i122);
            lcd_put_num(k122);
            lcd_put_num(l122);
            check_rpm = 0;
        }
     

     
     
    post edited by john_ive - 2019/10/12 21:45:10
    #19
    ric
    Super Member
    • Total Posts : 24633
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: RPM Measuring 2019/10/12 22:40:40 (permalink)
    0
    You have two separate interrupt sources.
    CCP1IF and TMR2IF
    Right now, you are not using TMR2IF for anything useful.
     
    However, as you have multiple sources, this:
        if (CCP1IF == 1) {
            ccp_now = (CCPR1H << 8) + CCPR1L;
        }
        if (check_ccp == 0) {
            ccp_diff = ccp_now - ccp_prev;
            ccp_prev = ccp_now;
            check_ccp = 1;
        }

    should be:
        if (CCP1IF == 1) {
            ccp_now = (CCPR1H << 8) + CCPR1L;
           if (check_ccp == 0) {
                ccp_diff = ccp_now - ccp_prev;
                ccp_prev = ccp_now;
                check_ccp = 1;
            }
     
        }

     
    Edit: Also note the comment in the following post about the location of the "CCP1IF=0;" line.
     
    post edited by ric - 2019/10/13 01:02:03

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2019 APG vNext Commercial Version 4.5