Have you thought of doing it a slightly different way? Most sensors have some jitter, so averaging out several samples gives a better result. Also, the duty cycle often isn't constant. To be really accurate, you have to take width of a positive half-cycle and add it to the width of a negative-half cyle.
I had enormous problems measuring the speeds of small fans using PULSIN. In order to get a stable, accurate result I had to average so many samples together the routine was taking too long.
Below is an ISR written in assembly that does the job perfectly.
It is run on a timer interrupt, so you can use any pin. The interrupt period is adjusted to be less than the period of the smallest half-cycle you need to measure.
In the example below, it is 1mSec. TPE is a flag that gets set after a certain number of interrrupts (1000 in this case), so it will measure over 1 second.
To use it, you clear Fanclock and Fan1Counter and TPE
Your main loop checks for TPE being set. If it is, it transfers the contents of Fan1Counter to another variable (call it SPEED), clears FanClock, Fan1Counter and TPE.
Now the variable SPEED always has the number of transitions (twice the pulse rate). It runs totally in the background. The rest of your program really doesn't need to know your timer exists. All it has to do is read SPEED and clear the variables.
Since you are getting ~4K pulses / mile, you will get a little less than 1 pulse per foot of travel. 60MPH = 88 ft/sec. So you could count for a little less than 1/2 second (change 3E8 to something a little smaller than 1F4) and you will get an answer in MPH. No fancy math required.
Code:ReadTach movlw 0xEC ; Reload TMR0 with 65535 - 10000 movwf TMR0H movlw 0x7E movwf TMR0L bcf INTCON,2 ; Clear the TIMER0 interrupt flag btfss TPE,0 bra CheckFans bra DoneForNow CheckFans infsnz FanClock incf FanClock + 1 movlw 0x03 - 1 ; 1000 = 0x3E8, but must have one less cpfsgt FanClock + 1 ; to compare with greater than bra FanRoutine movlw 0xE8 - 1 ; Again, subtract one cpfsgt FanClock bra FanRoutine bsf TPE,0 clrf FanClock clrf FanClock + 1 bra DoneForNow FanRoutine movf PORTB,0,0 movwf Temp,0 xorwf OldPortB,0,0 ' XOR current with old to detect change movwf changedB,0 movff Temp,OldPortB Fan1 btfss changedB,0 ' Fan is connected to PortB.0 bra DoneForNow infsnz Fan1Counter incf Fan1Counter+1 ; increment the counter DoneForNow INT_RETURN




Bookmarks