Tabla de contenido:

Contador de frecuencia de alta resolución: 5 pasos (con imágenes)
Contador de frecuencia de alta resolución: 5 pasos (con imágenes)

Video: Contador de frecuencia de alta resolución: 5 pasos (con imágenes)

Video: Contador de frecuencia de alta resolución: 5 pasos (con imágenes)
Video: Dato Curioso De La Electricidad ⚡️ 2024, Mes de julio
Anonim

Este instructable muestra un contador de frecuencia recíproco capaz de medir frecuencias rápidamente y con una precisión razonable. Está hecho con componentes estándar y se puede hacer en un fin de semana (me tomó un poco más de tiempo:-))

EDITAR: El código ahora está disponible en GitLab:

gitlab.com/WilkoL/high-resolution-frequency-counter

Paso 1: conteo de frecuencias de la vieja escuela

Conteo de frecuencia de la vieja escuela
Conteo de frecuencia de la vieja escuela
Conteo de frecuencia de la vieja escuela
Conteo de frecuencia de la vieja escuela

La forma tradicional de medir la frecuencia de una señal es usar una puerta Y lógica, alimentar la señal que se va a medir en un puerto y una señal con un tiempo máximo de exactamente 1 segundo al otro puerto y contar la salida. Esto funciona bastante bien para señales de unos pocos kHz dentro de los GHz. Pero, ¿y si desea medir una señal de baja frecuencia con buena resolución? Digamos que quiere medir la frecuencia de la red (aquí 50 Hz). Con el método de la vieja escuela, verá un 50 constante en su pantalla si tiene suerte, pero es más probable que vea que la pantalla cambia de 49 a 50 o de 50 a 51. La resolución es de 1 Hz, y eso es todo. Nunca verá 50,002 Hz a menos que esté dispuesto a aumentar el tiempo de la puerta a 1000 segundos. ¡Eso es más de 16 minutos, para una sola medición!

Una mejor forma de medir señales de baja frecuencia es medir el período de las mismas. Tomando la red como ejemplo nuevamente, tiene un período de 20 milisegundos. Tome la misma puerta Y lógica, alimente con, digamos, 10 MHz (pulsos de 0.1 us) y su señal en el otro puerto y salgan 200000 pulsos, por lo que el período de tiempo es 20000.0 uS y eso se traduce de nuevo en 50Hz. Cuando mide solo 199650 pulsos, la frecuencia es 50.087 Hz, eso es mucho mejor, y es en solo un segundo de tiempo de medición. Desafortunadamente, esto no funciona bien con frecuencias más altas. Tomemos, por ejemplo, ahora queremos medir 40 kHz. Con la misma frecuencia de entrada de 10 MHz como referencia, ahora medimos solo 250 pulsos. Cuando contamos solo 249 pulsos, el cálculo da 40161 Hz y con 251 el resultado es 39840 Hz. Esa no es una resolución aceptable. Por supuesto, aumentar la frecuencia de referencia mejora los resultados, pero hay un límite en lo que puede usar en un microcontrolador.

Paso 2: la forma recíproca

El camino recíproco
El camino recíproco
El camino recíproco
El camino recíproco

Una solución que funciona tanto para frecuencias bajas como altas es un contador de frecuencia recíproco. Intentaré explicar su principio. Comienza con un tiempo de medición de aproximadamente 1 segundo, no tiene que ser muy preciso pero es un tiempo razonable para realizar una medición. Alimente esta señal de 1 Hz en un D-flipflop en la entrada D. Todavía no ocurre nada en la (s) salida (s). Conecte la señal que desea medir a la entrada CLOCK del D-flipflop.

Tan pronto como esta señal pasa de BAJA a ALTA, la salida del flipflop D transfiere el estado de la entrada D a la salida (Q). Esta señal RISING se utiliza para comenzar a contar la señal de entrada, así como una señal de reloj de referencia.

Entonces, está contando DOS señales exactamente al mismo tiempo, la señal que desea medir y un reloj de referencia. Este reloj de referencia debe tener un valor preciso y ser estable, un oscilador de cristal normal está bien. El valor no es muy importante siempre que sea una frecuencia alta y se conozca bien su valor.

Después de un tiempo, digamos unos pocos milisegundos, vuelve a bajar la entrada D del flipflop D. En la siguiente entrada CLOCK, la salida Q sigue el estado de la entrada, pero no sucede nada más porque el microcontrolador está configurado para reaccionar solo a una señal RISING. Luego, una vez finalizado el tiempo de medición (aprox. 1 segundo), hace que la entrada D sea ALTA.

De nuevo, en la siguiente entrada de RELOJ, sigue la salida Q y esta señal ASCENDENTE activa el microcontrolador, esta vez para finalizar el conteo de ambos contadores.

El resultado son dos números. El primer número es el número de pulsos contados a partir de la referencia. Como conocemos la frecuencia de referencia, también sabemos el tiempo que tomó contar esos pulsos.

El segundo, el número es el número de pulsos de la señal de entrada que estamos midiendo. Como comenzamos exactamente en los bordes ASCENDENTES de esta señal, tenemos mucha confianza en el número de pulsos de esta señal de entrada.

Ahora es solo un cálculo para determinar la frecuencia de la señal de entrada.

Un ejemplo, digamos que tenemos estas señales y queremos medir la entrada f. La referencia es de 10 MHz, generada por un oscilador de cristal de cuarzo. f_input = 31,416 Hz f_reference = 10000000 Hz (10 MHz), el tiempo de medición es de aprox. 1 segundo

En este tiempo contamos 32 pulsos. Ahora, un período de esta señal toma 1 / 31.416 = 31830.9 uS. Entonces, 32 períodos nos tomaron 1.0185892 segundos, que es un poco más de 1 segundo.

En este 1.0186 segundo también habremos contado 10185892 pulsos de la señal de referencia.

Esto nos da la siguiente información: input_count = 32 reference_count = 10185892 f_reference = 10000000 Hz

La fórmula para calcular la frecuencia resultante es la siguiente: freq = (input_count * f_reference) / ref_count

En nuestro ejemplo, eso es: f-input = (32 * 10000000) / 10185892 = 31,416 Hz

Y esto funciona bien tanto para frecuencias bajas como para frecuencias altas, solo cuando la señal de entrada se acerca (o incluso más alta que) a la frecuencia de referencia, es mejor utilizar la forma estándar de medición "cerrada". Pero también podríamos simplemente agregar un divisor de frecuencia a la señal de entrada, ya que este método recíproco tiene la misma resolución para cualquier frecuencia (hasta la referencia nuevamente). Entonces, ya sea que mida 100 kHz directamente o dividido por un divisor externo de 1000x, la resolución es la misma.

Paso 3: hardware y su esquema

Hardware y su esquema
Hardware y su esquema
Hardware y su esquema
Hardware y su esquema

He hecho algunos contadores de frecuencia de este tipo. Hace mucho tiempo hice uno con un ATMEGA328 (el mismo controlador que hay en un Arduino), luego con microcontroladores ARM de ST. Lo último se hizo con un STM32F407 con una frecuencia de 168 MHz. Pero ahora me preguntaba qué pasa si hago lo mismo con uno * mucho * más pequeño. Elegí un ATTINY2313, que tiene solo 2 kbytes de memoria FLASH y 128 bytes de RAM. La pantalla que tengo es una MAX7219 con 8 pantallas de siete segmentos, estas pantallas están disponibles en Ebay por solo 2 euros. Se puede comprar un ATTINY2313 por alrededor de 1,5 euros, el resto de las piezas que utilicé cuestan solo centavos la pieza. La más cara fue probablemente la caja de plástico para proyectos. Más tarde, decidí hacerlo funcionar con una batería de iones de litio, por lo que necesitaba agregar un estabilizador de voltaje (LDO) de 3.3V, un módulo de carga de la batería y la batería en sí. Esto aumenta un poco el precio, pero supongo que se puede construir por menos de 20 euros.

Paso 4: el código

El código
El código
El código
El código

El código fue escrito en C con Atmel (Microchip) Studio 7 y programado en ATTINY2313 usando un OLIMEX AVR_ISP (¿clon?). Abra (main.c) en el archivo zip a continuación si desea seguir la descripción aquí.

INICIALIZACIÓN

Primero, el ATTINY2313 se configuró para usar un cristal externo, ya que el oscilador RC interno no sirve para medir nada. Utilizo un cristal de 10 MHz que sintonizo con la frecuencia correcta de 10000000 Hz con un pequeño condensador variable. La inicialización se encarga de configurar los puertos para las entradas y salidas, configurar los temporizadores y habilitar las interrupciones y la inicialización del MAX7219. TIMER0 está configurado para contar un reloj externo, TIMER1 el reloj interno y también para capturar el valor del contador en el borde ascendente de ICP, proveniente del D-flipflop.

Hablaré del programa principal en último lugar, así que las siguientes son las rutinas de interrupción.

TIMER0_OVF

Como TIMER0 cuenta hasta 255 (8 bits) y luego pasa a 0, necesitamos una interrupción para contar el número de desbordamientos. Eso es todo lo que hace TIMER0_OVF, solo cuente el número de desbordamiento. Posteriormente, este número se combina con el valor del propio contador.

TIMER1_OVF

TIMER1 puede contar hasta 65536 (16 bits), por lo que la interrupción TIMER1_OVF también cuenta el número de desbordamientos. Pero hace más. También disminuye de 152 a 0, lo que toma aproximadamente 1 segundo y luego establece un pin de salida, yendo a la entrada D del flipflop. Y lo último que se hace en esta rutina de interrupción es disminuir el contador de tiempo de espera, pasando de 765 a 0, lo que tarda unos 5 segundos.

TIMER1_CAPT

Esta es la interrupción TIMER1_CAPT que se dispara cada vez que el D-flipflop le envía una señal, en el flanco ascendente de la señal de entrada (como se explicó anteriormente). La lógica de captura se encarga de guardar el valor del contador TIMER1 en el momento de la captura, se guarda al igual que el contador de desbordamiento. Desafortunadamente, TIMER0 no tiene una función de captura de entrada, por lo que aquí se lee su valor actual y su valor actual del contador de desbordamiento. Una variable de mensaje se establece en uno para que el programa principal le diga que se trata de datos nuevos.

Las siguientes son dos funciones para controlar el MAX7219

SPI

Si bien hay una interfaz de serie universal (USI) disponible en el chip, decidí no usarla. La pantalla MAX7219 debe controlarse a través de SPI y eso es posible con la USI. Pero Bitbanging SPI es tan simple que no me tomé el tiempo para hacerlo con el USI.

MAX7219

El protocolo para configurar el MAX7219 también es bastante simple una vez que haya leído el manual del mismo. Necesita un valor de 16 bits para cada dígito que consta de 8 bits para el número de dígito (1 a 8) seguido de 8 bits para el número que necesita mostrar.

PRINCIPAL-PROG

Lo último es explicar el programa principal. Se ejecuta en un bucle infinito (while (1)) pero solo hace algo cuando hay un mensaje (1) de la rutina de interrupción o cuando el contador de tiempo de espera se ha reducido a cero (sin señal de entrada).

Lo primero que debe hacer cuando el mensaje variable se establece en uno, es restablecer el contador de tiempo de espera, después de todo, sabemos que hay una señal presente. El D-flipflop se reinicia para que esté listo para el siguiente disparo que vendrá después del tiempo de medición (espere un segundo).

Los números registrados en la interrupción de captura se suman para dar el recuento de referencia y el recuento de frecuencia de entrada. (tenemos que asegurarnos de que la referencia nunca pueda ser cero, ya que la dividiremos más adelante)

Lo siguiente es el cálculo de la frecuencia real. Seguramente no quiero usar números flotantes en un microcontrolador con solo 2kbytes de flash y solo 128 bytes de ram. Yo uso enteros. Pero las frecuencias pueden ser como 314,159 Hz, con varios decimales. Por lo tanto, multiplico la frecuencia de entrada no solo con la frecuencia de referencia sino también con un multiplicador, y luego agrego un número donde debe ir el punto decimal. Estos números se volverán muy, muy grandes cuando haga eso. P.ej. con una entrada de 500 kHz, una referencia de 10 MHz y un multiplicador de 100, esto da 5 x 10 ^ 14, ¡eso es realmente enorme! No encajarán en un número de 32 bits, así que utilizo números de 64 bits que llegarán hasta 1.8 x 10 ^ 19 (eso funciona bien en un ATTINY2313)

Y lo último que debe hacer es enviar el resultado a la pantalla MAX7219.

El código se compila en unos 1600 bytes, por lo que cabe en la memoria flash de 2048 bytes disponible en ATTINY2313.

Los registros de fusibles deberían leerse así:

EXTENDIDO 0xFF

ALTA 0xDF

BAJA 0xBF

Paso 5: Exactitud y precisión

Exactitud y precisión
Exactitud y precisión
Exactitud y precisión
Exactitud y precisión
Exactitud y precisión
Exactitud y precisión

La exactitud y la precisión son dos bestias distintas. La precisión aquí es de siete dígitos, la precisión real depende del hardware y la calibración. Calibré los 10 MHz (5 MHz en el punto de prueba) con otro contador de frecuencia que tiene un oscilador disciplinado por GPS.

Y funciona bastante bien, la frecuencia más baja que probé es de 0.2 Hz, la más alta de 2 MHz. Es perfecto. Por encima de 2 MHz, el controlador comienza a perder interrupciones, lo que no es realmente sorprendente cuando se sabe que a 2 MHz la señal de entrada TIMER0 genera más de 7800 interrupciones por segundo. Y el ATTINY2313 también tiene que hacer otras cosas, las interrupciones del TIMER1, a otras 150 interrupciones por segundo y, por supuesto, hacer los cálculos, controlando la pantalla y el D-flipflop. Cuando mires el dispositivo real, verás que utilizo solo siete de los ocho dígitos de la pantalla. Hago esto por varias razones.

Primero es que el cálculo de la frecuencia de entrada es una división, casi siempre tendrá un resto, que no ves ya que es una división entera. En segundo lugar, el oscilador de cristal de cuarzo no tiene estabilización de temperatura.

Los condensadores que lo sintonizan a los 10 MHz correctos son cerámicos, muy sensibles a los cambios de temperatura. Luego está el hecho de que TIMER0 no tiene lógica de captura incorporada, y todas las funciones de interrupción toman algún tiempo para hacer su trabajo. De todos modos, creo que siete dígitos es suficiente.

Recomendado: