News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

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.