Licence CC BY-NC-SA

Et les sorties “analogiques”, enfin… presque !

Vous vous souvenez du premier chapitre de cette partie ? Oui, lorsque je vous parlais de convertir une grandeur analogique (tension) en une donnée numérique. Eh bien là, il va s’agir de faire l’opération inverse. Comment ? C’est ce que nous allons voir. Je peux vous dire que ça à un rapport avec la PWM…

Convertir des données binaires en signal analogique

Je vais vous présenter deux méthodes possibles qui vont vous permettre de convertir des données numériques en grandeur analogique (je ne parlerai là encore de tension). Mais avant, plaçons-nous dans le contexte.

Convertir du binaire en analogique, pour quoi faire ? C’est vrai, avec la conversion analogique->numérique il y avait une réelle utilité, mais là, qu’en est-il ?

L’utilité est tout aussi pesante que pour la conversion A->N. Cependant, les applications sont différentes, à chaque outil un besoin dirais-je. En effet, la conversion A->N permettait de transformer une grandeur analogique non-utilisable directement par un système à base numérique en une donnée utilisable pour une application numérique.

Ainsi, on a pu envoyer la valeur lue sur la liaison série. Quant à la conversion opposée, conversion N->A, les applications sont différentes, je vais en citer une plus ou moins intéressante : par exemple commander une, ou plusieurs, LED tricolore (Rouge-Vert-Bleu) pour créer un luminaire dont la couleur est commandée par le son (nécessite une entrée analogique :-° ). Tiens, en voilà un projet intéressant ! Je vais me le garder sous la main… :ninja:

Alors ! alors ! alors !! Comment on fait !? :D

Serait-ce un léger soupçon de curiosité que je perçois dans vos yeux frétillants ? :p Comment fait-on ? Suivez -le guide !

Convertisseur Numérique->Analogique

La première méthode consiste en l’utilisation d’un convertisseur Numérique->Analogique (que je vais abréger CNA). Il en existe, tout comme le CAN, de plusieurs sortes :

  • CNA à résistances pondérées : ce convertisseur utilise un grand nombre de résistances qui ont chacune le double de la valeur de la résistance qui la précède. On a donc des résistances de valeur R, 2R, 4R, 8R, 16R, …, 256R, 512R, 1024R, etc. Chacune des résistances sera connectée grâce au micro-contrôleur à la masse ou bien au +5V. Ces niveaux logiques correspondent aux bits de données de la valeur numérique à convertir. Plus le bit est de poids fort, plus la résistance à laquelle il est adjoint est grande (maximum R). À l’inverse, plus il est de poids faible, plus il verra sa résistance de sortie de plus petite valeur. Après, grâce à un petit montage électronique, on arrive à créer une tension proportionnelle au nombre de bit à 1.
  • CNA de type R/2R : là, chaque sortie du micro-contrôleur est reliée à une résistance de même valeur (2R), elle-même connectée au +5V par l’intermédiaire d’une résistance de valeur R. Toujours avec un petit montage, on arrive à créer une tension analogique proportionnelle au nombre de bit à 1.

Cependant, je n’expliquerai pas le fonctionnement ni l’utilisation de ces convertisseurs car ils doivent être connectés à autant de broches du micro-contrôleur qu’ils ne doivent avoir de précision. Pour une conversion sur 10 bits, le convertisseur doit utiliser 10 sorties du microcontrôleur !

PWM ou MLI

Bon, s’il n’y a pas moyen d’utiliser un CNA, alors on va le créer utiliser ce que peut nous fournir la carte Arduino : la PWM. Vous vous souvenez que j’ai évoqué ce terme dans le chapitre sur la conversion A->N ? Mais concrètement, c’est quoi ?

Avant de poursuivre, je vous conseille d’aller [relire cette première partie](https:// zestedesavoir.com/tutoriels/537/arduino-premiers-pas-en-informatique-embarquee/745/les-grandeurs-analogiques/3430/les-entrees-analogiques-de-larduino/#1-un-signal-analogique-petits-rappels) du chapitre sur les entrées analogiques pour revoir les rappels que j’ai faits sur les signaux analogiques. ;)

Définition

N’ayez point peur, je vais vous expliquer ce que c’est au lieu de vous donner une définition tordue comme on peut en trouver parfois dans les dictionnaires. ;) D’abord, la PWM sa veut dire : Pulse Width Modulation et en français cela donne Modulation à Largeur d’Impulsion (MLI). La PWM est en fait un signal numérique qui, à une fréquence donnée, a un rapport cyclique qui change.

Y’a plein de mots que je comprends pas, c’est normal ? o_O

Oui, car pour l’instant je n’en ai nullement parlé. Voilà donc notre prochain objectif.

La fréquence et le rapport cyclique

La fréquence d’un signal périodique correspond au nombre de fois que la période se répète en UNE seconde. On la mesure en Hertz, noté Hz. Prenons l’exemple d’un signal logique qui émet un 1, puis un 0, puis un 1, puis un 0, etc. autrement dit un signal créneaux, on va mesurer sa période (en temps) entre le début du niveau 1 et la fin du niveau 0 :

Représentation d'une période
Représentation d’une période

Ensuite, lorsque l’on aura mesuré cette période, on va pouvoir calculer sa fréquence (le nombre de périodes en une seconde) grâce à la formule suivante :

$$ F = \frac 1 T $$

Avec :

  • FF : fréquence du signal en Hertz (Hz)
  • TT : temps de la période en seconde (s)

Le rapport cyclique, un mot bien particulier pour désigner le fait que le niveau logique 1 peut ne pas durer le même temps que le niveau logique 0. C’est avec ça que tout repose le principe de la PWM. C’est-à-dire que la PWM est un signal de fréquence fixe qui a un rapport cyclique qui varie avec le temps suivant "les ordres qu’elle reçoit" (on reviendra dans un petit moment sur ces mots).

Le rapport cyclique est mesuré en pourcentage (%). Plus le pourcentage est élevé, plus le niveau logique 1 est présent dans la période et moins le niveau logique 0 l’est. Et inversement. Le rapport cyclique du signal est donc le pourcentage de temps de la période durant lequel le signal est au niveau logique 1. En somme, cette image extraite de la documentation officielle d’Arduino nous montre quelques exemples d’un signal avec des rapports cycliques différents :

Des signaux aux rapports cycliques différents
Des signaux aux rapports cycliques différents - (CC-BY-SA - Timothy Hirzel)

Astuce : Rapport cyclique ce dit Duty Cycle en anglais.

Ce n’est pas tout ! Après avoir généré ce signal, il va nous falloir le transformer en signal analogique. Et oui ! Pour l’instant ce signal est encore constitué d’états logiques, on va donc devoir le transformer en extrayant sa valeur moyenne… Je ne vous en dis pas plus, on verra plus bas ce que cela signifie.

https://www.youtube.com/watch?v=3hTxY6cTBSE

La PWM de l’Arduino

Avant de commencer à programmer
Les broches de la PWM

Sur votre carte Arduino, vous devriez disposer de 6 broches qui sont compatibles avec la génération d’une PWM. Elles sont repérées par le symbole tilde ~ . Voici les broches générant une PWM : 3, 5, 6, 9, 10 et 11.

La fréquence de la PWM

Cette fréquence, je le disais, est fixe, elle ne varie pas au cours du temps. Pour votre carte Arduino elle est de environ 490Hz.

La fonction analogWrite()

Je pense que vous ne serez pas étonné si je vous dis que Arduino intègre une fonction toute prête pour utiliser la PWM ? Plus haut, je vous disais ceci :

la PWM est un signal de fréquence fixe qui a un rapport cyclique qui varie avec le temps suivant "les ordres qu’elle reçoit"

Moi :P

C’est sur ce point que j’aimerais revenir un instant. En fait, les ordres dont je parle sont les paramètres passés dans la fonction qui génère la PWM. Ni plus ni moins. Étudions maintenant la fonction permettant de réaliser ce signal : analogWrite(). Elle prend deux arguments :

  • Le premier est le numéro de la broche où l’on veut générer la PWM
  • Le second argument représente la valeur du rapport cyclique à appliquer. Malheureusement on n’exprime pas cette valeur en pourcentage, mais avec un nombre entier compris entre 0 et 255

Si le premier argument va de soi, le second mérite quelques précisions. Le rapport cyclique s’exprime de 0 à 100 % en temps normal. Cependant, dans cette fonction il s’exprimera de 0 à 255 (sur 8 bits). Ainsi, pour un rapport cyclique de 0% nous enverrons la valeur 0, pour un rapport de 50% on enverra 127 et pour 100% ce sera 255. Les autres valeurs sont bien entendu considérées de manière proportionnelle entre les deux. Il vous faudra faire un petit calcul pour savoir quel est le pourcentage du rapport cyclique plutôt que l’argument passé dans la fonction.

Utilisation

Voilà un petit exemple de code illustrant tout ça :

// une sortie analogique sur la broche 6
const int sortieAnalogique = 6;

void setup()
{
    pinMode(sortieAnalogique, OUTPUT);
}

void loop()
{
    // on met un rapport cyclique de 107/255 = 42 %
    analogWrite(sortieAnalogique, 107);
}
Exemple simple d’utilisation de la PWM
https://www.youtube.com/watch?v=tYuo41uMQrI
Quelques outils essentiels

Savez-vous que vous pouvez d’ores et déjà utiliser cette fonction pour allumer plus ou moins intensément une LED ? En effet, pour un rapport cyclique faible, la LED va se voir parcourir par un courant moins longtemps que lorsque le rapport cyclique est fort. Or, si elle est parcourue moins longtemps par le courant, elle s’éclairera également moins longtemps. En faisant varier le rapport cyclique, vous pouvez ainsi faire varier la luminosité de la LED.

La LED RGB ou RVB

RGB pour Red-Green-Blue en anglais. Cette LED est composée de trois LED de couleurs précédemment énoncées. Elle possède donc 4 broches et existe sous deux modèles : à anode commune et à cathode commune. Exactement comme les afficheurs 7 segments. Choisissez-en une à anode commune.

Mixer les couleurs

Lorsque l’on utilise des couleurs, il est bon d’avoir quelques bases en arts plastiques. Révisons les fondements. La lumière, peut-être ne le savez-vous pas, est composée de trois couleurs primaires qui sont :

  • Le rouge
  • Le vert
  • Le bleu

À partir de ces trois couleurs, il est possible de créer n’importe quelle autre couleur du spectre lumineux visible en mélangeant ces trois couleurs primaires entre elles. Par exemple, pour faire de l’orange on va mélanger du rouge (2/3 du volume final) et du vert (à 1/3 du volume final). Je vous le disais, la fonction analogWrite() prend un argument pour la PWM qui va de 0 à 255. Tout comme la proportion de couleur dans les logiciels de dessin ! On parle de "norme RGB" faisant référence aux trois couleurs primaires. Pour connaître les valeurs RGB d’une couleur, je vous propose de regarder avec le logiciel Gimp (gratuit et multiplateforme)1. Pour cela, il suffit de deux observations/clics :

  1. Tout d’abord on sélectionne la "boîte à couleurs" dans la boîte à outils
  2. Ensuite, en jouant sur les valeurs R, G et B on peut voir la couleur obtenue
La boite à couleur de Gimp
La boite à couleur de Gimp
Le ColorPicker de Gimp
Le ColorPicker de Gimp

Afin de faire des jolies couleurs, nous utiliserons analogWrite() trois fois (une pour chaque LED). Prenons tout de suite un exemple avec du orange et regardons sa composition sous Gimp :

La couleur orange avec Gimp
La couleur orange avec Gimp

À partir de cette image nous pouvons voir qu’il faut :

  • 100 % de rouge (255)
  • 56 % de vert (144)
  • 0% de bleu (0)

Nous allons donc pouvoir simplement utiliser ces valeurs pour faire une jolie couleur sur notre LED RGB :

const int ledRouge = 11;
const int ledVerte =  9;
const int ledBleue = 10;

void setup()
{
    // on déclare les broches en sorties
    pinMode(ledRouge, OUTPUT);
    pinMode(ledVerte, OUTPUT);
    pinMode(ledBleue, OUTPUT);

    // on met la valeur de chaque couleur
    analogWrite(ledRouge, 255);
    analogWrite(ledVerte, 144);
    analogWrite(ledBleue, 0);
}

void loop()
{
    // on ne change pas la couleur donc rien à faire dans la boucle principale
}
Utilisation d’une led RGB

Moi j’obtiens pas du tout de l’orange ! Plutôt un bleu étrange…

C’est exact. Souvenez-vous que c’est une LED à anode commune, or lorsqu’on met une tension de 5V en sortie du microcontrôleur, la LED sera éteinte. Les LED sont donc pilotées à l’état bas. Autrement dit, ce n’est pas la durée de l’état haut qui est importante mais plutôt celle de l’état bas. Afin de pallier cela, il va donc falloir mettre la valeur "inverse" de chaque couleur sur chaque broche en faisant l’opération ValeurReelle=255ValeurTheoriqueValeurReelle = 255 - ValeurTheorique . Le code précédent devient donc :

const int ledRouge = 11;
const int ledVerte =  9;
const int ledBleue = 10;

void setup()
{
    // on déclare les broches en sorties
    pinMode(ledRouge, OUTPUT);
    pinMode(ledVerte, OUTPUT);
    pinMode(ledBleue, OUTPUT);

    // on met la valeur de chaque couleur
    analogWrite(ledRouge, 255-255);
    analogWrite(ledVerte, 255-144);
    analogWrite(ledBleue, 255-0);
}
Utilisation d’une led RGB à anode commune
https://www.youtube.com/watch?v=vOB_grEVkwY

On en a fini avec les rappels, on va pouvoir commencer un petit exercice.

À vos claviers, prêt… programmez !
L’objectif

L’objectif est assez simple, vous allez générer trois PWM différentes (une pour chaque LED de couleur) et créer 7 couleurs (le noir ne compte pas ! :P ) distinctes qui sont les suivantes :

  • rouge
  • vert
  • bleu
  • jaune
  • bleu ciel
  • violet
  • blanc

Ces couleurs devront "défiler" une par une (dans l’ordre que vous voudrez) toutes les 500ms.

Le montage à réaliser

Vous allez peut-être être surpris car je vais utiliser pour le montage une LED à anode commune, afin de bien éclairer les LED avec la bonne proportion de couleur. Donc, lorsqu’il y aura la valeur 255 dans analogWrite(), la LED de couleur rouge, par exemple, sera complètement illuminée.

RGB schéma
RGB schéma
RGB montage
RGB montage

C’est parti ! ;)

Correction

Voilà le petit programme que j’ai fait pour répondre à l’objectif demandé :

// définition des broches utilisée (vous êtes libre de les changer)
const int led_verte = 9;
const int led_bleue = 10;
const int led_rouge = 11;

int compteur_defilement = 0; // variable permettant de changer de couleur


void setup()
{
    // définition des broches en sortie
    pinMode(led_rouge, OUTPUT);
    pinMode(led_verte, OUTPUT);
    pinMode(led_bleue, OUTPUT);
}

void loop()
{
    couleur(compteur_defilement); // appel de la fonction d'affichage
    compteur_defilement++; // incrémentation de la couleur à afficher

    // si le compteur dépasse 6 couleurs
    if(compteur_defilement> 6)
        compteur_defilement = 0;

    delay(500);
}

void couleur(int numeroCouleur)
{
    switch(numeroCouleur)
    {
    case 0 : // rouge
        // rapport cyclique au minimum pour une meilleure luminosité de la LED
        analogWrite(led_rouge, 0);
        // qui je le rappel est commandée en "inverse"
        // (0 -> LED allumée ; 255 -> LED éteinte)
        analogWrite(led_verte, 255);
        analogWrite(led_bleue, 255);
        break;
    case 1 : // vert
        analogWrite(led_rouge, 255);
        analogWrite(led_verte, 0);
        analogWrite(led_bleue, 255);
        break;
    case 2 : // bleu
        analogWrite(led_rouge, 255);
        analogWrite(led_verte, 255);
        analogWrite(led_bleue, 0);
        break;
    case 3 : // jaune
        analogWrite(led_rouge, 0);
        analogWrite(led_verte, 0);
        analogWrite(led_bleue, 255);
        break;
    case 4 : // violet
        analogWrite(led_rouge, 0);
        analogWrite(led_verte, 255);
        analogWrite(led_bleue, 0);
        break;
    case 5 : // bleu ciel
        analogWrite(led_rouge, 255);
        analogWrite(led_verte, 0);
        analogWrite(led_bleue, 0);
        break;
    case 6 : // blanc
        analogWrite(led_rouge, 0);
        analogWrite(led_verte, 0);
        analogWrite(led_bleue, 0);
        break;
    default : // "noir"
        analogWrite(led_rouge, 255);
        analogWrite(led_verte, 255);
        analogWrite(led_bleue, 255);
        break;
    }
}
Exercice, affichage de plusieurs couleurs

Bon ben je vous laisse lire le code tout seul, vous êtes assez préparé pour le faire, du moins j’espère. ;)

Voici la démonstration sur simulateur :

https://www.youtube.com/watch?v=hGkwStrLKVw

!(https://www.tinkercad.com/embed/9PHZiwon6Or)


  1. La même chose est réalisable avec des sites comme http://htmlcolorcodes.com/color-picker/

Transformation PWM -> signal analogique

Bon, on est arrivé à modifier les couleurs d’une LED RGB juste avec des "impulsions", plus exactement en utilisant directement le signal PWM.

Mais comment faire si je veux un signal complètement analogique ?

C’est justement l’objet de cette sous-partie : créer un signal analogique à partir d’un signal numérique.

Cependant, avant de continuer, je tiens à vous informer que l’on va aborder des notions plus profondes en électronique et que vous n’êtes pas obligé de lire cette sous-partie si vous ne vous en sentez pas capable. Revenez plus tard si vous le voulez. Pour ceux qui cela intéresserait vraiment, je ne peux que vous encourager à vous accrocher et éventuellement lire ce chapitre pour mieux comprendre certains points essentiels utilisés dans cette sous-partie.

La valeur moyenne d’un signal

Sur une période d’un signal périodique, on peut calculer sa valeur moyenne. En fait, il faut faire une moyenne de toutes les valeurs que prend le signal pendant ce temps donné. C’est une peu lorsque l’on fait la moyenne des notes des élèves dans une classe, on additionne toutes les notes et on divise le résultat par le nombre total de notes. Je ne vais prendre qu’un seul exemple, celui dont nous avons besoin : le signal carré.

Le signal carré

Reprenons notre signal carré :

Un signal carré
Un signal carré

J’ai modifié un peu l’image pour vous faire apparaitre les temps. On observe donc que du temps 00 (l’origine) au temps TT , on a une période du signal. aTaT correspond au moment où le signal change d’état. En somme, il s’agit du temps de l’état haut, qui donne aussi le temps à l’état bas et finalement permet de calculer le rapport cyclique du signal. Donnons quelques valeurs numériques à titre d’exemple :

  • T=1msT = 1ms
  • a=0.5a = 0.5 (correspond à un rapport cyclique de 50%)

La formule permettant de calculer la valeur moyenne de cette période est la suivante :

$$ \langle U \rangle = \frac{U_1 \times aT + U_2 \times (T - aT)}T $$

La valeur moyenne d’un signal se note avec des chevrons <, > autour de la lettre indiquant de quelle grandeur physique il s’agit.

Explications

Premièrement dans la formule, on calcule la tension du signal sur la première partie de la période, donc de 00 à aTaT . Pour ce faire, on multiplie U1U_1 , qui est la tension du signal pendant cette période, par le temps de la première partie de la période, soit aTaT . Ce qui donne : U1×aTU_1 \times aT . Deuxièmement, on fait de même avec la deuxième partie du signal. On multiplie le temps de ce bout de période par la tension U2U_2 pendant ce temps. Ce temps vaut TaTT - aT . Le résultat donne alors : U2×(TaT)U_2 \times (T - aT) Finalement, on divise le tout par le temps total de la période après avoir additionné les deux résultats précédents. Après simplification, la formule devient : U=a×U1+U2a×U2\langle U \rangle = a \times U_1 + U_2 - a \times U_2 Et cela se simplifie encore en :

$$ \langle U \rangle = a \times (U_1 - U_2) + U_2 $$

Dans notre cas, comme il s’agit d’un signal carré ayant que deux valeurs : 0V et 5V, on va pouvoir simplifier le calcul par celui-ci : U=a×U1\langle U \rangle = a \times U_1 ,car U2=0U_2 = 0

Les formules que l’on vient d’apprendre ne s’appliquent que pour une seule période du signal. Si le signal a toujours la même période et le même rapport cyclique alors le résultat de la formule est admissible à l’ensemble du signal. En revanche, si le signal a un rapport cyclique qui varie au cours du temps, alors le résultat donné par la formule n’est valable que pour un rapport cyclique donné. Il faudra donc calculer la valeur moyenne pour chaque rapport cyclique que possède le signal.

De ce fait, si on modifie le rapport cyclique de la PWM de façon maitrisée, on va pouvoir créer un signal analogique de la forme qu’on le souhaite, compris entre 0 et 5V, en extrayant la valeur moyenne du signal. On retiendra également que, dans cette formule uniquement, le temps n’a pas d’importance.

Extraire cette valeur moyenne

Alors, mais comment faire pour extraire la valeur moyenne du signal de la PWM, me direz-vous. Eh bien on va utiliser les propriétés d’un certain couple de composants très connu : le couple RC ou résistance-condensateur.

La résistance on connait, mais, le condensateur… tu nous avais pas dit qu’il servait à supprimer les parasites ? o_O

Si, bien sûr, mais il possède plein de caractéristiques intéressantes. C’est pour cela que c’est un des composants les plus utilisés en électronique. Cette fois, je vais vous montrer une de ses caractéristiques qui va nous permettre d’extraire cette fameuse valeur moyenne.

Le condensateur

Je vous ai déjà parlé de la résistance, vous savez qu’elle limite le courant suivant la loi d’Ohm. Je vous ai aussi parlé du condensateur, je vous disais qu’il absorbait les parasites créés lors d’un appui sur un bouton poussoir. À présent, on va voir un peu plus en profondeur son fonctionnement car on est loin d’avoir tout vu ! Le condensateur, je rappelle ses symboles : Symbole des condensateurs polarisés est constitué de deux plaques métalliques, des armatures, posées face à face et isolées par… un isolant ! :P Donc, en somme le condensateur est équivalent à un interrupteur ouvert puisqu’il n’y a pas de courant qui peut passer entre les deux armatures. Chaque armature sera mise à un potentiel électrique. Il peut être égal sur les deux armatures, mais l’utilisation majoritaire fait que les deux armatures ont un potentiel différent.

Le couple RC

Bon, et maintenant ? Maintenant on va faire un petit montage électrique, vous pouvez le faire si vous voulez, non en fait faites-le vous comprendrez mes explications en même temps que vous ferez l’expérience qui va suivre. Voilà le montage à réaliser :

Un couple RC en action
Un couple RC en action

Les valeurs des composants sont :

  • U=5VU = 5V (utilisez la tension 5V fournie par votre carte Arduino)
  • C=1000μFC = 1000 \mu F
  • Rcharge=1kΩR_{charge} = 1k\Omega
  • Rdecharge=1kΩR_{decharge} = 1k\Omega

Le montage est terminé ? Alors fermez l’interrupteur…

Que se passe-t-il ?

Lorsque vous fermez l’interrupteur, le courant peut s’établir dans le circuit. Il va donc aller allumer la LED. Ceci fait abstraction du condensateur. Mais, justement, dans ce montage il y a un condensateur. Qu’observez-vous ? La LED ne s’allume pas immédiatement et met un peu de temps avant d’être complètement allumée. Ouvrez l’interrupteur. Et là, qu’y a-t-il de nouveau ? En théorie, la LED devrait être éteinte, cependant, le condensateur fait des siennes. On voit la LED s’éteindre tout doucement et pendant plus longtemps que lorsqu’elle s’allumait. Troublant, n’est-ce pas ? :D

Vous pouvez réitérer l’expérience en changeant la valeur des composants, sans jamais descendre en dessous de 220 Ohm pour la résistance de décharge.

Explications

Je vais vous expliquer ce phénomène assez étrange. Vous l’aurez sans doute deviné, c’est le condensateur qui joue le premier rôle ! En fait, lorsque l’on applique un potentiel différent sur chaque armature, le condensateur n’aime pas trop ça. Je ne dis pas que ça risque de l’endommager, simplement qu’il n’aime pas ça, comme si vous on vous forçait à manger quelque chose que vous n’aimez pas. Du coup, lorsqu’on lui applique une tension de 5V sur une de ses armatures et l’autre armature est reliée à la masse, il met du temps à accepter la tension. Et plus la tension croit, moins il aime ça et plus il met du temps à l’accepter. Si on regarde la tension aux bornes de ce pauvre condensateur, on peut observer ceci :

La courbe de charge d'un condensateur
La courbe de charge d’un condensateur

La tension augmente d’abord très rapidement, puis de moins en moins rapidement aux bornes du condensateur lorsqu’on le charge à travers une résistance. Oui, on appelle ça la charge du condensateur. C’est un peu comme si la résistance donnait un mauvais goût à la tension et plus la résistance est grande, plus le goût est horrible et moins le condensateur se charge vite. C’est l’explication de pourquoi la LED s’est éclairée lentement. Lorsque l’on ouvre l’interrupteur, il se passe le phénomène inverse. Là, le condensateur peut se débarrasser de ce mauvais goût qu’il a accumulé, sauf que la résistance et la LED l’en empêchent. Il met donc du temps à se décharger et la LED s’éteint doucement :

La courbe de décharge d'un condensateur
La courbe de décharge d’un condensateur

Pour terminer, on peut déterminer le temps de charge et de décharge du condensateur à partir d’un paramètre très simple, que voici :

$$ \tau = R \times C $$

Avec :

  • τ\tau : (prononcez "to") temps de charge/décharge en secondes (s)
  • RR : valeur de la résistance en Ohm ( Ω\Omega )
  • CC : valeur de la capacité du condensateur en Farad (F)

Cette formule donne le temps τ\tau qui correspond à 63% de la charge à la tension appliquée au condensateur. On considère que le condensateur est complètement chargé à partir de 3τ3 \tau (soit 95% de la tension de charge) ou 5τ5\tau (99% de la tension de charge).

Imposons notre PWM !

Bon, très bien, mais quel est le rapport avec la PWM ?

Ha, haa ! Alors, pour commencer, vous connaissez la réponse.

Depuis quand ? o_O

Depuis que je vous ai donné les explications précédentes. Dès que l’on aura imposé notre PWM au couple RC, il va se passer quelque chose. Quelque chose que je viens de vous expliquer. À chaque fois que le signal de la PWM sera au NL 1 (Niveau Logique 1), le condensateur va se charger. Dès que le signal repasse au NL 0, le condensateur va se décharger. Et ainsi de suite. En somme, cela donne une variation de tension aux bornes du condensateur semblable à celle-ci :

Charge et décharge successive
Charge et décharge successive

Qu’y a-t-il de nouveau par rapport au signal carré, à part sa forme bizarroïde !?

Dans ce cas, rien de plus, si on calcule la valeur moyenne du signal bleu, on trouvera la même valeur que pour le signal rouge. (Ne me demandez pas pourquoi, c’est comme ça, c’est une formule très compliquée qui le dit :P ). Précisons que dans ce cas, encore une fois, le temps de charge/décharge 3τ3\tau du condensateur est choisi de façon à ce qu’il soit égal à une demi-période du signal. Que se passera-t-il si on choisit un temps de charge/décharge plus petit ou plus grand ?

Constante de temps τ\tau supérieure à la période

Voilà le chronogramme lorsque la constante de temps de charge/décharge du condensateur est plus grande que la période du signal :

Charge et décharge successive
Charge et décharge successive

Ce chronogramme permet d’observer un phénomène intéressant. En effet, on voit que la tension aux bornes du condensateur n’atteint plus le +5V et le 0V comme au chronogramme précédent. Le couple RC étant plus grand que précédemment, le condensateur met plus de temps à se charger, du coup, comme le signal "va plus vite" que le condensateur, ce dernier ne peut se charger/décharger complètement. Si on continue d’augmenter la valeur résultante du couple RC, on va arriver à un signal comme ceci :

Charge et décharge successive
Charge et décharge successive

Et ce signal, Mesdames et Messieurs, c’est la valeur moyenne du signal de la PWM !! :D

Calibrer correctement la constante RC

Je vous sens venir avec vos grands airs en me disant : "Oui, mais là le signal il est pas du tout constant pour un niveau de tension. Il arrête pas de bouger et monter descendre ! Comment on fait si on veut une belle droite ?" "Eh bien, dirais-je, cela n’est pas impossible, mais se révèle être une tâche difficile et contraignante. Plusieurs arguments viennent conforter mes dires".

Le temps de stabilisation entre deux paliers

Je vais vous montrer un chronogramme qui représente le signal PWM avec deux rapports cycliques différents. Vous allez pouvoir observer un phénomène "qui se cache" :

Charge et décharge successive
Charge et décharge successive

Voyez donc ce fameux chronogramme. Qu’en pensez-vous ? Ce n’est pas merveilleux hein ! :( Quelques explications : pour passer d’un palier à un autre, le condensateur met un certain temps. Ce temps est grosso modo celui de son temps de charge (constante RC). C’est-à-dire que plus on va augmenter le temps de charge, plus le condensateur mettra du temps pour se stabiliser au palier voulu. Or si l’on veut créer un signal analogique qui varie assez rapidement, cela va nous poser problème.

La perte de temps en conversion

C’est ce que je viens d’énoncer, plus la constante de temps est grande, plus il faudra de périodes de PWM pour stabiliser la valeur moyenne du signal à la tension souhaitée. À l’inverse, si on diminue la constante de temps, changer de palier sera plus rapide, mais la tension aux bornes du condensateur aura tendance à suivre le signal. C’est le premier chronogramme que l’on a vu plus haut.

Finalement, comment calibrer correctement la constante RC ?

Cela s’avère être délicat. Il faut trouver le juste milieu en fonction du besoin que l’on a.

  • Si l’on veut un signal qui soit le plus proche possible de la valeur moyenne, il faut une constante de temps très grande.
  • Si au contraire on veut un signal qui soit le plus rapide et que la valeur moyenne soit une approximation, alors il faut une constante de temps faible.
  • Si on veut un signal rapide et le plus proche possible de la valeur moyenne, on a deux solutions qui sont :
    • mettre un deuxième montage ayant une constante de temps un peu plus grande, en cascade du premier (on perd quand même en rapidité)
    • changer la fréquence de la PWM

Cette expérience peut être visualisée sur le schéma interactif suivant (attention, il faut souvent relancer la simulation pour observer l’impact du changement de valeur du condensateur) :

!(https://www.tinkercad.com/embed/26HFCFSbYWI)

Modifier la fréquence de la PWM

On l’a vu, avec la fréquence actuelle de la PWM en sortie de l’Arduino, on va ne pouvoir créer que des signaux "lents". Lorsque vous aurez besoin d’aller plus vite, vous vous confronterez à ce problème. C’est pourquoi je vais vous expliquer comment modifier la fréquence de cette PWM.

Nouveau message d’avertissement : cette fois, on va directement toucher aux registres du microcontrôleur, donc si vous comprenez pas tout, ce n’est pas très grave car cela requiert un niveau encore plus élevé que celui que vous avez actuellement.

Commençons cette très courte sous-partie.

Pourquoi changer la fréquence de la PWM ?

Oui, pourquoi ? Tout simplement pour essayer de créer un signal qui se rapproche le plus de la valeur moyenne de la PWM à chaque instant. L’objectif est de pouvoir maximiser l’avantage de la structure ayant une faible constante de temps tout en éliminant au mieux son désavantage. Vous verrez peut-être mieux avec des chronogrammes. En voici deux, le premier est celui où la fréquence de la PWM est celle fournie d’origine par l’Arduino, le second est la PWM à une fréquence deux fois plus élevée, après modification du programme :

L'impact de la modification de la PWM
L’impact de la modification de la PWM

Pour une constante de temps identique pour chaque courbe réalisée, on relève que le temps de stabilisation du signal est plus rapide sur le chronogramme où la fréquence est deux fois plus élevée qu’avec la fréquence standard d’Arduino. Ici donc, on a : t2t1=2×(t4t3)t_2 - t_1 = 2 \times (t_4 - t_3) . En effet car le temps (T) est inversement proportionnel à la fréquence (F) selon cette formule : F=1TF = \frac 1 T Avec quelques mots pour expliquer cela, le temps de charge du condensateur, pour se stabiliser au nouveau palier de tension, est plus rapide avec une fréquence plus élevée. À comparaison, pour le premier signal, le temps de charge est deux fois plus grand que celui pour le deuxième signal où la fréquence est deux fois plus élevée.

Mes dessins ne sont pas très rigoureux, mais mes talents de graphistes me limitent à ça. Soyez indulgent à mon égard. :-° Quoi qu’il en soit, il s’agissait, ici, simplement d’illustrer mes propos et donner un exemple concret.

Utilisation du registre

Bigre ! Je viens de comprendre pourquoi on avait besoin de changer la fréquence de la PWM. :D Mais euh… comment on fait ? C’est quoi les registres ? :-°

Les registres…………… eh bien…………… c’est compliqué ! :ninja: Non, je n’entrerai pas dans le détail en expliquant ce qu’est un registre, de plus c’est un sujet que je ne maitrise pas bien et qui vous sera certainement inutile dans le cas présent. Disons pour l’instant que le registre est une variable très spéciale.

Code de modification de la fréquence de la PWM

Alors, pour modifier la fréquence de la PWM de l’Arduino on doit utiliser le code suivant :

// on définit une variable de type byte
// qui contiendra l'octet à donner au registre pour diviser la fréquence de la PWM

// division par : 1, 8, 64, 256, 1024
byte division_frequence=0x01;
// fréquence : 62500Hz, 7692Hz, ...
// temps de la période : 16µs, 130µs, ...

void setup()
{
    pinMode(6, OUTPUT); // broche de sortie

    // TCCR0B c'est le registre, on opère un masquage sur lui même
    TCCR0B = TCCR0B & 0b11111000 | division_frequence;
    // ce qui permet de modifier la fréquence de la PWM
}

void loop ()
{
    // on écrit simplement la valeur de 0 à 255 du rapport cyclique du signal
    analogWrite(6, 128);
    // qui est à la nouvelle fréquence choisit
}
Modification de la fréquence de la PWM

Vous remarquerez que les nombres binaires avec Arduino s’écrivent avec les caractères 0b devant.

Cette sous-partie peut éventuellement être prise pour un truc et astuce. C’est quelque peu le cas, malheureusement, mais pour éviter que cela ne le soit complètement, je vais vous expliquer des notions supplémentaires, par exemple la ligne 14 du code.

Traduction s’il vous plait !

Je le disais donc, on va voir ensemble comment fonctionne la ligne 14 du programme :

TCCR0B = TCCR0B & 0b11111000 | division_frequence;

Très simplement, TCCR0B est le nom du registre utilisé. Cette ligne est donc là pour modifier le registre puisqu’on fait une opération avec et le résultat est inscrit dans le registre. Cette opération est, il faudra l’avouer, peu commune. On effectue, ce que l’on appelle en programmation, un masquage. Le masquage est une opération logique que l’on utilise avec des données binaires. On peut faire différents masquages en utilisant les opérations logiques ET, OU, OU exclusif, … Dans le cas présent, on a la variable TCCR0B qui est sous forme binaire et on effectue une opération ET (symbole &) puis une opération OU (symbole |). Les opérations ET et OU sont définies par une table de vérité. Avec deux entrées, on a une sortie qui donne le résultat de l’opération effectuée avec les deux niveaux d’entrée.

Entrées

Sortie ET

Sortie OU

A

B

A ET B

A OU B

0

0

0

0

0

1

0

1

1

0

0

1

1

1

1

1

Table: Table de vérité de l’opérateur ET et OU

Les opérations de type ET et OU ont un niveau de priorité comme la multiplication et l’addition. On commence toujours par effectuer l’opération ET, puis on termine avec l’opération OU. On pourrait donc écrire ceci :

TCCR0B = (TCCR0B & 0b11111000) | division_frequence;

Prenons maintenant un exemple où la variable spéciale TCCR0B serait un nombre binaire égal à :

TCCR0B = 0b10011101; // valeur du registre

À présent, on lui fait un masquage de type ET :

TCCR0B = 0b10011101;

TCCR0B = TCCR0B & 0b11111000; // masquage de type ET

On fait l’opération à l’aide de la table de vérité du ET (voir tableau ci-dessus) et on trouve le résultat :

TCCR0B = 0b10011101;

TCCR0B = TCCR0B & 0b11111000;

// TCCR0B vaut maintenant : 0b10011000

En somme, on conclut que l’on a gardé la valeur des 5 premiers bits, mais l’on a effacé la valeur des 3 derniers bits pour les mettre à zéro. Ainsi, quelle que soit la valeur binaire de TCCR0B, on met les bits que l’on veut à l’état bas. Ceci va ensuite nous permettre de changer l’état des bits mis à l’état bas en effectuant l’opération OU :

byte division_frequence = 0x01; // nombre haxadécimal qui vaut 0b00000001

TCCR0B = 0b10011101;

TCCR0B = TCCR0B & 0b11111000;
// TCCR0B vaut maintenant : 0b10011000

TCCR0B = TCCR0B | division_frequence;
// TCCR0B vaut maintenant : 0b10011001

D’après la table de vérité du OU logique, on a modifié la valeur de TCCR0B en ne changeant que le ou les bits que l’on voulait.

La valeur de TCCR0B que je vous ai donnée est bidon. C’est un exemple qui vous permet de comprendre comment fonctionne un masquage.

Ce qu’il faut retenir, pour changer la fréquence de la PWM, c’est que pour la variable division_frequence, il faut lui donner les valeurs hexadécimales suivantes :

0x01 // la fréquence vaut 62500Hz (fréquence maximale fournie par la PWM => provient de la fréquence du quartz / 256)
// effectue une division par 1 de la fréquence max

0x02 // f = 7692Hz (division par 8 de la fréquence maximale)
0x03 // f = 976Hz, division par 64
0x04 // f = 244Hz, division par 256
0x05 // f = 61Hz, division par 1024

Vous trouverez plus de détails sur cette page (en anglais).

Test de vérification

Pour vérifier que la fréquence a bien changé, on peut reprendre le montage que l’on a fait plus haut et enlever l’interrupteur en le remplaçant par un fil. On ne met plus un générateur de tension continue, mais on branche une sortie PWM de l’arduino avec le programme qui va bien. Pour deux fréquences différentes, on devrait voir la LED s’allumer plus ou moins rapidement. On compare le temps à l’état au lorsque l’on écrit 1000 fois un niveau de PWM à 255 à celui mis par le même programme avec une fréquence de PWM différente, grâce à une LED.


À partir de maintenant, vous allez pouvoir faire des choses amusantes avec la PWM. Cela va nous servir pour les moteurs pour ne citer qu’eux. Mais avant, car on en est pas encore là, je vous propose un petit TP assez sympa. Rendez-vous au prochain chapitre ! :)