Comment un Arduino peut-il produire une fréquence porteuse spécifique (c'est-à-dire 56 kHz)?


9

Je travaille sur un projet d'optique de l'espace libre pour envoyer des données sans fil entre deux points. Pour ce faire, j'utilise une LED IR connectée à un Arduino Uno qui émet des impulsions avec une fréquence porteuse de 56 kHz pour l'émetteur et un second Arduino avec un module de détection infrarouge de 56 kHz pour le récepteur.

J'ai essayé d'utiliser delayMicroseconds () entre les commandes pin high et pin low afin de créer la fréquence porteuse. Ce genre de travail, mais la fréquence n'est pas toujours la même et tout retard supplémentaire pour pulser le signal (c'est-à-dire le temps nécessaire pour appeler la fonction et décrémenter) peut le changer.

En lisant la fiche technique de l'ATmega328, il semble qu'il existe un moyen de définir une impulsion plus précise à l'aide des minuteries de la puce. Est-ce possible, et si oui, comment créer une impulsion de 56 kHz à l'aide des minuteries?


Quelle est la précision dont vous avez besoin pour votre fréquence 56KHz? C'est-à-dire quelle gamme de fréquences est acceptable dans votre projet? Je pose la question car en utilisant les minuteries Arduino seules, la précision a ses limites.
jfpoilpret

55,5 kHz à 56,5 kHz serait idéal pour maintenir un haut niveau de réactivité dans le détecteur.
jlbnjmn

Réponses:


10

Il est en effet possible de générer un signal à 56 kHz avec une minuterie Arduino .

Un temporisateur peut en fait être vu comme un registre spécial, dans le MCU, qui contient une valeur (commençant à 0) qui est incrémentée à une fréquence qui est la fréquence d'horloge du MCU (16 MHz sur Arduino Uno), possibilité divisée par un facteur appelé prescaler . Lorsque cette valeur atteint une limite, appelée Compare Match , que vous spécifiez, deux choses se produisent:

  • La valeur du registre de minuterie est réinitialisée à 0.
  • Une fonction de rappel ISR (routine de service d'interruption) est appelée (vous pouvez la définir pour pointer vers votre propre code).

L'idée est d'utiliser cet ISR pour changer la sortie d'une broche logique à chaque fois qu'elle est appelée ( HIGH, puis LOW, puis HIGH...).

Maintenant, afin de générer une onde carrée de 56 kHz, vous aurez besoin que votre ISR soit appelé 56000 * 2fois par seconde ( * 2car vous devez changer la valeur de sortie deux fois par période).

Vous pouvez choisir la valeur de mise à l'échelle que vous souhaitez pour une minuterie parmi la liste suivante:

  • 1 (la fréquence d'horloge n'est pas divisée, donc 16 MHz)
  • 8 (la fréquence d'horloge est divisée par 8, donc 2 MHz)
  • 64
  • 256
  • 1024

Il y a deux tailles de temporisateurs / compteurs sur Arduino Uno (ils sont appelés minuterie / compteur en fait): 8 bits et 16 bits.

Sur Arduino Uno (ATmega328P), vous avez globalement trois temporisateurs, mais certains peuvent être utilisés par la bibliothèque principale Arduino ou d'autres bibliothèques utilisées dans vos esquisses (vous devrez vérifier cela par vous-même):

  • timer0 (8 bits)
  • timer1 (16 bits)
  • timer2 (8 bits): celui-ci a plus d'options de mise à l'échelle (1, 8, 32, 64, 128, 256 et 1024)

Maintenant, vous devez générer une onde de 56 kHz à partir de 16 MHz, donc sans mise à l'échelle, vous devrez compter pour:

16000000 / (56000 * 2) - 1 = 141.857( - 1car un minuteur compte de 0 à cette valeur et ne se réinitialise qu'après avoir été atteint)

De ce calcul, nous pouvons tirer deux observations:

  1. 141.857 n'est pas un entier et vous ne pourrez donc pas générer une onde de 56 kHz exactement.
  2. Sans mise à l'échelle préalable, vous avez besoin d'un temporisateur 16 bits car 285 n'est pas représentable comme un entier non signé 8 bits.

A partir de maintenant, vous avez deux options:

  1. Utilisez une minuterie 16 bits ( timer1 ), utilisez prescaler = 1 et sélectionnez 142comme comparaison de comparaison; qui vous donnera la fréquence suivante:16000000 / (2 * (142 + 1)) = 55944 Hz
  2. Utilisez un temporisateur 8 bits ( timer0 ), utilisez prescaler = 8 et sélectionnez 17comme comparaison de comparaison; cela donnera moins de précision avec la fréquence suivante: 16000000 / (8 * 2 * (17 + 1)) = 55555 Hzqui est toujours dans la plage requise.

Maintenant, en ce qui concerne la façon d'écrire votre croquis pour cela, je vous conseille de consulter cet instructable qui est très complet et très intéressant à lire.

Bien sûr, la fiche technique complète ATmega328P est également importante si vous voulez comprendre, dans les moindres détails, ce que vous faites.

Quelques notes importantes:

  • Un ISR est exécuté avec des interruptions désactivées et doit donc être aussi court que possible. En particulier, il existe plusieurs fonctions de la bibliothèque Arduino qui ne doivent pas être appelées à partir d'un ISR.
  • L'horloge Arduino Uno n'est pas très précise (elle utilise un résonateur en céramique au lieu d'un quartz, ce qui aurait été beaucoup plus précis), ce qui signifie que la fréquence de sortie se déplacera davantage.

2
De plus, lorsque la limite spécifiée est atteinte, le matériel peut basculer une broche. Il n'est donc pas du tout nécessaire d'utiliser des ISR. Il y aura toujours une gigue avec un ISR car une instruction ne peut pas être interrompue une fois qu'elle a démarré. Cependant, le matériel bascule toujours la broche au taux souhaité.
Nick Gammon

Il est quelque peu surprenant que l'Arduino Uno utilise un résonateur en céramique, mais une source pour cela est la FAQ Arduino UNO (près de "L'Uno utilise-t-il un résonateur ou un cristal pour l'horloge du processeur?" ).
Peter Mortensen

3

J'ai trouvé tone()utile pour générer des impulsions haute fréquence sur n'importe quelle broche. Il devrait être capable de gérer 56 KHz. (Edit: Comme indiqué par jfpoilpret, le plus proche que vous pourriez réellement obtenir sur un Arduino 16 MHz est d'environ 55,944 KHz)

La difficulté sera évidemment de le combiner avec votre signal de données. Je ne pense pas que vous puissiez le faire dans un logiciel sans recourir à un code de bas niveau. Le matériel devrait être assez simple, car il est numérique.

Tout ce que vous devez faire est de sortir votre signal de données sur une broche différente, puis de le combiner avec le support à l'aide d'une porte ET. Le signal combiné peut aller directement à votre émetteur IR.

Si vous n'avez pas de porte ET à portée de main, il est assez simple de créer la vôtre à l'aide d'une paire de transistors. Recherchez simplement en ligne "transistor et grille".


Les récepteurs ont généralement des sorties basses actives. Si vous connectez le haut de la LED au 56 kHz et le bas à votre broche de données, lorsque la broche de données devient faible, vous obtenez une sortie infrarouge, ce qui devrait rendre le récepteur bas. Non et porte nécessaire, juste une led et une résistance. Le seul problème est limité à ce que les broches io actuelles peuvent entraîner.
EternityForest

2

La réponse acceptée de jfpoilpret est très bien écrite, parfaitement valable et dans 99% des cas je ferai exactement ce qu'il explique. Ses solutions sont bien dans vos paramètres définis, donc elles devraient très bien fonctionner. Mais quoi de mieux que " très bien "? La perfection! Après tout, la question est de générer une valeur exacte. Comme dit assez proche est bon dans la plupart des cas (sans doute tous), et même lorsqu'il s'agit de quelque chose comme des horloges quand 1 seconde doit être 1 seconde, vous devez toujours souffrir d'imperfections héritées des pièces.

Ce que je proposerai n'est pas toujours possible. Dans certains cas, c'est possible, mais avec beaucoup plus de tracas et d'efforts que dans ce cas. Cela vaut-il la peine de dépendre au cas par cas. Mon objectif est principalement de montrer une alternative pour de futures références qui est meilleure dans des cas quelque peu marginaux. Ceci est écrit avec les utilisateurs Arduino novices à l'esprit qui n'ont pas une vaste expérience en électronique.

Pour les personnes plus avancées, cela semblera probablement trop verbeux et stupide. Mais je crois que ces mêmes personnes le savent probablement déjà et n'ont pas besoin de cette réponse. Cela s'applique également à chaque microcontrôleur et à chaque fabricant et architecture. Mais pour les autres microcontrôleurs, vous devrez consulter la fiche technique correcte pour trouver les registres appropriés et les noms et valeurs de pré-échelle.

Dans votre cas, vous avez besoin d'une fréquence spécifique et ce qu'il y a de bien, c'est qu'en réalité, 56 kHz peuvent être atteints très facilement (sans compter les imperfections pratiques des pièces). C'est donc également un exemple parfait.

La génération d'un signal dépend des temporisateurs et de la source d'horloge du microcontrôleur, comme l'explique bien jfpoilpret. Sa réponse ne traite que du problème d'un seul point de vue, c'est-à-dire qu'il s'agit de minuteries. Mais vous pouvez également jouer avec la source d'horloge, ou encore mieux avec les deux pour une synergie et des résultats impressionnants. En modifiant les paramètres de l'environnement, dans ce cas, en piratant le système et en remplaçant la source d'horloge, nous pouvons traiter un problème spécifique avec beaucoup, beaucoup plus de facilité et de simplicité.

Tout d'abord pour rappeler, en raison du basculement de l'état des broches, vous devez exécuter l'ISR deux fois plus que la fréquence du signal. C'est 112 000 fois par seconde. 56 000 et 16 000 000 ne s'additionnent pas très bien comme déjà souligné. Nous devons changer la fréquence du signal ou la fréquence du toucher. Traitons pour l'instant d'une fréquence de signal immuable et trouvons une meilleure vitesse d'horloge.

Il serait plus simple de choisir une horloge avec un ordre de grandeur supérieur à 56 kHz (ou 112 kHz, mais c'est pratiquement le même), car vous n'ajoutez que des zéros et ce type de calcul est le plus simple pour la plupart des gens. Malheureusement, tout dans ce monde est une sorte de compromis avec quelque chose. Toutes les valeurs ne fonctionneront pas.

Le premier exemple est avec une vitesse de générateur de tact trop faible.

Si vous choisissez une horloge à 56 000 Hz, vous ne pourrez rien faire car vous devrez appeler l'ISR à chaque cycle et ne pourrez rien faire d'autre. C'est totalement inutile. Si vous choisissez une vitesse 10 fois plus rapide (560 kHz), vous aurez 9 (10 cycles pour que la minuterie atteigne sa valeur maximale - un cycle pour appeler la fonction ISR) des cycles de microcontrôleur pour faire votre travail et cela est tout à fait possible peut ne pas être suffisant. Vous avez simplement souvent besoin de plus de puissance de calcul.

Si vous choisissez une valeur beaucoup trop grande d'autre part, comme 56 MHz, le microcontrôleur ne peut tout simplement pas fonctionner avec. C'est beaucoup trop rapide. Donc, choisir simplement la plus grande valeur dans la boutique ne la réduira pas non plus.

L'Arduino Uno R3 d'origine a une horloge standard à 16 MHz, donc tout ce qui est plus lent que garanti. La prochaine valeur qui est un ordre de grandeur supérieur à 56 et inférieur à 16 MHz est 5,6 MHz. Cela permettra d'appeler l'ISR tous les 50 cycles et de créer la fréquence de minuterie de 112 000 Hz parfaite. Et votre signal sera exactement de 56 kHz. Vous aurez 49 cycles MCU pour exécuter votre programme entre les appels ISR, mais c'est toujours environ 1/3 de la vitesse de l'horloge d'origine. On peut utiliser le 112 comme base et utiliser une horloge de 11,2 MHz, ce qui donnera environ 2/3 du résonateur de 16 MHz d'origine. La fonction ISR sera appelée tous les 100 cycles et générera toujours un signal parfait de 56 kHz.

Cependant, deux problèmes majeurs existent avec ces valeurs.

  • Le premier problème dépend fortement de vos besoins: vous sacrifiez environ 1/3 (avec 11,2 MHz) de votre puissance de calcul maximale pour obtenir la fréquence de signal exacte qui utilise une valeur de registre facile à trouver (OCR iirc ). Cela peut vous convenir ou non.

  • Le deuxième problème est un showstopper dur : il est très facile de trouver des valeurs, mais très souvent elles n'existent tout simplement pas comme source d'horloge fabriquée. Il s'agit de la page Web du résonateur de Farnell qui manque tout simplement de 5,6 MHz et 11,2 MHz.

Pour contourner cela, nous pouvons regarder les valeurs de résonateur disponibles et découvrir quelque chose d'autre qui peut être utilisé pour générer des valeurs exactement souhaitées. Si nous divisons 56 par 4, nous obtenons 14 et heureusement, il y a un résonateur à 14 MHz. Cela nous donne une vitesse beaucoup plus élevée et plus de puissance et une valeur de registre tout aussi facile à trouver. Pour appeler l'ISR 112000 fois par seconde, nous devons mettre la valeur décimale 124 ou hexadécimale 0x7C dans le registre OCR, donc en comptant 124 cycles + 1 pour appeler l'ISR, nous obtenons la valeur parfaite souhaitée.

NB

  1. ISR - routine de service d'interruption (c'est le code qui est exécuté uniquement sur les interruptions générées)
  2. La taille de votre programme dépend de la taille de la mémoire! Cela n'a rien à voir avec la vitesse d'horloge et n'a rien à voir avec la fréquence à laquelle vous appelez l'ISR.
  3. Lorsque le microcontrôleur démarre avec une commande de programme, un compteur est incrémenté. Si une interruption est générée, l'ISR est appelé et cette valeur est stockée dans un registre spécial. Lorsque le code ISR est terminé, la valeur du compteur de programme est restaurée à partir de ce registre spécial et le programme continue d'où il a été interrompu comme s'il ne s'était jamais produit.

    Je vais donner un exemple extrêmement stupide. Si vous êtes puriste, je vous préviens: des saignements de nez et d'oeil peuvent survenir.

    Imaginez que vous deviez marcher d'un endroit à un autre. Les instructions d'itinéraire étape par étape sont votre programme principal et ses commandes. La vitesse à laquelle vous marchez ou courez dépend de votre "vitesse d'horloge", mais pas des instructions de l'itinéraire (30 pas en avant, 1 tour à 90 degrés à gauche, 10 pas en avant, 45 degrés à droite, etc.) Ils sont toujours les mêmes . Imaginez maintenant un petit enfant ou un politicien local corrompu et gourmand qui détache vos chaussures de temps en temps. Il s'agit de l'événement qui génère une interruption. Ensuite, vous vous arrêtez après votre dernière étape, vous agenouillez et attachez à nouveau votre chaussure. Ceci est votre programme ISR.

    Ensuite, vous continuez de l'endroit où vous vous êtes arrêté; vous ne partez pas du début. Lorsque vous marchez sans souci dans le monde et avec tout le temps, vous ne vous souciez pas même si vous devez attacher votre chaussure à chaque étape. Cependant, si vous le faites avec des contraintes de temps, comme courir sur 100 mètres aux Jeux olympiques (ou fuir un prédateur mangeur de chair affamé), arrêter et attacher vos chaussures peut avoir des conséquences désastreuses. C'est la même chose avec les microcontrôleurs. Même si vous n'exécutez qu'une seule ligne de code, votre programme continuera, bien que lentement. Si vous ne vous souciez pas du tout de la vitesse, ce ne sera pas un problème. Si vous devez faire un certain temps, comme utiliser d'autres actions dépendant de la minuterie, les interférences peuvent être très indésirables et problématiques.

  4. Moins est plus! Une horloge plus rapide n'est pas toujours meilleure. Les appareils cadencés plus lentement consomment beaucoup moins d'énergie. Cela peut être un point crucial dans un appareil fonctionnant sur batterie.

  5. Les cycles nécessaires sont dérivés de ces formules:
    (vitesse d'horloge / (valeur de mise à l'échelle * fréquence d'appel ISR requise)) - 1


TLDR: Dessouder l'oscillateur céramique 16 MHz et le remplacer par un autre qui autorise exactement 56 kHz par division entière (par exemple 14 MHz et diviser par 250).
Peter Mortensen

0

Vous pouvez activer et désactiver le support en basculant simplement le mode de broche du support entre la sortie et l'entrée. Je l'ai utilisé pour contrôler une pompe à chaleur via le port infrarouge (télécommande) à 37 KHz.


0

Il n'est pas nécessaire d'utiliser un ISR pour créer le transporteur. Il vous suffit de configurer une minuterie pour produire une sortie PWM de 50% à la fréquence porteuse requise. L'ISR est alors juste en charge de moduler la porteuse - généralement à des intervalles de 0,5 ou 1 ms - un taux beaucoup plus confortable. D'après mon expérience, une erreur de 5% dans la fréquence porteuse est tolérée par la plupart des récepteurs IR. J'ai utilisé un Freetronics EtherMega 2560 (qui a beaucoup de minuteries) mais je suis sûr que d'autres processeurs feront aussi bien.


Comment la modulation de la porteuse est-elle alors implémentée exactement? Changer le mode pour la broche de capture de sortie du temporisateur entre l'entrée (porteuse désactivée) et la sortie (porteuse activée)?
Peter Mortensen
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.