Fordulatszámmérő

Fordulatszámmérő

tachometer.pdf


Tachometer Algorithm
Do you want to build a tachometer? Here is the algorithm showing how it basically works.
In English! Click HERE for the English version.

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

; Tachometer algorithm / Algoritmo de tacometro
; www.josepino.com
; created: October 3, 2003
; Last version: April 22, 2005
; Intended for 16F628 - 10 Mhz

variable byte cero at 0x46 ; zero
variable byte uno at 0x47 ; one
variable byte dos at 0x48 ; two
variable byte tres at 0x49 ; three
variable byte cuatro at 0x4A ; four
variable byte cinco at 0x4B ; five
variable byte seis at 0x4C ; six
variable byte siete at 0x4D ; seven
variable byte ocho at 0x4E ; eight
variable byte nueve at 0x4F ; nine
variable byte blanco ; blank

delay 100ms
disable comparators ; 628 tiene comparadores

port B = all output
port A = all output
pin a4 = input ; used to detect display type / Tipo de display
pin a5 = input ; input pulses / Pulsos de entrada

if a4 then
blanco = 0b_1111_1111 ; If display is Common cathode,
cero = 0b_1100_0000 ; define the numbers for common
uno = 0b_1111_1001 ; cathode
dos = 0b_1010_0100
tres = 0b_1011_0000
cuatro = 0b_1001_1001 ; define los numeros
cinco = 0b_1001_0010 ; cuando sean para
seis = 0b_1000_0010 ; catodo comun
siete = 0b_1101_1000
ocho = 0b_1000_0000
nueve = 0b_1001_0000
else
blanco = 0b_0000_0000 ; Define the numbers for common
cero = 0b_0011_1111 ; anode
uno = 0b_0000_0110
dos = 0b_0101_1011
tres = 0b_0100_1111 ; define los numeros para
cuatro = 0b_0110_0110 ; el display de anodo comun
cinco = 0b_0110_1101
seis = 0b_0111_1101
siete = 0b_0010_0111
ocho = 0b_0111_1111
nueve = 0b_0110_1111
end if

; A routine test HERE
; Se recomienda una rutina de TEST aqui.

; Define sample rate, display every 500 ms
; Define cada cuando calcula las RPM
variable byte bres_hi = 0x09 ; hi byte of our 24bit variable
variable byte bres_mid = 0x89 ; mid byte
variable byte bres_lo = 0x68 ; lo byte

variable byte bandera = 0 ; a flag
variable byte bandera1 = 0 ; another "flag"
variable byte temporal ; temporary variable
variable byte contador = 0 ; Counter
variable byte decenas = 0 ; 10's
variable byte centenas = 0 ; 100'a
variable byte datad = 0 ; Auxiliary variariable
variable byte datac = 0 ; Auxiliary var.

; Here is the interruption based on Roman Black's code.
; Every 500ms gets the RPM and displays it.
; Esta es la rutina de interrupcion que se genera cada 500ms
; esta basado en el codigo hecho por Roman Black
; for more info: www.romanblack.com/one_sec.htm

procedure interrupcion is ; Assembler code
tstf bres_mid ; first test for mid==0
skpnz ; nz = no underflow needed
decf bres_hi,f ; z, so is underflow, so dec the msb
decfsz bres_mid,f ; dec the mid byte (subtract 256)
goto int_exit ; nz, so definitely not one second yet.
tstf bres_hi ; test hi for zero too
skpz ; z = both hi and mid are zero, is one second!
goto int_exit ; nz, so not one second yet.
movlw alto ; get msb value
movwf bres_hi ; load in msb
movlw medio ; get mid value
movwf bres_mid ; load in mid
movlw bajo ; lsb value to add
addwf bres_lo,f ; add it to the remainder already in lsb
skpnc ; nc = no overflow, so mid is still ok
incf bres_mid,f ; c, so lsb overflowed, so inc mid
movlw 0x01
movwf bandera ; 500ms ? then activate a flag
int_exit:
BCF INTCON,2 ; reset the tmr0 interrupt flag
end assembler
end procedure

select bank 1 ; Necesario para interrupciones
option register = 0b_1000_0000 ; Enable interrupts
intcon gie bit = on
intcon t0ie bit = on
select bank 0

; Here is the main program / Aqui comienza el programa principal

Loop ; main Loop / Ciclo infinito
if ! pin a5 then ; Pulse? / Recibio un pulso?
if bandera1 = 1 then ; This calculation is not done? Calculate RPM
bandera1 = 0 ; Si no se ha calculado las RPM, Calcula RPM
decenas = decenas + 20
centenas = centenas + 1
if decenas > 99 then
centenas = centenas + 1
decenas = decenas - 100
end if
end if
else
bandera1 = 1
end if

if bandera = 1 then ; 500ms already? clear all counters
bandera = 0 ; Ya son 500ms? Regresa a cero los contadores
datad = decenas
datac = centenas
centenas = 0
decenas = 0
end if

temporal = datac / 10 ; calculate UNITS / Calcula unidades
FSR = temporal + 0x46 ; get the mem address of variable / Obtiene direccion de la variable
temporal = INDF ; gets the character / obtiene el caracter a desplegar
if temporal = cero then ; Zero? then BLANK / Cero? entonces no despliega nada
temporal = blanco
end if
if pin a4 then ; check the display type and activate the digit
port a = 0b_0000_0001 ; verifica el tipo de display y activa el digito
else
port a = 0b_1111_1110
end if
port b = temporal ; display 1000's / Despliega los millares
delay 5microseconds
port b = blanco

if datac = 0 then ; 100's are cero? blank.
temporal = blanco ; Si las centenas es cero, deja en blanco
else
temporal = datac % 10 ; calculate 100's and get the value to display
FSR = temporal + 0x46 ; calcula centenas y obtiene el valor a desplegar
temporal = INDF
end if
if pin a4 then ; get display type and activate the digit
port a = 0b_0000_0010 ; obtiene el tipo de display y activa el digito
else
port a = 0b_1111_1101
end if
port b = temporal ; display 100's / Despliega centenas
delay 5 microseconds
port b = blanco

temporal = datad / 10 ; Same as previous for 10's
FSR = temporal + 0x46 ; igual que el anterior pero para decenas
temporal = INDF
if datac = 0 then
if temporal = cero then
temporal = blanco
end if
end if
if pin a4 then
port a = 0b_0000_0100
else
port a = 0b_1111_1011
end if
port b = temporal ; Display 10's / despliega decenas
delay 5 microseconds
port b = blanco

temporal = datad % 10 ; Same as previous for 1's
FSR = temporal + 0x46 ; Igual al anterior para unidades
temporal = INDF
if pin a4 then
port a = 0b_0000_1000
else
port a = 0b_1111_0111
end if
port b = temporal
delay 5 microseconds ; Display 1's / despliega unidades
port b = blanco

end loop ; Main loop / Ciclo principal

MINDEN VÉLEMÉNY SZÁMÍT!