News:

;) This forum is the property of Proton software developers

Main Menu

Reading Rpm signal from 5 tooth gear

Started by Maxi, May 21, 2025, 09:22 AM

Previous topic - Next topic

Maxi

Hello guys, I need some serious help with RPM reading.
I tried a lot, but it doesn't work. I uploaded Proteus and codes as rar, you can take a look.

Normally I have no problem with rpm reading (rpm_OK.bas).
The intervals of the standard rpm signal vary according to the speed, but the pulses of the descending and ascending edge pulses are always equal.

But this time I need to read rpm from a rotating gear with 5 different intervals.
I counted these 5 gears and at the end I tried to read rpm using timer1 interrupt. However, the rpm value on the screen is constantly playing as zero-rpm, zero-rpm.

I'm really missing something but I can't understand what's wrong. I think it should work. I want help from friends who are available.

rpm_OK.bas is working old rpm code.
rpm.bas is new 5 gear for signalling and this is not working.
 
I created a pattern similar to the gear I use in Proteus, you will see it when you open it.

 _RPM.rar

Maxi

#1
I tried to do this,
counting these teeth with irregular intervals and measuring the interval between the time to return to the beginning at the end.
That is, I am interested in the rotation of the gear,
I don't care how many teeth there are.

If this gear rotates 1000 revolutions in 1 minute, I need to measured back 1000/60= 16.6hz



Device 18F26K22
Declare Xtal=16
   
OSCCON.6=1
OSCCON.5=1
OSCCON.4=1

OSCCON.1=1
OSCCON.0=1
   
    TRISC=%00000100

    Declare Optimiser_Level = 0
    Declare All_Digital= true
    Declare FSR_CONTEXT_SAVE = On
    Declare MemWrite_Int_Control = 0
   
    Declare LCD_DTPin PORTB.4
    Declare LCD_RSPin PORTB.0
    Declare LCD_ENPin PORTB.1
    Declare LCD_Interface 4
    Declare LCD_Lines 4
   
    'RPM --------------------
    Dim RPM As Word
    Dim PERIOD As Word
    Dim FREQUENCY As Float
    Dim FREQ As Float
    Dim Ex1 As Byte
    Dim Ex2 As Bit
    '----------------------


'-------------------------------------------------------------
Symbol GIE = INTCON.7 ' Global Interrupt Enable
Symbol PEIE = INTCON.6 'peripheral interrupt enable
'------------CCP1-2 INTERRUPT-------------------
Symbol CCP1IE = PIE1.2 'ccp1 interrupt enable
Symbol CCP1IF = PIR1.2 'ccp1 interrupt flag bit
'--------TIMER1 INTERRUPT-----------------
Symbol TMR1IE = PIE1.0 ' TMR1 OVERFLOW Interrupt Enable
Symbol TMR1IF = PIR1.0 ' TMR1 OVERFLOW INTERRUPT FLAG

Symbol TMR1ON = T1CON.0 'TMR1 ON - OFF
Dim TIMER1 As TMR1L.Word

T1CON=%00110000  '1:8 prescale
CCP1CON=%00000100 'capture every falling edge

While GIE=1 : GIE=0 : Wend         ' make sure to disable the Global interrupt
On_Hardware_Interrupt GoTo Isr              ' If interrupted go to ISR
PEIE = 1  'pherepheral interruptlar a  ld .
CCP1IE = 1
'------------------------------------------------------------------------
GIE=1                              ' Enable Global interrupt ( 0 disable)

Cls
GoTo LOOP1

Isr:'-----------------------
Context Save

If CCP1IF=1 Then
Inc Ex1
If Ex1=5 Then Toggle Ex2
If Ex1=5 Then Ex1=0
EndIf

If Ex2=1 Then
TMR1ON = 1
PERIOD = TIMER1

TIMER1=0
TMR1IF = 0
TMR1IE=1

Else
TMR1ON = 0
TIMER1=0
TMR1IE = 0
EndIf


'----------
CCP1IF = 0
Context Restore


LOOP1:
   
FREQUENCY = 1000.0 / (PERIOD / 4)
If PERIOD=0 Then FREQUENCY=0
FREQUENCY = FREQUENCY * 3750

If TMR1IE= 0 Then
PERIOD = 0
FREQUENCY =0
RPM = 0
Else
RPM = FREQUENCY
EndIf
 
Print At 1,1,"RPM:",Dec RPM,"   "
   
DelayMS 1
GoTo LOOP1



;-------------------------------------------------------------------------------
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings


Config_Start
  FOSC = INTIO67 ;Internal oscillator block
  PLLCFG = OFF ;Oscillator used directly
  PRICLKEN = On ;Primary clock enabled
  FCMEN = OFF ;Fail-Safe Clock Monitor disabled
  IESO = OFF ;Oscillator Switchover mode disabled
  PWRTEN = On ;Power up timer enabled
  BOREN = SBORDIS ;Brown-out Reset enabled in hardware only and disabled in Sleep mode (SBOREN is disabled)
  BORV = 190 ;VBOR set to 2.50 V nominal
  WDTEN = OFF ;Watch dog timer is always disabled. SWDTEN has no effect.
  WDTPS = 32768 ;1:32768
  CCP2MX = PORTC1 ;CCP2 input/output is multiplexed with RC1
  PBADEN = OFF
  CCP3MX = PORTC6 ;P3A/CCP3 input/output is mulitplexed with RC6
  HFOFST = OFF ;HFINTOSC output and ready status are not delayed by the oscillator stable status
  T3CMX = PORTC0 ;T3CKI is on RC0
  P2BMX = PORTC0 ;P2B is on RC0
  MCLRE = INTMCLR ;RE3 input pin enabled; MCLR disabled
  STVREN = OFF ;Stack full/underflow will not cause Reset
  LVP = OFF ;Single-Supply ICSP disabled
  XINST = OFF ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
  Debug = OFF ;Disabled
  Cp0 = On ;Block 0 (000800-001FFFh) code-protected
  CP1 = On ;Block 1 (002000-003FFFh) code-protected
  CP2 = On ;Block 2 (004000-005FFFh) code-protected
  CP3 = On ;Block 3 (006000-007FFFh) code-protected
  CPB = On ;Boot block (000000-0007FFh) code-protected
  CPD = OFF ;Data EEPROM not code-protected
  WRT0 = OFF ;Block 0 (000800-001FFFh) not write-protected
  WRT1 = OFF ;Block 1 (002000-003FFFh) not write-protected
  WRT2 = OFF ;Block 2 (004000-005FFFh) not write-protected
  WRT3 = OFF ;Block 3 (006000-007FFFh) not write-protected
  WRTC = OFF ;Configuration registers (300000-3000FFh) not write-protected
  WRTB = OFF ;Boot Block (000000-0007FFh) not write-protected
  WRTD = OFF ;Data EEPROM not write-protected
  EBTR0 = OFF ;Block 0 (000800-001FFFh) not protected from table reads executed in other blocks
  EBTR1 = OFF ;Block 1 (002000-003FFFh) not protected from table reads executed in other blocks
  EBTR2 = OFF ;Block 2 (004000-005FFFh) not protected from table reads executed in other blocks
  EBTR3 = OFF ;Block 3 (006000-007FFFh) not protected from table reads executed in other blocks
  EBTRB = OFF ;Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
Config_End

;**** End of Fuse Configurator Settings ****
;------------------------------------------------------------------- 
 

   


RGV250

#2
Hi,
I haven't downloaded the files but just a thought. Could you start a timer and count 5 teeth and then stop the timer, the time should be the same irrespective of which tooth it starts on.

Not sure if that is what you meant you have tried?

Bob

Maxi

Quote from: RGV250 on May 21, 2025, 10:31 AMHi,
I haven't downloaded the files but just a thought. Could you start a timer and count 5 teeth and then stop the timer, the time should be the same irrespective of which tooth it starts on.

Not sure if that is what you meant you have tried?

Bob

If the high and low ranges of the incoming signal were equal, we could already read rpm in that way.
But if we directly read 5 low signals in a rotating gear, we see a fluctuating rpm on the screen because the incoming pulse intervals are different.
If only the intervals were equal, then the job was easy.

Wait, let me add the picture of the gear I want to read.
This is the camshaft of an engine, there is a sensor connected to it and I am trying to read the engine speed from there.
There is no std rpm signal in this vehicle (diesel).

camshaft.jpg

RGV250

Hi,
If you count the rising edges and check the elapsed time on the 6th one the duration should always be the same irrespective of which tooth it starts counting from.
Unfortunately I am a bit too busy to try to do some code.
Normally you would have a timebase and count the number of impulses, what I am suggesting is do the same thing but in reverse. Count 6 rising edges, on the 6th stop the timer and calculate the speed etc and then start counting again from the next rising edge.

Bob

Maxi

Quote from: RGV250 on May 21, 2025, 11:10 AMHi,
If you count the rising edges and check the elapsed time on the 6th one the duration should always be the same irrespective of which tooth it starts counting from.
Unfortunately I am a bit too busy to try to do some code.
Normally you would have a timebase and count the number of impulses, what I am suggesting is do the same thing but in reverse. Count 6 rising edges, on the 6th stop the timer and calculate the speed etc and then start counting again from the next rising edge.

Bob

hi, yes, yes, that's exactly what I'm trying to do.
The only difference is that the signal at the sensor output comes inverted, so the teeth come out as low.
I checked it with a scope.

RGV250

Hi,
There has to be a rising edge for it to go low so it should not matter. Alternatively can you use an inverter on the signal?

Bob

Maxi

#7
This is how I measured the output of the sensor.

signal.jpg

edit:
here is proteus screen and my pattern out
pro1.jpg
patt1.jpg

Pepe

#8
fixed program

Maxi

Quote from: Pepe on May 21, 2025, 01:10 PMfixed program

Pepe, thank you very much, can I ask you one more little favour?
When the RPM signal is interrupted, it should write zero on the display, it should continue when it comes back :-[

RGV250

Hi,
QuoteWhen the RPM signal is interrupted, it should write zero on the display,
Looking at the code it is because the count would not reach 5. Can you not use the timer 1 overflow flag and reset period to 0 if it overflows?

Bob

Maxi

Quote from: RGV250 on May 22, 2025, 08:21 AMHi,
QuoteWhen the RPM signal is interrupted, it should write zero on the display,
Looking at the code it is because the count would not reach 5. Can you not use the timer 1 overflow flag and reset period to 0 if it overflows?

Bob
I tried hard,
when ccp1IE=0, I try to reset the rpm and tmr1 numbers, I don't understand, it doesn't work :(

Pepe

#12
Fixed program


Device 18F26K22
Declare Xtal=16
   
OSCCON.6=1
OSCCON.5=1
OSCCON.4=1

OSCCON.1=1
OSCCON.0=1
   
    TRISC=%00000100

    Declare Optimiser_Level = 3
    Declare Create_Coff On
    Declare FSR_CONTEXT_SAVE = On
    Declare MemWrite_Int_Control = 0
   
    Declare LCD_DTPin PORTB.4
    Declare LCD_RSPin PORTB.0
    Declare LCD_ENPin PORTB.1
    Declare LCD_Interface 4
    Declare LCD_Lines 4
   
    'RPM --------------------
    Dim RPM As Word
    Dim PERIOD As Word
    Dim FREQUENCY As Float
    Dim Ex1 As Byte
    Dim PERIOD_OLD As Word
    '----------------------


'-------------------------------------------------------------
Symbol GIE = INTCON.7 ' Global Interrupt Enable
Symbol PEIE = INTCON.6 'peripheral interrupt enable
'------------CCP1-2 INTERRUPT-------------------
Symbol CCP1IE = PIE1.2 'ccp1 interrupt enable
Symbol CCP1IF = PIR1.2 'ccp1 interrupt flag bit
'--------TIMER1 INTERRUPT-----------------
Symbol TMR1IE = PIE1.0 ' TMR1 OVERFLOW Interrupt Enable
Symbol TMR1IF = PIR1.0 ' TMR1 OVERFLOW INTERRUPT FLAG

Symbol TMR1ON = T1CON.0 'TMR1 ON - OFF
Dim TIMER1 As TMR1L.Word

T1CON=%00110000  '1:8 prescale
CCP1CON=%00000100 'capture every falling edge

On_Hardware_Interrupt GoTo Isr              ' If interrupted go to ISR
PEIE = 1  'pherepheral interruptlar a  ld .
CCP1IE = 1
'------------------------------------------------------------------------
TMR1ON = 1
TMR1IE = 1
GIE=1                              ' Enable Global interrupt ( 0 disable)

Cls

Do
If PERIOD_OLD <> PERIOD Then
                             PERIOD_OLD = PERIOD   
                             
                             If PERIOD = 65535 Then
                                                   RPM = 0
                                             Else
                                                   FREQUENCY = 1000.0 / (PERIOD / 4)
                                                   RPM = FREQUENCY * 3750
                             EndIf
                                                   
                             Print At 1,1,"RPM:",Dec RPM,"   "
EndIf                             
Loop

Isr:'-----------------------
Context Save

If CCP1IF=1 Then
                 Inc Ex1
                 If Ex1=5 Then
                               PERIOD = TIMER1
                               TIMER1=0
                               Ex1=0
                 EndIf

                 CCP1IF = 0
EndIf
If TMR1IF = 1 Then
                   TMR1IF = 0
                   PERIOD=65535
EndIf                   
Context Restore


;-------------------------------------------------------------------------------
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings


Config_Start
  FOSC = INTIO67 ;Internal oscillator block
  PLLCFG = OFF ;Oscillator used directly
  PRICLKEN = On ;Primary clock enabled
  FCMEN = OFF ;Fail-Safe Clock Monitor disabled
  IESO = OFF ;Oscillator Switchover mode disabled
  PWRTEN = On ;Power up timer enabled
  BOREN = SBORDIS ;Brown-out Reset enabled in hardware only and disabled in Sleep mode (SBOREN is disabled)
  BORV = 190 ;VBOR set to 2.50 V nominal
  WDTEN = OFF ;Watch dog timer is always disabled. SWDTEN has no effect.
  WDTPS = 32768 ;1:32768
  CCP2MX = PORTC1 ;CCP2 input/output is multiplexed with RC1
  PBADEN = OFF
  CCP3MX = PORTC6 ;P3A/CCP3 input/output is mulitplexed with RC6
  HFOFST = OFF ;HFINTOSC output and ready status are not delayed by the oscillator stable status
  T3CMX = PORTC0 ;T3CKI is on RC0
  P2BMX = PORTC0 ;P2B is on RC0
  MCLRE = INTMCLR ;RE3 input pin enabled; MCLR disabled
  STVREN = OFF ;Stack full/underflow will not cause Reset
  LVP = OFF ;Single-Supply ICSP disabled
  XINST = OFF ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
  Debug = OFF ;Disabled
  Cp0 = On ;Block 0 (000800-001FFFh) code-protected
  CP1 = On ;Block 1 (002000-003FFFh) code-protected
  CP2 = On ;Block 2 (004000-005FFFh) code-protected
  CP3 = On ;Block 3 (006000-007FFFh) code-protected
  CPB = On ;Boot block (000000-0007FFh) code-protected
  CPD = OFF ;Data EEPROM not code-protected
  WRT0 = OFF ;Block 0 (000800-001FFFh) not write-protected
  WRT1 = OFF ;Block 1 (002000-003FFFh) not write-protected
  WRT2 = OFF ;Block 2 (004000-005FFFh) not write-protected
  WRT3 = OFF ;Block 3 (006000-007FFFh) not write-protected
  WRTC = OFF ;Configuration registers (300000-3000FFh) not write-protected
  WRTB = OFF ;Boot Block (000000-0007FFh) not write-protected
  WRTD = OFF ;Data EEPROM not write-protected
  EBTR0 = OFF ;Block 0 (000800-001FFFh) not protected from table reads executed in other blocks
  EBTR1 = OFF ;Block 1 (002000-003FFFh) not protected from table reads executed in other blocks
  EBTR2 = OFF ;Block 2 (004000-005FFFh) not protected from table reads executed in other blocks
  EBTR3 = OFF ;Block 3 (006000-007FFFh) not protected from table reads executed in other blocks
  EBTRB = OFF ;Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
Config_End

;**** End of Fuse Configurator Settings ****
;-------------------------------------------------------------------

Maxi

Pepe, thank you again. You're like a hero.
Bob, thank you for your time and help.

Lavi

Hello to all! I know that this is an old post, but i am trying to understand this code for reading Rpm's, somebody can explain to me, in this line  "RPM = FREQUENCY * 3750" , this value 3750 from where it comes ?

Pepe

#15
FREQUENCY = 1000.0 / (PERIOD / 4)
RPM = FRECUENCIA * 7500           '3750 is wrong

actually the correct value is 7500 and it comes from 30000/4

This is more understandable

FREQUENCY = 1000000 / PERIOD    ' 4x8/16mhz= 2us prescaler=8 xtal=16mhz
RPM = FREQUENCY * 30    '60/2us=30


Lavi

Thank you for quick answer !I did write a code for reading rpm, but i need assistance, i am not sure if its ok....                                     *
 Device = 16F874A

 Config  HS_OSC , WDT_OFF , PWRTE_ON , BODEN_OFF , LVP_OFF , CP_OFF , CPD_OFF , DEBUG_OFF
 Xtal = 4
    TRISC = 0
    PORTC = 0
    TRISD = 0
    PORTD = 0
    TRISE = 0
    PORTE = 0
    TRISB = %00000001
    PORTB = 0
   
 Symbol digit2 = PORTD.5         'input base pnp transistor for 2 Digit
 Symbol digit1 = PORTD.6         'input base pnp transistor for 1 Digit
 Symbol digit3 = PORTD.7         'input base pnp transistor for 3 Digit
 Symbol digit4 = PORTD.4         'input base pnp transistor for 4 Digit
 
 Dim digitdata1 As Byte
 Dim digitdata2 As Byte
 Dim digitdata3 As Byte
 Dim digitdata4 As Byte
 Dim dummy      As Byte
 Dim count      As Byte
 Dim number     As Byte
 Dim index      As Byte
 Dim RPM        As Word
 
 Dim PERIOD     As Word
 Dim FREQUENCY  As Word
 Dim PERIOD_OLD As Word
;============================================================
;Setup Timer1
Symbol GIE  = INTCON.7 ' Global Interrupt Enable Bit
Symbol PEIE = INTCON.6              ' Peripheral Interrupts
Symbol Timer1 = TMR1L.Word ' Addressing  TMR1L and TMR1H with one register
Symbol TMR1IE1 = PIE1.0     ' TMR1 interrupt enable
Symbol TMR1IF1 = PIR1.0     ' TMR1 overflow flag
Symbol Timer1_On = T1CON.0 ' Start,stop TMR1   

 T1CON.1  = 0 ' 0 = Internal clock (FOSC/4)
 T1CON.4  = 1 ' 11 = 1:8 prescale value
 T1CON.5  = 1 '
;=====================================================
'setup timer0
  OPTION_REG.0 = 1       '|001-1:4 1ms
OPTION_REG.1 = 0       '|
OPTION_REG.2 = 0                   '|
        OPTION_REG.3 = 0    ' PRESCALER TO TIMER0
OPTION_REG.5 = 0    ' Internal Clock Source
  TMR0 = 0        ' Clear the TMR0 register
 Symbol TMR0IE   = INTCON.5    ' Enables TMR0 interrupts
 Symbol TMR0IF   = INTCON.2    ' TMR0 overflow flag
'=====================================================
' RBO INT  SETUP
Symbol RB0INTE   = INTCON.4    'Enable Rb0 interrupt
OPTION_REG.6     = 0           'INTEDG = 0 LOW 1 HIGH
Symbol RB0INTF   = INTCON.1    'RB0 Interrupt flag
'=====================================================

  High digit1             ; All DIGITs OFF
  High digit2
  High digit3
  High digit4

 
  On_Interrupt GoTo Int_Sub
 
  TMR1IE1   = 1          'Enable timer 1 int
  Timer1_On = 1          'Start  timer 1 int
  TMR0IE    = 1          'Enable timer 0 int
  RB0INTE   = 1          'Enable RB0 int
  GIE       = 1          'Global interrupt On
 
GoTo Main 


Int_Sub:

Context Save

If RB0INTF=1 Then         ' RB0 INTERRUPT? YES WE HAVE A PULSE 
        PERIOD = Timer1   ' READ TIMER VALUE AND STORE IN PERIOD
         Timer1=0         ' CLEAR TIMER1           
   RB0INTF = 0            ' CLEAR CCP INT FLAG
EndIf

If TMR1IF1 = 1 Then       ' TIMER OVERFLOWED? YES!
   TMR1IF1 = 0            ' CLEAR INTERRUPT FLAG
   PERIOD=65535           ' PRELOAD WITH 65536
EndIf

If  TMR0IF = 1 Then  Inc count   'when timer0 is overflowed
 
 Select count
 Case 1
  High digit4              ;DIGIT4 OFF
  PORTC = digitdata1       ;segment data
  Low digit1               ;DIGIT1 ON
 Case 2
  High digit1              ;DIGIT1 OFF
  PORTC = digitdata2       ;segment data
  Low digit2               ;DIGIT2 ON
 Case 3
  High digit2              ;DIGIT2 OFF
  PORTC = digitdata3       ;segment data
  Low digit3               ;DIGIT3 ON
 Case 4
  High digit3              ;DIGIT3 OFF
  PORTC = digitdata4       ;segment data
  Low digit4               ;DIGIT4 ON
EndSelect

 If count >= 4 Then  count = 0
  TMR0IF = 0                  ;CLEAR TMR0 FLAG 
  OPTION_REG = %001           ;RE-SET  TIMER0 PRESCALER

Context Restore
 

 
Main:

If  PERIOD_OLD <> PERIOD Then       'IF PERIOD_OLD IS GREATER OR SMALLER THEN PERIOD VALUE
    PERIOD_OLD  = PERIOD            'UPDATE PERIOD_OLD VALUE
 If PERIOD      = 65535  Then       'IF PERIOD (TIMER1 OVERFLOWED) 
    RPM = 0                         'CLEAR RPM VALUE
   Else
    FREQUENCY = 1000000 / PERIOD    ' 50hz = 25 high_pulses   1500RpM 4 STROKE ENGINE (2 PULSE PER REV)
    RPM    = FREQUENCY * 3.76
 EndIf
EndIf
DelayMS 100
Display_Rpm_Segments:

For index = 0 To 3      'Convert segment data
 dummy  = Dig RPM,index
 number = LookUpL dummy,[%11000000,%11111001,%10100100,%10110000 ,%10011001,_
 %10010010, %10000010 ,%11111000 ,%10000000 ,%10010000 ]

Select index
Case 0
 digitdata3 = number
Case 1
 digitdata2 = number
Case 2
 digitdata1 = number
Case 3
 digitdata4 = number
EndSelect
 
 Next

 DelayMS 100
GoTo Main ' Loop for ever

Pepe

#17
demo proteus

Device = 16F874A

 Config  HS_OSC , WDT_OFF , PWRTE_ON , BODEN_OFF , LVP_OFF , CP_OFF , CPD_OFF , DEBUG_OFF
 Xtal = 20
Declare Optimiser_Level = 3
Declare Create_Coff On
Declare Watchdog off
 
    TRISC = 0
    PORTC = 0
    TRISD = 0
    PORTD = 0
    TRISE = 0
    PORTE = 0
    TRISB = %00000001
    PORTB = 0
 
 Symbol digit4 = PORTD.4         'input base pnp transistor for 4 Digit 
 Symbol digit2 = PORTD.5         'input base pnp transistor for 2 Digit
 Symbol digit1 = PORTD.6         'input base pnp transistor for 1 Digit
 Symbol digit3 = PORTD.7         'input base pnp transistor for 3 Digit
 
 
 Dim digitdata1 As Byte
 Dim digitdata2 As Byte
 Dim digitdata3 As Byte
 Dim digitdata4 As Byte
 Dim dummy      As Byte
 Dim count      As Byte
 Dim number     As Byte
 Dim index      As Byte
 Dim RPM        As Word
 
 Dim PERIOD     As Word
 
 Dim PERIOD_OLD As Word
;============================================================
;Setup Timer1
Symbol GIE  = INTCON.7                ' Global Interrupt Enable Bit
Symbol PEIE = INTCON.6              ' Peripheral Interrupts               
Symbol Timer1 = TMR1L.Word            ' Addressing  TMR1L and TMR1H with one register
Symbol TMR1IE1 = PIE1.0                ' TMR1 interrupt enable
Symbol TMR1IF1 = PIR1.0                ' TMR1 overflow flag
Symbol Timer1_On = T1CON.0            ' Start,stop TMR1  

 T1CON.1  = 0         ' 0 = Internal clock (FOSC/4)
 T1CON.4  = 1         ' 11 = 1:8 prescale value
 T1CON.5  = 1         '
;=====================================================
'setup timer0
    OPTION_REG.0 = 1           '|101 - 1:64
    OPTION_REG.1 = 0           '|
    OPTION_REG.2 = 1           '|
    OPTION_REG.3 = 0           ' PRESCALER TO TIMER0
    OPTION_REG.5 = 0           ' Internal Clock Source
     TMR0 = 0                      ' Clear the TMR0 register
 Symbol TMR0IE   = INTCON.5       ' Enables TMR0 interrupts
 Symbol TMR0IF   = INTCON.2       ' TMR0 overflow flag
'=====================================================
' RBO INT  SETUP
Symbol RB0INTE   = INTCON.4    'Enable Rb0 interrupt
OPTION_REG.6     = 0           'INTEDG = 0 LOW 1 HIGH
Symbol RB0INTF   = INTCON.1    'RB0 Interrupt flag
'=====================================================

  High digit1             ; All DIGITs OFF
  High digit2
  High digit3
  High digit4

 
  On_Hardware_Interrupt GoTo Int_Sub
 
  TMR1IE1   = 1          'Enable timer 1 int
  Timer1_On = 1          'Start  timer 1 int
  TMR0IE    = 1          'Enable timer 0 int
  RB0INTE   = 1          'Enable RB0 int
  GIE       = 1          'Global interrupt On
 
Do

If  PERIOD_OLD <> PERIOD Then       'IF PERIOD_OLD IS GREATER OR SMALLER THEN PERIOD VALUE
    PERIOD_OLD  = PERIOD            'UPDATE PERIOD_OLD VALUE
 If PERIOD      = 65535  Then       'IF PERIOD (TIMER1 OVERFLOWED)
    RPM = 0                         'CLEAR RPM VALUE
   Else
    RPM = 312500 / PERIOD    ' 50hz = 25 high_pulses   1500RpM 4 STROKE ENGINE (2 PULSE PER REV)
   
 EndIf


For index = 0 To 3      'Convert segment data
 dummy  = Dig RPM,index
 number = LookUpL dummy,[%11000000,%11111001,%10100100,%10110000 ,%10011001,%10010010, %10000010 ,%11111000 ,%10000000 ,%10010000 ]

Select index
Case 0
 digitdata3 = number
Case 1
 digitdata2 = number
Case 2
 digitdata1 = number
Case 3
 digitdata4 = number
EndSelect
 
 Next
EndIf

Loop            ' Loop for ever   
   
Int_Sub:

Context Save

If RB0INTF=1 Then         ' RB0 INTERRUPT? YES WE HAVE A PULSE
         PERIOD = Timer1  ' READ TIMER VALUE AND STORE IN PERIOD
         Timer1=0         ' CLEAR TIMER1          
         RB0INTF = 0      ' CLEAR CCP INT FLAG
EndIf

If TMR1IF1 = 1 Then       ' TIMER OVERFLOWED? YES!
   TMR1IF1 = 0            ' CLEAR INTERRUPT FLAG
   PERIOD=65535           ' PRELOAD WITH 65536
EndIf

If  TMR0IF = 1 Then 

 Select count
 Case 0
  High digit4              ;DIGIT4 OFF
  PORTC = digitdata1       ;segment data
  Low digit1               ;DIGIT1 ON
 Case 1
  High digit1              ;DIGIT1 OFF
  PORTC = digitdata2       ;segment data
  Low digit2               ;DIGIT2 ON
 Case 2
  High digit2              ;DIGIT2 OFF
  PORTC = digitdata3       ;segment data
  Low digit3               ;DIGIT3 ON
 Case 3
  High digit3              ;DIGIT3 OFF
  PORTC = digitdata4       ;segment data
  Low digit4               ;DIGIT4 ON
EndSelect
  Inc count   'when timer0 is overflowed
 
 If count > 3  Then  count = 0
  TMR0IF = 0                  ;CLEAR TMR0 FLAG
 EndIf
Context Restore