• AVR Freaks

Hot!RPM Measuring

Page: < 12 Showing page 2 of 2
Author
1and0
Access is Denied
  • Total Posts : 9977
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: RPM Measuring 2019/10/13 00:31:54 (permalink)
+2 (2)
  • TMR1IE is enabled, but it is not handled in your ISR.
  • Local variable "ccp_prev" should be a "static" variable.
  • Also, as Ric said in Post #20, but also include CCP1IF=0 in the block.
  • Calculation of "rp2" and "rpm" can be performed with integer math, instead of floating point math, and your "rp1" variable is not used.
Edit:
  • I assumed "ccp_diff" is a "volatile" variable. Notice it is not atomic.
  • Do use meaningful variable names instead of "a122", "b122", "c122", ... 
  • Your RPM calculation limits "rp2" to 5 digits, so "rpm" can has up to 4 integral digits but it is being factored into 6 digits.?!
post edited by 1and0 - 2019/10/13 01:39:48
#21
john_ive
Super Member
  • Total Posts : 214
  • Reward points : 0
  • Joined: 2017/05/22 22:22:08
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/14 04:35:59 (permalink)
0
#include <xc.h>
#define _XTAL_FREQ 8000000

#include "lcd.h" //For LCD display3

// 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)

int check_ccp;
unsigned int rpm;
unsigned int ccp_diff; //written by ISR, read outside ISR

void fn_display_rpm(void);

void System_init(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;
}

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

    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;
    }
}

void Init_rpm_timer(void) {

    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
    GIE = 1; //Enable Global Interrupt
    PEIE = 1; //Enable the Peripheral Interrupt
}

void main(void) {

    System_init();
    lcd_init();

    Init_rpm_timer();

    lcd_clear();
    lcd_goto(1, 1);
    lcd_puts("Tachometer Test");

    __delay_ms(200);
    __delay_ms(200);
    __delay_ms(200);

    while (1) {
        fn_display_rpm();
    }
}

void fn_display_rpm(void) {

    unsigned long int a122, b122, c122, d122, e122, f122, i122, j122, k122, l122;

    if (check_ccp == 1) {

        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(2, 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);
        check_ccp = 0;
    }
}

This is the full code finally tested for RPM,

rpm = ccp_diff / 60;

If I used like above calculation means the out is 6500
 

rpm = (int) (60000.0 / (0.008 * ccp_diff));

If I used this calculation means the result is 650 only.
 
I tried as much as possible.I dono how to do it.
So please help to solve this project.
#22
ric
Super Member
  • Total Posts : 24540
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: RPM Measuring 2019/10/14 05:06:49 (permalink)
+1 (1)
You are enabling the wrong interrupt.
The only interrupt you have enabled is for TMR1, but the only interrupt you are checking for is CCP1.
You need to UNDERSTAND what you are doing, and why. Not just fiddle with things until they hopefully work.
 

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!
#23
1and0
Access is Denied
  • Total Posts : 9977
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: RPM Measuring 2019/10/14 07:46:37 (permalink)
+1 (1)
john_ive
This is the full code finally tested for RPM,

rpm = ccp_diff / 60;

If I used like above calculation means the out is 6500

IMPOSSIBLE!!! The maximum value of "ccp_diff" (unsigned int) is 65535, so dividing any unsigned int values by 60 will NOT give you 6500.
 
john_ive

rpm = (int) (60000.0 / (0.008 * ccp_diff));

If I used this calculation means the result is 650 only.

That means "ccp_diff" equal to 11538. Again, why are you using floating point math? Why cast the result to a SIGNED value?
 
john_ive
I tried as much as possible.I dono how to do it.
 

As Ric said, "you need to UNDERSTAND what you are doing."
#24
pcbbc
Super Member
  • Total Posts : 1381
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/14 08:22:51 (permalink)
+1 (1)
1and0
As Ric said, "you need to UNDERSTAND what you are doing."

See post #4:
Me
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.

#25
1and0
Access is Denied
  • Total Posts : 9977
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: RPM Measuring 2019/10/14 09:21:35 (permalink)
0
pcbbc
See post #4:
Me
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.


Indeed!
#26
1and0
Access is Denied
  • Total Posts : 9977
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: RPM Measuring 2019/10/14 09:23:52 (permalink)
+1 (1)
john_ive
#include <xc.h>
#define _XTAL_FREQ 8000000

#include "lcd.h" //For LCD display3

// 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)

int check_ccp;
unsigned int rpm;
unsigned int ccp_diff; //written by ISR, read outside ISR

void fn_display_rpm(void);

void System_init(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;
}

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

    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;
    }
}

void Init_rpm_timer(void) {

    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
    GIE = 1; //Enable Global Interrupt
    PEIE = 1; //Enable the Peripheral Interrupt
}

void main(void) {

    System_init();
    lcd_init();

    Init_rpm_timer();

    lcd_clear();
    lcd_goto(1, 1);
    lcd_puts("Tachometer Test");

    __delay_ms(200);
    __delay_ms(200);
    __delay_ms(200);

    while (1) {
        fn_display_rpm();
    }
}

void fn_display_rpm(void) {

    unsigned long int a122, b122, c122, d122, e122, f122, i122, j122, k122, l122;

    if (check_ccp == 1) {

        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(2, 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);
        check_ccp = 0;
    }
}

This is the full code finally tested for RPM,

Looking closely, I don't see where "rpm" is calculated.!?
 
#27
pcbbc
Super Member
  • Total Posts : 1381
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/15 04:05:46 (permalink)
+1 (1)
1and0
Looking closely, I don't see where "rpm" is calculated.!?

 
Indeed.  Presumably it's calculated by one of the two lines the OP claims to have tested:
 
rpm = ccp_diff / 60;

rpm = (int) (60000.0 / (0.008 * ccp_diff));

But where the OP chose to place that line is anyone's guess.
#28
davea
Senior Member
  • Total Posts : 158
  • Reward points : 0
  • Joined: 2016/01/28 13:12:13
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/15 11:01:57 (permalink)
0

if max is 650rpm then period of TMR1 should be set using a prescaler to
APX  1S overflow (65536), ccp_diff will = apx 63000 at 65RPM
ccp_diff will = apx 6300 at 650RPM

1/6300  = .000158   *  4113920 = 650rpm    (10.8 Hz .092mS)
1/63000 = .0000158  *  4113920 =  65rpm    (1.08 HZ .92S )
I just do not see a way NOT to use floating point math.
Im not saying the math is 100%
but its close
scaling is important for min / max RPM
shorten TMR1 to extend the range then you will have to count TMR1OV at the low end
I would like some insight into this allso
#29
1and0
Access is Denied
  • Total Posts : 9977
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: RPM Measuring 2019/10/15 11:10:58 (permalink)
0
davea
I just do not see a way NOT to use floating point math.

For OP's equation:
 

(60000.0 / (0.008 * ccp_diff)) = 7500000uL / ccp_diff
#30
john_ive
Super Member
  • Total Posts : 214
  • Reward points : 0
  • Joined: 2017/05/22 22:22:08
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/16 05:55:15 (permalink)
0
Actually my requirement is have to read the RPM from 4 to 9999.By refer,with some articles on internet started this project.I got some basic details only from there.
My doubts are
1.By setting the timer and ccp,how the values are generated for ccp_now based on inputs in pins..?
2.After getting the values in ccp_now,by which method we have to convert the values into rpm...
#31
pcbbc
Super Member
  • Total Posts : 1381
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/16 08:21:01 (permalink)
+3 (3)
Ignore ccp_now.  The only value of any use for calculating the actual RPM is ccp_diff.
 
ccp_diff gives you the number of TIMER1 ticks between edges of your signal.  Presumably an edge represents one complete revolution.
 
Therefore, to calculate RPM, you need to:
 
1. Work out how many TIMER1 ticks there are per minute:
Your _XTAL_FREQ setting indicates your Fosc clock is 8MHz
TIMER1 is clocked a Fosc/4 = 2MHz
Your comments indicate you have set the pre-scaler to 1:8
So final TIMER1 clock is 250KHz, which equals 250k x 60 = 15,000,000 ticks per minute
 
Note that the above calculations are based only on the comments in your code.  It's your responsibility to check these are correct.
 
2. To get RPM divide TIMER1 frequency by the number of TIMER1 ticks you measured per revolution (ccp_diff):
rpm = 15,000,000 / ccp_diff
 
Note that with the TIMER1 running at 250,000 your minimum RPM you can measure (without counting TIMER1 overflows) is:
15,000,000 / 65535 = 228 (rounder down to nearest integer)
 
As you approach lower frequencies, the integer arithmetic reduces accuracy.  You may wish to introduce a fixed decimal point.  For example by using:
rpm = 150,000,000 / ccp_diff
That will give you RPM x 10 and you can insert a decimal point before the last digit to give RPM to 1/10ths of a revolution.
 
If you need to measure lower RPMs you either need to count TIMER1 overflows, or reduce TIMER1 clock frequency.  The pre-scaler is already set to the maximum value of 8, so the only way to do the latter is reduce Fosc.
 
I suggest you get things working as is first (and test with RPM > 228).
post edited by pcbbc - 2019/10/16 08:22:34
#32
john_ive
Super Member
  • Total Posts : 214
  • Reward points : 0
  • Joined: 2017/05/22 22:22:08
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/18 23:08:17 (permalink)
0
advisory: (1510) non-reentrant function "___lodiv" appears in multiple call graphs and has been duplicated by the compiler
 
while compiling the code,this warning is generated...
#33
ric
Super Member
  • Total Posts : 24540
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: RPM Measuring 2019/10/18 23:26:15 (permalink)
+1 (1)
Are you doing a floating point divide inside an interrupt service routine?
 
Note, that is NOT a "warning".
It is an "advisory", telling you about something the compiler is doing to protect your from yourself!
 

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!
#34
john_ive
Super Member
  • Total Posts : 214
  • Reward points : 0
  • Joined: 2017/05/22 22:22:08
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/18 23:56:25 (permalink)
0
ric
Are you doing a floating point divide inside an interrupt service routine?
 
Note, that is NOT a "warning".
It is an "advisory", telling you about something the compiler is doing to protect your from yourself!
 


Yes I tried this "rpm = 15,000,000 / ccp_diff" inside interrupt function
#35
pcbbc
Super Member
  • Total Posts : 1381
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/19 01:50:06 (permalink)
+2 (2)
john_ive
ricAre you doing a floating point divide inside an interrupt service routine? Note, that is NOT a "warning".It is an "advisory", telling you about something the compiler is doing to protect your from yourself! 

Yes I tried this "rpm = 15,000,000 / ccp_diff" inside interrupt function

NEVER do floating point math inside an interrupt routine. Floating point is VERY slow on an 8-bit device with no FP hardware unit.

And you should never do anything slow in an interrupt routine. You will cause latency in processing any future interrupts, and since interrupts can’t be “queued” (beyond having 1 pending interrupt of any one type), eventually you’ll get issues with missed interrupts.

Do ALL your floating point maths in main.

Note: this warning is not there to warn you of the above issue, it’s there as a consequence of you calling a FP routine from BOTH the ISR and main. Had you called it from one of those only you wouldn’t have got the warning, however your code would still be “problematic” had you included FP in your ISR.
#36
1and0
Access is Denied
  • Total Posts : 9977
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: RPM Measuring 2019/10/19 03:06:03 (permalink)
+2 (2)
john_ive
ric
Are you doing a floating point divide inside an interrupt service routine?
 
Note, that is NOT a "warning".
It is an "advisory", telling you about something the compiler is doing to protect your from yourself!

Yes I tried this "rpm = 15,000,000 / ccp_diff" inside interrupt function

This "rpm = 15,000,000 / ccp_diff" is not a valid C statement. Show us your REAL code.
 
In addition to what others said, avoid even integer division inside an interrupt function. Why? Because it is also slow on an 8-bit device; and ISR is supposed to be fast. Besides, you should not even perform this division inside the ISR, when it can be done outside in main. As I understand it, your ISR should only capture the CCP values.
 
Anyway, avoid floating point math (even in main) if you can. Use it only as a last resort.
 
FYI, function is called reentrant if it can be interrupted in the middle of its execution and then safely called again ("re-entered") before its previous invocation completed execution. XC8 does not support reentrant functions, so it creates two copies of the function and "advises" you of it.
#37
pcbbc
Super Member
  • Total Posts : 1381
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/19 04:14:31 (permalink)
+1 (1)
Actually ___lodiv is a long integer divide routine, is t it?
But our advice still stands - as 1and0 says avoid integer division as well!
Best not doing any integer multiplies either, or make all multiplies powers of two if you have to.
#38
1and0
Access is Denied
  • Total Posts : 9977
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: RPM Measuring 2019/10/19 04:33:24 (permalink)
0
pcbbc
Actually ___lodiv is a long integer divide routine, is t it?

That is my guess.  Is there a documentation listing what these internal routines are; such as __aldiv, __awdiv, __lldiv, __lodiv, etc?
#39
pcbbc
Super Member
  • Total Posts : 1381
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: RPM Measuring 2019/10/19 10:46:03 (permalink)
+2 (2)
Just in case the OP is still unclear what to do:
a) Calculate ccp_diff in your ISR as you where doing previously;
b) In your main code, disable interrupts, read ccp_diff into a local temporary variable (don’t do any calculations on it), then re-enable interrupts;
c) Do any calculations, be they integer or float divides, etc, on your temporary variable once interrupts are re-enabled.
#40
Page: < 12 Showing page 2 of 2
Jump to:
© 2019 APG vNext Commercial Version 4.5