Timer/Counter & PWM pour des fréquences élevés.

Cette article traite de l'utilisation de certaines fonctionnalités de l'ATMega328P qui peuvent s’avérer utiles pour le traitement des signaux audio (par exemple, réaliser une pédale d'effet), jouer des samples de musique (échantillonnés à 44100Hz ou moins), ou encore réaliser de la synthèse sonore.

Il est question d'aborder ici le stricte minimum pour utiliser le PWM (Pulse Width Modulation) à une fréquence suffisamment élevé affin de pouvoir générer un signale analogique et de contrôler son amplitude. En bonus, nous pourrons exécuter une interruption toute les 16uS.

Je recommande fortement au gens aillant un peut d'expérience de lire directement la documentation relative aux Timers/Counters, PWM, et aux registres DDRx/PORTx.

Timer et PWM

L'ATMega328P comprend 3 Timers, c'est à dire trois compteurs qui sont incrémenté par le microcontroleur tout les N ticks d'horloges (K peut valoir 1, 8, 32, 64, 256, 1024 celons vos envies). Ces timers se noment "Timer0", "Timer1" et "Timer2".  Le Timer0 est utilisé par la bibliothèque arduino pour évaluer l'écoulement du temps (delay, microsecond) et pour les sorties PWM associés à ce timer. Le Timer1 dispose d'un compteur 16bits, c'est à dire de 0 à 0xFFFF, alors que les timers 2 et 1 sont en 8bits (de 0 à 0xFF). L'idée est que nous voulons compter vite, très vite, donc nous avons intéret à utiliser un compteur 8bits. Notre choix se port donc tout naturellement sur le timer2.

Le PWM correspond à la mise sous tension d'une patte de l'ATMega durant un certain laps de temps, puis de sa mise à 0 durant un autre instant, et le tout répété très rapidement. Cela permet de simuler un signale analogique de tension comprise entre 5v et 0v (Moins si vous n'utilisez pas l'alimentation 5V). Le principe est très bien décrit par le schéma suivant provenant du site d'arduino(http://arduino.cc/en/Tutorial/PWM) :

Il faut savoir que chaque Timer controle deux sorties PWM. Les pattes correspondant à ces sorties sont indiqué sur la page 2 de la documentation atmel (OCnA et OCnB, où n est le numéro du timer). Dans notre cas nous utiliseront la sortie OC2A, qui correspond au pin 11 d'une carte arduino.

Le fonctionnement du PWM est extrêmement simple ; Vous réglez le PWM avec une valeur comprise entre 0 et 255, disons C. Alors, tant que le compteur est plus petit que C, il y auras une tension de 5V sur la sortie OC2A. Quand le compteur dépasse C, la tension passe à 0V. Pour accélérer une sortie PWM, il faut donc accélérer le timer qui est associé.

Le mode FastPWM (ATMega328P datasheet p152-153)

Il existe plusieurs configurations possible pour la sortie PWM, la frequence des timers, etc. Je vous conseille très fortement de lire la documentation atmel à ce sujet. Dans notre cas, nous cherchons la plus rapide, et il y en a une qui correspond tout à fait à nos besoins ; La configuration Fast PWM.

Le compteur que nous avons évoqué, associé au Timer2, se nome "TCNT2"(Timer Counter 2), et peut être lut et écrit à tout moment. La valeur à partir de la quel le signal basule de 5V à 0V est stocké dans OCR2A(Output Compare Register 2 A). Un second registre de comparaison est disponible, OCR2B, et correspond au pin OC2B.

Dans ce mode, le comTCNT2 part de 0, puis atteint progressivement OCR2A. Alors, la tension de sortie de OC2A s'inverse. À cette instant, une interruption peut être déclenchée. C'est à dire, si vous n'êtes pas familier avec ce mécanisme, qu'une fonction que vous aurez préalablement écrite, compilé, et associé à ce mécanisme, seras exécuté. De même pour OCR2B/OC2B.

Le compteur continus sa montée, et atteint alors 0xFF. Il y a alors overflow : le compteur repasse à 0x00 à la prochaine incrémentation, et éclanche interruption TIMER2_OVF (Timer 2 Overflow), si elle est activée.

Sachez enfin que vous pouvez configurer si la tension de sortie avant que le compteur atteigne OCR2A doit être haute ou basse. Nous choisirons qu'elle est haute, puis basse. De cette façon, si OCR2A = 0, la tension sera 0 sur une période (16us, pour mémoire), et si OCR2A = 0xFF, elle sera de 5V (toujours sur une période).

Le schéma suivant, issu de la documentation, décrit une succession d’interventions sur le registre OCR2A, l'évolution du compteur, le déclenchement des interruptions, et les tensions de sorties(haut pour 5V et bas pour 0V) celons la configuration des deux bits COM2A1 et COM2A0 (Pour les valeur 2( = 1 0 en binaire) et 3 = (1 1 en binaire))

La fréquence à la quel l’interruption TOV2(TIMER2_OVF) est appelé se calcul aisément à partir de celle de l'horloge de l'ATMega. Si vous utilisez un quartz externe à 16MHz (c'est le cas des cartes arduino) la fréquence est alors $\frac{f_{clock}}{N . 256}$ où $N$ est le facteur d'échelle (prescale factor), dont nous parlerons un peu plus loin.

L'activation du mode FastPWM (p160 de la documentation) se fait en fixant les bits du "Timer Counter Control Register"  A et B (TCCR2A et TCCR2B).

Le premier contient le type de sortie COM2A1:0 et COM2B1:0, ainsi que les bits WGM21 WMGM20 contrôlant le mode de l'horloge.  Le second (p163)  contient le dernier bit de configuration du mode, WGM22 et les trois bits permettant de sélectionner le facteur d'échelle (dans notre cas, nous choisirons 1, pour que la fréquence soit la plus élevé) ; CS22, CS21, CS20.

Ainsi, nous pouvons déjà configurer le mode Fast PWM :

TTCCR2A = 1 << COM2A1 | 1 << WGM01 | 1 << WGM00;
TTCCR2B = 0 << WGM02 | 0 << CS22 | 0 << CS21 | 1 << CS20;

Nb : Sachez que pour chacun des modes, vous trouverez un tel schéma dans la documentation :)

Facteur d'échelle

Les bits CS22, CS21 et CS20 permettent de configurer le facteur d’échelle. Le concept est simple (p155 et p156 de la documentation pour des schéma extrêmement claires) ; le compteur TCNT2 seras incrémenté de 1 tout les N ticks d'horloge, où la valeur de n dépend du facteur d'échelle choisit, d'après le tableau suivant (p164 de la documentation) :

Activer la sortie PWM

Nous avons donc configurer le compteur, et la sortie PWM peut maintenant être utilisée. Mais encore faut-il l'activer. Pour cela, il faut sélectionner la "direction" du pin associé au comparateur A (OC2A) comme "OUTPUT". Cela se fait via le Data Direction Register B (car la sortie OC2A est la troisième patte du port B, c'est à dire la sortie 11 de la carte arduino).

DDRB |= 1 << DDB3;

Pour désactiver la sortie PWM lorsque le pin est toujours en mode output, il suffit de modifier la valeur de COM2A.

Utiliser les interruptions

Le dernier outil, pour pouvoir par exemple effectuer une acquisition audio à  $31,25kHz$, est interruption OVF, déclenchée dès que le compteur passe de 0xFF à 0x00.  Pour ce faire, il faut informer le compilateur que votre fonction doit être associé à une interruption, et activer l'intéruption grâce au masque d’interruption TIMSK2.

// Configuration
TIMSK2 = 1 << TOIE2;
 
// ...
 
ISR(TIMER2_OVF_vect)
{
  // Code de l'interruption
}

La bibliothèque C AVR

Si nous pouvons utiliser toute ces macros, c'est bien quelles sont définit quelques part. Il s'agit d'une bibliothèque C permettant de développer sur les microcontroleurs atmel en C. Cette bibliothèque contient une documentation dont je recommande chaudement la lecture, notamment pour ceux qui souhaiterais diminuer le temps perdu en entête C dans l’interruption OVF (environs 20 à ticks d'horloge à 16MHz, ce qui représente tout de même 20 à 30 256ième du temps d’exécution de votre microcontroleur!)

Sachez aussi qu'une façon plus agréable d'écrire (1 << ABCD) est _BV(ABCD).

Documentation :

-La bibliothèque C AVR (Interruptions) : http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
-Atmel ATMega328 Datasheet : http://www.atmel.com/Images/doc8271.pdf
-Realtime Audio Processing de Martin Nawrath : http://interface.khm.de/wp-content/uploads/2008/10/arduino_realtime_audio_eng.pdf
-PWM : http://arduino.cc/en/Tutorial/PWM

 

Il semblerait que le serveur SQL ai subit un crash, peut-être depuis plusieurs jours, aillant pour conséquence l’indisponibilité du blog (une table endommagée). Veuillez m'en excuser.

Un jolis rappelle comme quoi on est jamais à l’abri d'un crash inopportun (bien que je ne connaisse pas de crash opportun), et qu'il peut être aviser de faire quelques sauvegardes... :/

 

Un peu de retard...

Comme vous l'auriez remarqué, cela fait bien un petit moment que je n'ai pas publié de billet. Non pas que je n'en ai pas eu l’envie, mais avant de publier, il faut quelque chose à dire, et de préférence que ceci ai un réel apport, et non ne soit une concaténation approximative d'informations glané sur les flux d'informations les plus commun, ce que chacun sais faire à son gout celons ses propres besoins. J'ai effectivement quelques documents intéressant sous la main, mais j'aimerais les relire et les retravailler un minimum avant de les publier. Malheureusement, je manque cruellement de temps. Veuillez donc m'excuser pour ce long silence. Je vais tacher de publier plus régulièrement.

 

Nova Methodus pro maximis et minimis
itemque tangentibus, quae nec fractas nec irrationales quantitates moran-
tur et singulare pro illis calculi genus.

Il s'agit du titre d'une publication de Gottfried Wilhelm Leibniz, qui rappelons le, est un philosophe, diplomate, et mathématicien/physicien du XVIIem siècle. Ce texte, est l'un des précurseurs relatifs au calcul différentiel (dérivées, et généralisation des dérivés pour les fonctions de plusieurs variables). On y trouve les règles de différentiations du produit(règle de liebniz), de la somme (linéarité), et les règles que l'on peut en dérivé. Bien entendu, dans l'esprit de liebniz, nulls formes linéaires, mais bien des infiniments petits, des quantité que l'on sautoriseras aujourd'hui sans le moindre doute à mettre en parallèle avec les infinitésimaux du corps des surréels ( par exemple, si l'on inverse l'ordinal $\omega + 1$, on obtient infinitésimale $\frac{1}{\omega + 1} ).

À défaut de pouvoir accéder a ces infinitésimaux, il est possible de les comparer, en prenant leur rapport. Dans le cas ou celui ci est fini, on a ainsi le rapport de deux quantité infinitésimale, que l'on peut à très juste titre associer a la limite du quotient de deux quantités finies tendant chacune vers les quantités infinitésimale précédemment nommé.

Dans le cadre du cours d'histoire des mathématiques, j'ai rédigé quelques lignes explicatives sur cette publication, que vous pouvez trouver dans le paragraphe "commentaire suivit" du document situé en bas de ce billet. Notez aussi une analyse philosophique très intéressante de ce texte. Par contre, à ce sujet, je ne saurait donner plus de détails.

Bref, autant dire qu'une lecture de ce papier ne peux pas faire de mal, et pourrait même pour certain démystifier ce "sacrilège des physiciens" consistant à "diviser et multiplier" par des "dt". (Même si une vrais formulation rigoureuse de tout ceci serait à chercher dans les formes différentielles, et ce qui s'y rapporte.)

Le voici sans plus attendre : http://zenol.fr/dl/hdm_liebniz.pdf

Si certains des points évoqué ne sont pas très claires (notamment ceux abordé par ce billet), voici un complément :

-Visual Complex Analysis, Tristan Needham , p.20-21 pour une explication claire en quelque ligne d'une formulation rigoureuse à partir de nos notions de maths de ce que l'on pourrait appeler un infinitésimal.
-On numbers and Games, John Conway, pour une formalisation précédé d'une introduction très claire aux sur-réels. Sinon, vous avez toujours http://en.wikipedia.org/wiki/Surreal_number

 

 

Un petit billet pour présenter cette conférence de Daniel Fortier sur la mécanique quantique, particulièrement intéressante, qui ne requière que peu(pas?) de connaissances mathématique pour être abordé.

C'est un petit jeu de 12 vidéos, très agréable (si vous souhaitez vous détendre en soiré) :

http://www.youtube.com/watch?v=y9G9B3-q4xI
http://www.youtube.com/watch?v=dJEP0_w4Pfs
http://www.youtube.com/watch?v=6aczefi2XIk
http://www.youtube.com/watch?v=3NZCOwx6dSk
http://www.youtube.com/watch?v=ODM5ECaolgk
http://www.youtube.com/watch?v=Ysp74XJ7iSo
http://www.youtube.com/watch?v=n0sUBspLMj0
http://www.youtube.com/watch?v=s2rn8LBmKTY
http://www.youtube.com/watch?v=kmpKh-ZcxQ8
http://www.youtube.com/watch?v=yn1zvivbj0E
http://www.youtube.com/watch?v=BHxOWs3Rs4c
http://www.youtube.com/watch?v=ZD1lD-DL_OE

Sur ce, bonsoir.

 

Bonjour

Comme je l'avais laissé entendre dans le précédent billet, je travaillais sur un second document, relatif à l'informatique. À vrais dire, travailler est un bien grand mot. Il se trouve que je devais rédiger le dernier chapitre, mais souhaitant m'imposer de donner la priorité à mes études, j'ai reporté la rédaction de ce dernier après l'échéance du rendu du premier document (cf: billet précédent). Il s'est avéré que sa rédaction fut (beaucoup) plus rapide que je ne le prévoyais. Aussi, c'est la correction orthographique qui me prit tant de temps.

Un petit retour sur la rédaction

Je voudrais demander à mes lecteurs de ne pas être trop sévère quant à la rédaction ; il s'agit du second texte de cette envergure (une 40aine de pages) bien que sa "publication" ne vienne qu'après le troisième (qui n'est autre que mon TIPE). Les phrases ne sont pas toujours très élégantes, et parfois les mots mal choisis. Je ne me sentais pas le courage de reprendre tout le document. Il n'en est pas moins un document qui sauras surement se montrer utile à des étudiants qui souhaiterais découvrir et comprendre le mythique "Bruit de Perlin".

Le bruit de Perlin ?

Pour ceux qui ne connaitrais pas encore cette algorithme, le bruit de Perlin est un outil très prisé pour la génération de textures paramétriques. Plus que des mots, une simple image pour résumer :

Perlin Noise

Voici, sans plus attendre, le lien vers le document en question : Bruit de Perlin

Perlin Noise

© 2012 Zenol's Blog Suffusion theme by Sayontan Sinha