Autor Tema: Frecuencimetro  (Leído 6377 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado jhordyb3xd

  • PIC10
  • *
  • Mensajes: 7
Frecuencimetro
« en: 19 de Noviembre de 2019, 03:19:38 »
Buenas noches, quisiera saber como cambiar mi programa porque me cuenta hasta 255 el frecuencimetro pero luego cuando intento poner frecuencias mas grandes de 400 o 500, se reinicia por el acarreo, pero no se como hacer para que me salga frecuencias mas altas, si alguien me puede ayudar explicandome, y si vale hacerle mas exacto al frecuecimetro porque me falla por 10Hz aprox.Muchas gracias, adjunto todo lo que he hecho, sería de gran ayuda.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Frecuencimetro
« Respuesta #1 en: 19 de Noviembre de 2019, 06:46:17 »
Por lo que veo es:

Timer0 para contar los pulsos externos y unicamente se muestra cuando pasa de 255 a 0
Timer1 configurado a 250ms para que cuando ocurra 4 veces sea 1 segundo.

Existen 2 formas de "medir la frecuencia"

La primera es la que estas nombrando. Que considero que esta bien, pero si queres ser mas exacto deberias usar realmente las interrupciones y el modulo CCP en Compare con el Timer1, asi no tenes que "recargar" el Timer, sino que se hace automaticamente. Evitando errores.
Tambien considero activar la interrupcion del Timer 0, si ocurre un overflow incrementar otra variable, solo recordar que al momento de que ocurran las 4 entradas del Timer1 (paso el segundo) necesitas poner el Timer0 y la variable esta a 0. Esta variable + el TMR0 van a formar un registro de 16bits, que es el que vas a tener que pasar a BCD, observaras que ahora necesitas un codigo binario -> BCD de 16bits.

Esto te va a exigir que actualices cada 1s tus displays (el numero, no me refiero al barrido), otra forma es la de usar solo 2 entradas o 1 entrada al Timer1, y multiplicarlo por 2 o por 4 respectivamente.

La otra forma que comentaba es un poco mas complicada matematicamente, pero mas simple de implementar usando los modulos. Y es medir el periodo de una señal, Usando el CCP en modo Capture y sus interrupciones, podes obtener la cantidad de tiempo que paso entre cada flanco ascendente, por lo que podrias calcular la frecuencia, lo mas complicado en ASM aca seria hacer el 1/periodo para obtener la frecuencia. De todas formas este tampoco esta excento a tus problemas. Es util para medir frecuencias mas altas y no bajas, si son bajas como las que planteas el problema es que el Timer1 se desbordaria, y la cuenta en realidad es mucho mas grande.

Desconectado jhordyb3xd

  • PIC10
  • *
  • Mensajes: 7
Re:Frecuencimetro
« Respuesta #2 en: 19 de Noviembre de 2019, 09:58:13 »
Si te entiendo amigo, pero ahora más que arreglar la frecuencia, quisiera saber cómo ocupar los 16 bits del timer 1, puesto que utilizo el timer1_L que es de 8 bits pero no sé cómo ocupar el timer1H,para que en el displays me salga más de 255 en los displays, me podrías mostrarme un ejemplo para guiarme porfavor

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Frecuencimetro
« Respuesta #3 en: 19 de Noviembre de 2019, 12:25:16 »
Antes de poder ayudarte con un codigo de ejemplo, necesito que me digas que es lo que haces con los Timers, con que PIN estas leyendo la frecuencia. Asi de esa forma te doy algo que masomenos pueda guiarte o servirte.

Personalmente al programa lo haria asi:

- Timer1 + CCP : Tiempo para contar pulsos
- Timer0 - Entrada externa : Pulsos contados
- Una rutina binario a BCD de 16bits
- Una rutina de muestra en los displays.

Es todo lo necesario para poder realizar el programa que planteas.

Desconectado jhordyb3xd

  • PIC10
  • *
  • Mensajes: 7
Re:Frecuencimetro
« Respuesta #4 en: 19 de Noviembre de 2019, 12:36:59 »
La entrada para la lectura de frecuencia está en el T1CKI, y lo que hago con los timers es hacer conteo de los pulsos de entrada, para hacer un frecuencimetro cada segundo, me estaba guiando por un ejemplo del libro de un contador normal.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Frecuencimetro
« Respuesta #5 en: 19 de Noviembre de 2019, 18:01:18 »
Bueno si es posible consideraría cambiar el pin de entrada al otro timer mejor. Pero voy a seguir tu forma de resolverlo:

Timer 0 - Tiempo
Timer 1 - Frecuencia

Primero necesito una base de tiempo. Es decir 0.5s o 1s. Creo que estas usando un cristal de 4Mhz por lo que veo de los bits de configuracion.
Por lo tanto cada 1 que cuente el timer 0 es de 1us, aplicamos preescaler de 1:256, y esto quiere decir que contaria 1 cada 256us
Con 256 cuentas, es decir el timer comienza de 0 y rebalsa cada 65.536ms, necesito 15.25878906 interrupciones, o 15 completas y una de 66 cuentas. aproximadamente.

Timer 1 con preescaler 1:1, pulsos externos.


Algo asi:

Código: ASM
  1. INCLUDE "P16F877A.INC"
  2.  
  3. ; CONFIG
  4. ; __config 0xFF39
  5.  __CONFIG _FOSC_XT & _WDTE_OFF & _PWRTE_OFF & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _CP_OFF    
  6.    
  7.     CBLOCK 0x20
  8.     NumL
  9.     NumH
  10.     W_TEMP
  11.     STATUS_TEMP
  12.     unidad
  13.     decena
  14.     centena
  15.     contadorinterrup
  16.     ENDC
  17.    
  18.     ORG 0x00
  19.     GOTO    INICIO
  20.     ORG 0x04
  21.     MOVWF   W_TEMP
  22.     SWAPF   STATUS,W
  23.     CLRF    STATUS
  24.     MOVWF   STATUS_TEMP
  25.     CALL    INTERRUPCION
  26.     SWAPF   STATUS_TEMP,W
  27.     MOVWF   STATUS
  28.     SWAPF   W_TEMP,F
  29.     SWAPF   W_TEMP,W
  30.     RETFIE
  31.    
  32. INICIO:    
  33.    
  34.     ; Inicio registros
  35.     CLRF    unidad
  36.     CLRF    decena
  37.     CLRF    centena
  38.     CLRF    NumH
  39.     CLRF    NumL
  40.     MOVLW   .16
  41.     MOVWF   contadorinterrup
  42.     ;Configuro los pines
  43.    
  44.     ; Configuro Timer0
  45.     BANKSEL OPTION_REG
  46.     MOVLW   0x07    ;Preescaler 1:256
  47.     MOVWF   OPTION_REG
  48.     BANKSEL T1CON
  49.  
  50.    
  51.     ;Configuro Timer 1
  52.     BSF     T1CON, TMR1CS
  53.     CLRF    TMR1H
  54.     CLRF    TMR1L
  55.     BSF     T1CON, TMR1ON
  56.    
  57.     CLRF    TMR0
  58.  
  59.     BSF     INTCON, TMR0IE    
  60.     BSF     INTCON, GIE
  61.    
  62. LOOP:
  63.    
  64.     ;CALL    BIN_TO_BCD
  65.     ;CALL    MOSTRAR
  66.     NOP
  67.     GOTO    LOOP
  68.  
  69. INTERRUPCION:
  70.     BCF     INTCON, TMR0IF
  71.     MOVLW   0x02
  72.     XORWF   contadorinterrup, W
  73.     BTFSC   STATUS, Z
  74.     GOTO    CUENTA66
  75.     DECFSZ  contadorinterrup, F
  76.     RETURN
  77.     BCF     T1CON, TMR1ON
  78.     MOVF    TMR1L, W
  79.     MOVWF   NumL
  80.     MOVF    TMR1H, W
  81.     MOVWF   NumH
  82.     CLRF    TMR1H
  83.     CLRF    TMR1L
  84.     MOVLW   .16
  85.     MOVWF   contadorinterrup
  86.     CLRF    TMR0
  87.     BSF     T1CON, TMR1ON
  88.     RETURN
  89.    
  90. CUENTA66:    
  91.     DECF    contadorinterrup, F
  92.     MOVLW   .189        ; 255 - 66
  93.     MOVWF   TMR0
  94.     RETURN
  95.     END


Faltaria:

- Crear la funcion BIN_TO_BCD, que podes obtener de aca:

http://www.piclist.com/techref/microchip/math/radix/b2a-16b3a-ng.htm

Que pasa un numero de 16bits almacenado en NumH y NumL, reemplazar el Hund:Tens:Ones del codigo con las unidad,decena y centena. (Los nombres)

- Crear la funcion que muestra los regisotrs Unidad, Decena y Centena en el display

Fin del problema.

Desconectado jhordyb3xd

  • PIC10
  • *
  • Mensajes: 7
Re:Frecuencimetro
« Respuesta #6 en: 19 de Noviembre de 2019, 20:52:44 »
Disculpa le hice así, puede revisarle si se encuentra bien, los vales a cargar en los displays puse unidad, decena y centena, cuando le pruebo en proteus e ingreso la señal no me muestra nada, creo que falle en algo, con todo seguiré viendo en que estoy fallando

Código: [Seleccionar]
    INCLUDE "P16F877A.INC"
 
; CONFIG
; __config 0xFF39
 __CONFIG _FOSC_XT & _WDTE_OFF & _PWRTE_OFF & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _CP_OFF   
   
 ;%%%%%% Variables para crear retardo
d1 EQU 23H    
d2 EQU 24H
d3 EQU 25H
    CBLOCK 0x20
    NumL
    NumH
    W_TEMP
    STATUS_TEMP
    unidad
    decena
    centena
    contadorinterrup
    ENDC
   
    ORG 0x00
    GOTO    INICIO
    ORG 0x04
    MOVWF   W_TEMP
    SWAPF   STATUS,W
    CLRF    STATUS
    MOVWF   STATUS_TEMP
    CALL    INTERRUPCION
    SWAPF   STATUS_TEMP,W
    MOVWF   STATUS
    SWAPF   W_TEMP,F
    SWAPF   W_TEMP,W
    RETFIE
   
INICIO:   
   
    ; Inicio registros
    CLRF    unidad
    CLRF    decena
    CLRF    centena
    CLRF    NumH
    CLRF    NumL
    MOVLW   .16
    MOVWF   contadorinterrup
    ;Configuro los pines
    bcf STATUS,RP1; Situo en el banco 1
    bsf STATUS,RP0; Situo en el banco 1
;%%%%%%%%
    movlw 0x00
    movwf TRISB; Pines del puerto B como salida
    movwf TRISD; Pines del puerto D como salida
    bcf STATUS,RP0;
    ; Configuro Timer0
    BANKSEL OPTION_REG
    MOVLW   0x07    ;Preescaler 1:256
    MOVWF   OPTION_REG
    BANKSEL T1CON
 
   
    ;Configuro Timer 1
    BSF     T1CON, TMR1CS
    CLRF    TMR1H
    CLRF    TMR1L
    BSF     T1CON, TMR1ON
   
    CLRF    TMR0
 
    BSF     INTCON, TMR0IE   
    BSF     INTCON, GIE
   
LOOP:
   
    CALL    BIN_TO_BCD
    CALL    MOSTRAR
    NOP
    GOTO    LOOP
 
INTERRUPCION:
    BCF     INTCON, TMR0IF
    MOVLW   0x02
    XORWF   contadorinterrup, W
    BTFSC   STATUS, Z
    GOTO    CUENTA66
    DECFSZ  contadorinterrup, F
    RETURN
    BCF     T1CON, TMR1ON
    MOVF    TMR1L, W
    MOVWF   NumL
    MOVF    TMR1H, W
    MOVWF   NumH
    CLRF    TMR1H
    CLRF    TMR1L
    MOVLW   .16
    MOVWF   contadorinterrup
    CLRF    TMR0
    BSF     T1CON, TMR1ON
    RETURN
BIN_TO_BCD:
        movf NumH, w
        addlw d'241'
        addwf NumH, w
        movwf centena      ;b_2 = 2a_2 - 15

        addwf centena, w
        addwf centena, w
        addlw d'253'
        movwf decena
        swapf NumL, w
        andlw 0x0F
        addwf decena, f
        addwf decena, f   ;b_1 = 6a_2 + 2a_1 - 48

        addwf NumH, w
        sublw d'251'
        movwf unidad
        addwf unidad, f
        addwf unidad, f
        addwf unidad, f
        movf NumL, w
        andlw 0x0F
        addwf unidad, f   ;b_0 = a_0 - 4(a_2 + a_1) - 20

        movlw d'10'
bin2dec999a                     ;9 cycles max
        addwf unidad, f
        decf decena, f
        skpc
         goto bin2dec999a

bin2dec999b                     ;6 cycles max
        addwf decena, f
        decf centena, f
        skpc
         goto bin2dec999b

bin2dec999c                     ;3 cycles max
        addwf centena, f
        skpc
         goto bin2dec999c

        return

MOSTRAR:   
movlw 0xff;Limpio el puerto B como es anódo común imprimo 1's en puerto B
movwf PORTB
movlw 0x06;Activo primer display
movwf PORTD
movf unidad,0; Cargo valor de unidades en W
call tabla; Despues con el valor en W llamo a una tabla que retorna en W con la decodificacion 7segmentos
movwf PORTB;     Imprimo valor decodificado en el puerto B
call RETARDO; Mantengo ese valor por 5ms
movlw 0xff; Limpio el puerto de nuevo
movwf PORTB
movlw 0x05; Activo el segundo display
movwf PORTD
movf decena,0; Cargo el valor de decenas en W
call tabla; Llamo a tabla que me retorna con el valor decodificado
movwf PORTB; Imprimo ese valor en el display de decenas
call RETARDO;    Mantengo ese valor 5ms
movlw 0xff; Limpio el puerto
movwf PORTB
movlw 0x03; Activo el display de centenas
movwf PORTD
movf centena,0; Muevo centenas a W
call tabla;      Decodifico el valor de centenas
movwf PORTB; Imprimo ese valor en el display centenas
call RETARDO; Mantengo ese valor 5ms
goto MOSTRAR; Repito en un bucle todo el tiempo
;%%%%%%%%%%%%%%%
tabla
addwf PCL,F; Suma el valor del PCL con el valor de W que venga de unidades, decenas o centenas
retlw b'01000000'; Valor decodificado en 7seg del numero 0
retlw b'01111001'; Valor decodificado en 7seg del numero 1
retlw b'00100100'; Valor decodificado en 7seg del numero 2
retlw b'00110000'; Valor decodificado en 7seg del numero 3
retlw b'00011001'; Valor decodificado en 7seg del numero 4
retlw b'00010010'; Valor decodificado en 7seg del numero 5
retlw b'00000010'; Valor decodificado en 7seg del numero 6
retlw b'01111000'; Valor decodificado en 7seg del numero 7
retlw b'00000000'; Valor decodificado en 7seg del numero 8
retlw b'00010000'; Valor decodificado en 7seg del numero 9


CUENTA66:   
    DECF    contadorinterrup, F
    MOVLW   .189        ; 255 - 66
    MOVWF   TMR0
    RETURN
 RETARDO
 
movlw 0xE7
movwf d1
movlw 0x04
movwf d2
Delay_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_0

;2 cycles
goto $+1
return
    END









Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5878
    • Picuino
Re:Frecuencimetro
« Respuesta #7 en: 20 de Noviembre de 2019, 11:04:52 »
¿Qué rango de frecuencias estás midiendo?

Desconectado jhordyb3xd

  • PIC10
  • *
  • Mensajes: 7
Re:Frecuencimetro
« Respuesta #8 en: 20 de Noviembre de 2019, 11:51:38 »
Entre 0 y 999 Hz

Desconectado elreypic2

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1295
Re:Frecuencimetro
« Respuesta #9 en: 20 de Noviembre de 2019, 11:58:50 »
Al ver tu archivo de simulación estás usando 1MHz, tienes que cambiarlo a 4MHz. Esto en las propiedades del microcontrolador, no el cristal externo que has colocado.

elreypic.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5878
    • Picuino
Re:Frecuencimetro
« Respuesta #10 en: 20 de Noviembre de 2019, 14:09:01 »
Entre 0 y 999 Hz

Es raro que en frecuencias tan bajas tengas un error de 10Hz. Es demasiado alto.


Tienes que conseguir tener una interrupción cada segundo. Por ejemplo acumulando 125 interrupciones con un contador de 125 y un prescaler de 64, que te da exactamente 1.000.000 de ciclos.

PD. Si te pasas del ensamblador al C, sería más sencillo toda la parte de visualización de los números en decimal y yo en particular te podría ayudar más.

Un saludo.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5878
    • Picuino
Re:Frecuencimetro
« Respuesta #11 en: 20 de Noviembre de 2019, 14:55:52 »
El timer2 puede contar 125 con un registro de periodo PR2 y tiene dos prescaler que se pueden ajustar a 1:64.
yo lo veo mejor opción para contar un segundo con interrupciones.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5878
    • Picuino
Re:Frecuencimetro
« Respuesta #12 en: 20 de Noviembre de 2019, 15:07:59 »
Para la conversión a BCD necesitas esta rutina:
http://www.piclist.com/techref/microchip/math/radix/b2bu-10b4d-eag.htm

La anterior no te vale porque convierte a ASCII, no a BCD.

Saludos.
« Última modificación: 20 de Noviembre de 2019, 15:13:30 por Picuino »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Frecuencimetro
« Respuesta #13 en: 20 de Noviembre de 2019, 15:13:36 »
El timer2 puede contar 125 con un registro de periodo PR2 y tiene dos prescaler que se pueden ajustar a 1:64.
yo lo veo mejor opción para contar un segundo con interrupciones.

Es lo que digo, pero el lo tiene realizado con el Timer0, y contando con el Timer1.


Tambien tenes estos:
El codigo lo hace en BCD, de 16 bits a 999, luego si lo necesita en ASCII o lo que sea, le agrega el codigo abajo.
http://www.piclist.com/techref/microchip/math/radix/b2a-16b3a-ng.htm

O este que es 10bit a BCD, ya que con 10bits tiene hasta 1023...
http://www.piclist.com/techref/microchip/math/radix/b2bu-10b3d-mullw-dd.htm
« Última modificación: 20 de Noviembre de 2019, 15:16:18 por KILLERJC »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5878
    • Picuino
Re:Frecuencimetro
« Respuesta #14 en: 20 de Noviembre de 2019, 15:26:36 »
Yo cuando lo he necesitado he utilizado la rutina de 16bit. Así tenía dígitos de sobra si más tarde hacían falta.
La rutina de todas formas ocupa poco y es rápida.