Table des matières:

Compteur de fréquence haute résolution : 5 étapes (avec photos)
Compteur de fréquence haute résolution : 5 étapes (avec photos)

Vidéo: Compteur de fréquence haute résolution : 5 étapes (avec photos)

Vidéo: Compteur de fréquence haute résolution : 5 étapes (avec photos)
Vidéo: Messi Compte sa liasse de billet 2024, Novembre
Anonim

Cette instructable montre un compteur de fréquence réciproque capable de mesurer les fréquences rapidement et avec une précision raisonnable. Il est fabriqué avec des composants standard et peut être fabriqué en un week-end (cela m'a pris un peu plus de temps:-))

EDIT: Le code est désormais disponible sur GitLab:

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

Étape 1: Comptage de fréquence à l'ancienne

Comptage de fréquence à l'ancienne
Comptage de fréquence à l'ancienne
Comptage de fréquence à l'ancienne
Comptage de fréquence à l'ancienne

La méthode à l'ancienne pour mesurer la fréquence d'un signal consiste à utiliser une porte logique ET, à envoyer le signal à mesurer dans un port et un signal avec un temps élevé d'exactement 1 seconde vers l'autre port et à compter la sortie. Cela fonctionne assez bien pour des signaux de quelques kHz bien dans le GHz. Mais que faire si vous voulez mesurer un signal basse fréquence avec une bonne résolution ? Supposons que vous vouliez mesurer la fréquence du secteur (ici 50 Hz). Avec la méthode à l'ancienne, vous verrez un 50 constant sur votre écran si vous avez de la chance, mais vous verrez plus probablement l'affichage passer de 49 à 50 ou de 50 à 51. La résolution est de 1 Hz, et c'est tout. Vous ne verrez jamais 50,002 Hz à moins que vous ne vouliez augmenter le temps de porte à 1000 secondes. C'est plus de 16 minutes, pour une seule mesure !

Une meilleure façon de mesurer les signaux basse fréquence est d'en mesurer la période. Prenant à nouveau le secteur comme exemple, a une période de 20 millisecondes. Prenez la même porte logique ET, alimentez-la avec, disons, 10 MHz (0,1 impulsions us) et votre signal sur l'autre port et sortez 200 000 impulsions, donc la période est de 20000,0 uS et cela se traduit en 50 Hz. Lorsque vous ne mesurez que 199650 impulsions, la fréquence est de 50,087 Hz, c'est beaucoup mieux, et le temps de mesure n'est que d'une seconde. Malheureusement, cela ne fonctionne pas bien avec des fréquences plus élevées. Prenons par exemple, nous voulons maintenant mesurer 40 kHz. Avec la même fréquence d'entrée de 10 MHz que la référence, nous ne mesurons plus que 250 impulsions. Lorsque nous ne comptons que 249 impulsions, le calcul donne 40161 Hz et avec 251 le résultat est 39840 Hz. Ce n'est pas une résolution acceptable. Bien sûr, augmenter la fréquence de référence améliore les résultats, mais il y a une limite à ce que vous pouvez utiliser dans un microcontrôleur.

Étape 2: La Voie Réciproque

La Voie Réciproque
La Voie Réciproque
La Voie Réciproque
La Voie Réciproque

Une solution qui fonctionne à la fois pour les basses et les hautes fréquences est un compteur de fréquence réciproque. Je vais essayer d'expliquer son principe. Vous commencez avec un temps de mesure d'environ 1 seconde, il n'a pas besoin d'être très précis mais c'est un temps raisonnable pour une mesure. Introduisez ce signal de 1 Hz dans une bascule D sur l'entrée D. Rien ne se passe encore sur la ou les sorties. Connectez le signal que vous souhaitez mesurer à l'entrée CLOCK de la bascule D.

Dès que ce signal passe de BAS à HAUT, la sortie de la bascule D transfère l'état de l'entrée D à la sortie (Q). Ce signal MONTANT aller est utilisé pour commencer à compter le signal d'entrée ainsi qu'un signal d'horloge de référence.

Vous comptez donc DEUX signaux exactement en même temps, le signal que vous souhaitez mesurer et une horloge de référence. Cette horloge de référence doit avoir une valeur précise et être stable, un oscillateur à cristal normal convient parfaitement. La valeur n'est pas très importante tant qu'il s'agit d'une fréquence élevée et que sa valeur est bien connue.

Après un certain temps, disons quelques millisecondes, vous réduisez à nouveau l'entrée D de la bascule D à l'état bas. A l'entrée CLOCK suivante, la sortie Q suit l'état de l'entrée, mais rien d'autre ne se passe car le microcontrôleur est réglé pour réagir uniquement à un signal RISING. Ensuite, une fois le temps de mesure terminé (environ 1 seconde), vous mettez l'entrée D à HAUT.

De nouveau, à l'entrée CLOCK suivante, la sortie Q suit et ce signal RISING déclenche le microcontrôleur, cette fois pour mettre fin au comptage des deux compteurs.

Le résultat est deux nombres. Le premier nombre est le nombre d'impulsions comptées à partir de la référence. Comme nous connaissons la fréquence de référence, nous connaissons également le temps qu'il a fallu pour compter ces impulsions.

Le deuxième nombre est le nombre d'impulsions du signal d'entrée que nous mesurons. Comme nous avons commencé exactement sur les fronts MONTANTS de ce signal, nous sommes très confiants quant au nombre d'impulsions de ce signal d'entrée.

Maintenant, c'est juste un calcul pour déterminer la fréquence du signal d'entrée.

Un exemple, disons que nous avons ces signaux et que nous voulons mesurer l'entrée f. La référence est de 10 MHz, générée par un oscillateur à quartz. f_input = 31,416 Hz f_reference = 10000000 Hz (10 MHz), le temps de mesure est d'env. 1 seconde

Pendant ce temps, nous avons compté 32 impulsions. Maintenant, une période de ce signal prend 1 / 31,416 = 31830.9 uS. Donc 32 périodes nous ont pris 1,0185892 secondes, ce qui est un peu plus d'1 seconde.

Dans cette 1.0186 seconde nous aurons également compté 10185892 impulsions du signal de référence.

Cela nous donne les informations suivantes: input_count = 32 reference_count = 10185892 f_reference = 10000000 Hz

La formule pour calculer la fréquence résultante est la suivante: freq = (input_count * f_reference) / ref_count

Dans notre exemple, c'est: entrée f = (32 * 10000000) / 10185892 = 31,416 Hz

Et cela fonctionne bien pour les basses fréquences ainsi que pour les hautes fréquences, uniquement lorsque le signal d'entrée se rapproche (ou même plus haut) de la fréquence de référence, il est préférable d'utiliser la méthode de mesure standard "gated". Mais alors nous pourrions aussi simplement ajouter un diviseur de fréquence au signal d'entrée car cette méthode réciproque a la même résolution pour n'importe quelle fréquence (jusqu'à la référence à nouveau). Donc, que vous mesuriez 100 kHz directement ou divisés par un diviseur externe 1000x, la résolution est la même.

Étape 3: Matériel et son schéma

Matériel et son schéma
Matériel et son schéma
Matériel et son schéma
Matériel et son schéma

J'ai fait quelques-uns de ce type de compteurs de fréquence. Il y a longtemps, j'en ai fait un avec un ATMEGA328 (le même contrôleur qu'il y a dans un Arduino), plus tard avec des microcontrôleurs ARM de ST. Le dernier en date a été réalisé avec un STM32F407 cadencé à 168 MHz. Mais maintenant, je me demandais et si je faisais la même chose avec un *beaucoup* plus petit. J'ai choisi un ATTINY2313, qui n'a que 2 Ko de mémoire FLASH et 128 octets de RAM. L'écran que j'ai est un MAX7219 avec 8 écrans à sept segments, ces écrans sont disponibles sur Ebay pour seulement 2 euros. Un ATTINY2313 peut être acheté pour environ 1,5 Euros, le reste des pièces que j'ai utilisées ne coûte que quelques centimes pièce. Le plus cher était probablement la boîte de projet en plastique. Plus tard, j'ai décidé de le faire fonctionner sur une batterie lithium-ion, j'ai donc dû ajouter un stabilisateur de tension (LDO) 3,3 V, un module de charge de batterie et la batterie elle-même. Cela augmente quelque peu le prix, mais je suppose qu'il peut être construit pour moins de 20 euros.

Étape 4: le code

Le code
Le code
Le code
Le code

Le code a été écrit en C avec Atmel (Microchip) Studio 7 et programmé dans l'ATTINY2313 à l'aide d'un OLIMEX AVR_ISP (clone ?). Ouvrez le (main.c) dans le fichier zip ci-dessous si vous souhaitez suivre la description ici.

INITIALISATION

Tout d'abord, l'ATTINY2313 a été configuré pour utiliser un cristal externe car l'oscillateur RC interne est inutile pour mesurer quoi que ce soit. J'utilise un cristal de 10 MHz que j'accorde à la bonne fréquence de 10 000 000 Hz avec un petit condensateur variable. L'initialisation se charge de configurer les ports sur les entrées et les sorties, de configurer les temporisateurs et d'activer les interruptions et l'initialisation du MAX7219. TIMER0 est configuré pour compter une horloge externe, TIMER1 l'horloge interne et également pour capturer la valeur du compteur au front montant de l'ICP, provenant de la bascule D.

Je parlerai du programme principal en dernier, ensuite les routines d'interruption.

TIMER0_OVF

Comme TIMER0 compte jusqu'à 255 (8 bits) puis revient à 0, nous avons besoin d'une interruption pour compter le nombre de débordements. C'est tout ce que TIMER0_OVF fait, il suffit de compter le nombre de débordements. Plus tard, ce nombre est combiné avec la valeur du compteur lui-même.

TIMER1_OVF

TIMER1 peut compter jusqu'à 65536 (16 bits), donc l'interruption TIMER1_OVF compte également le nombre de débordements. Mais il fait plus. Il décrémente également de 152 à 0, ce qui prend environ 1 seconde, puis définit une broche de sortie, allant à l'entrée D de la bascule. Et la dernière chose à faire dans cette routine d'interruption est de décrémenter le compteur de temporisation, en passant de 765 à 0, ce qui prend environ 5 secondes.

TIMER1_CAPT

Il s'agit de l'interruption TIMER1_CAPT qui est déclenchée chaque fois que la bascule D lui envoie un signal, sur le front montant du signal d'entrée (comme expliqué ci-dessus). La logique de capture se charge de sauvegarder la valeur du compteur TIMER1 au moment de la capture, elle est sauvegardée ainsi que le compteur de débordement. Malheureusement TIMER0 n'a pas de fonction de capture d'entrée donc ici sa valeur actuelle et sa valeur actuelle du compteur de débordement sont lues. Une variable de message est définie sur un pour que le programme principal lui dise qu'il s'agit de nouvelles données.

Viennent ensuite deux fonctions pour contrôler le MAX7219

SPI

Bien qu'une interface série universelle (USI) soit disponible dans la puce, j'ai choisi de ne pas l'utiliser. L'écran du MAX7219 doit être contrôlé via SPI et cela est possible avec l'USI. Mais bitbanging SPI est si simple que je n'ai pas pris le temps de le faire avec l'USI.

MAX7219

Le protocole pour configurer le MAX7219 est également assez simple une fois que vous en avez lu le manuel. Il a besoin d'une valeur de 16 bits pour chaque chiffre qui se compose de 8 bits pour le nombre de chiffres (1 à 8) suivis de 8 bits pour le nombre qu'il doit afficher.

MAIN-PROG

La dernière chose est d'expliquer le programme principal. Il s'exécute dans une boucle infinie (while(1)) mais ne fait réellement quelque chose que lorsqu'il y a un message (1) de la routine d'interruption ou lorsque le compteur de délai d'attente est descendu à zéro (pas de signal d'entrée).

La première chose à faire lorsque le message variable est défini sur un, est de réinitialiser le compteur de temporisation, après tout, nous savons qu'il y a un signal présent. La bascule D est réinitialisée pour la préparer au prochain déclenchement qui viendra après le temps de mesure (attendre une seconde).

Les nombres enregistrés dans l'interruption de capture sont ajoutés pour donner le compte de référence et le compte de fréquence d'entrée. (nous devons nous assurer que la référence ne peut jamais être nulle car nous la diviserons plus tard)

Vient ensuite le calcul de la fréquence réelle. Je ne veux sûrement pas utiliser de nombres flottants sur un microcontrôleur avec seulement 2 Ko de flash et seulement 128 octets de RAM. J'utilise des entiers. Mais les fréquences peuvent être comme 314.159 Hz, avec plusieurs décimales. Par conséquent, je multiplie la fréquence d'entrée non seulement avec la fréquence de référence mais aussi avec un multiplicateur, puis j'ajoute un nombre à l'endroit où le point décimal doit aller. Ces chiffres deviendront très très importants lorsque vous ferez cela. Par exemple. avec une entrée de 500 kHz, une référence de 10 MHz et un multiplicateur de 100, cela donne 5 x 10^14, c'est vraiment énorme ! Ils ne s'adapteront pas à un nombre 32 bits, j'utilise donc des nombres 64 bits qui iront jusqu'à 1,8 x 10^19 (cela fonctionne bien sur un ATTINY2313)

Et la dernière chose à faire est d'envoyer le résultat à l'écran du MAX7219.

Le code se compile en quelque 1600 octets, il s'intègre donc dans le flash de 2048 octets disponible dans l'ATTINY2313.

Les registres de fusibles devraient se lire comme ceci:

0xFF ÉTENDU

ÉLEVÉ 0xDF

FAIBLE 0xBF

Étape 5: Exactitude et précision

Exactitude et précision
Exactitude et précision
Exactitude et précision
Exactitude et précision
Exactitude et précision
Exactitude et précision

L'exactitude et la précision sont deux bêtes distinctes. La précision ici est de sept chiffres, la précision réelle dépend du matériel et de l'étalonnage. J'ai calibré le 10 MHz (5 MHz sur le point de test) avec un autre fréquencemètre doté d'un oscillateur discipliné GPS.

Et ça marche plutôt bien, la fréquence la plus basse que j'ai essayée est de 0,2 Hz, la plus élevée de 2 MHz. C'est sur place. Au-dessus de 2 MHz, le contrôleur commence à perdre des interruptions, ce qui n'est pas vraiment surprenant quand on sait qu'à 2 MHz, le signal d'entrée TIMER0 génère plus de 7800 interruptions par seconde. Et l'ATTINY2313 doit aussi faire d'autres choses, les interruptions du TIMER1, à 150 autres interruptions par seconde et bien sûr faire les calculs, contrôler l'affichage et la bascule D. Lorsque vous regardez l'appareil réel, vous verrez que je n'utilise que sept des huit chiffres de l'affichage. Je le fais pour plusieurs raisons.

La première est que le calcul de la fréquence d'entrée est une division, il aura presque toujours un reste, que vous ne voyez pas car c'est une division entière. Deuxièmement, l'oscillateur à quartz n'est pas stabilisé en température.

Les condensateurs qui l'accordent au bon 10 MHz sont en céramique, très sensibles aux changements de température. Ensuite, il y a le fait que TIMER0 n'a pas de logique de capture intégrée et que les fonctions d'interruption prennent toutes un certain temps pour faire leur travail. Je pense que sept chiffres suffisent de toute façon.

Conseillé: