thanks for ur help.
I am also interested in what Mr. Wolf mentioned:using PULSEIN with flipflop.would u shed some light on it also.
thanks
thanks for ur help.
I am also interested in what Mr. Wolf mentioned:using PULSEIN with flipflop.would u shed some light on it also.
thanks
In short, what the flip-flop does for you, when measuring frequency, such as in a tachometer application, is it negates the need to measure the duration of the high portion of the period, then switch context and measure the duration of the low portion of the period. The time it takes to switch contexts (jump to another section of code) will be lost, and your measurement will be innacurate.
The flip-flop makes one long pulse, spanning the entire period of the tach signal, so that a single PULSEIN command can accurately measure the duration of the period.
For an explanation of the flip-flop idea go to the following Parallax URL:
http://www.parallax.com/dl/appnt/stamps/bs1appnotes.pdf
Scroll down to the "Practical Pulse Measurements" section.
For the complete blow-by-blow as to how I implemented rotor tachometers on my helicopter go to the following URL:
http://www.basicmicro.com/downloads/docs/RRPM.pdf
I have a PIC reliably reading 10 fan tachometers while it is doing other things. Something to keep in mind is that if your input signal is at all noisy, a simple period measurement may not result in a stable reading, since noise can easily affect a single reading. It is best to take a an average over a period.
My method involves running a timer interrupt with a period shorter than the shortest expected "high" or "low" tachometer time. The interrupt service routine reads the port bits, and XORs them with the last reading of those bits. If the bit has changed, a counter is incremented. There is one counter for each fan to be monitored. The interrupt service routine keeps track of how many times it has run, so after a period of time (say a quarter or a half-second) it stores the individual counts. Simply multiplying the number of counts by a fixed value yields the RPM.
The ISR is written in assembly, but this approach has several advantages:
It doesn't require any external hardware
It averages the counts over a short period, so the readings are stable even in the presence of noise.
It works when the duty cycle is far from 50%.
It runs in the background, so you can process other tasks at the same time.
If you choose this approach, I can send you the code.
Charles Linquist
your saying it counts all 10 inputs while using just one timer? I'd like to see that code! sounds sweet.
OK, here you go.
The interrupt period is 500uSec.
All transitions in .5 seconds are added, since FanClock has a count value
of 1000. 500E-9 X 1000 = .5 seconds.
'------------------ Timer 0 interrupt handler-----------------------------------
Asm
ReadTachs
movlw 0xEC ; Reload TMR0
movwf TMR0H
movlw 0x7E
movwf TMR0L
bcf INTCON,2 ; Clear the TIMER0 interrupt flag
infsnz MasterClock
incf MasterClock + 1 ; 16 bit Master system clock
btfss TPE,0 ; Fan counter active gate
bra CheckFans
bra DoneForNow
CheckFans
infsnz FanClock
incf FanClock + 1 ; 16 bit loop counter
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 ; Set the bit if completed 1000 loops
clrf FanClock
clrf FanClock + 1
bra DoneForNow
FanRoutine
movf PORTB,0,0 ; Read the port bits all at once
movwf Temp,0 ; Copy port into temp register
xorwf OldPortB,0,0 ; XOR bits to see which ones have changed
movwf changedB,0 ; Bits of changed ports will be set to "1"
movff Temp,OldPortB ; Save the register for next pass
movf PORTC,0,0
movwf Temp,0
xorwf OldPortC,0,0
movwf changedC,0
movff Temp,OldPortC
movf PORTD,0,0
movwf Temp,0
xorwf OldPortD,0,0
movwf changedD,0
movff Temp,OldPortD
Fan1
btfss changedB,0
bra Fan2
infsnz Fan1Counter
incf Fan1Counter+1
Fan2
btfss changedB,1
bra Fan3
infsnz Fan2Counter
incf Fan2Counter+1
Fan3
btfss changedB,2
bra Fan4
infsnz Fan3Counter
incf Fan3Counter+1
Fan4
btfss changedB,3
bra Fan5
infsnz Fan4Counter
incf Fan4Counter+1
Fan5
btfss changedB,4
bra Fan6
infsnz Fan5Counter
incf Fan5Counter+1
Fan6
btfss changedB,5
bra Fan7
infsnz Fan6Counter
incf Fan6Counter+1
Fan7
btfss changedC,0
bra Fan8
infsnz Fan7Counter
incf Fan7Counter+1
Fan8
btfss changedC,1
bra Fan9
infsnz Fan8Counter
incf Fan8Counter+1
Fan9
btfss changedC,5
bra Fan10
infsnz Fan9Counter
incf Fan9Counter+1
Fan10
btfss changedC,4
bra DoneForNow
infsnz Fan10Counter
incf Fan10Counter+1
DoneForNow
INT_RETURN ; Return from the interrupt
ENDASM
;---------------------- End of Timer 0 Int handler -----------------------------
Charles Linquist
Bookmarks