Manuel de laboratoire pour contrôleurs embarqués

Utilisation du langage C et de la plateforme Arduino


précédentsommairesuivant

XIV. Sortie « analogique » via des signaux PWM

Dans cet exercice, on examinera les « sorties analogiques » à travers l'utilisation des signaux PWM ou Pulse Width Modulation (NDLR en français, Image non disponibleMLI pour Modulation en Largeur d'Impulsion). Les signaux PWM permettent de générer des signaux analogiques à l'aide de sorties numériques, à défaut de disposer de véritables sorties variables en continu. Certains microcontrôleurs et cartes à microcontrôleur intègrent en effet des DAC (NDLR Digital-Analogic Converter ou Convertisseur Numérique-Analogique) comme l'Arduino Due, mais comme la plupart n'en disposent pas, un signal numérique impulsionnel modulé en largeur d'impulsion avec un rapport cyclique variable peut être utilisé à la place.

Note de la rédaction

Un signal PWM est un signal logique, rectangulaire et périodique, dont on peut faire varier le rapport cyclique (le pourcentage de temps où le signal est à l'état haut sur une période du signal).

Image non disponible
Allure d'un signal modulé en largeur d'impulsion ou PWM

Le signal n’est nullement analogique, mais on peut l'adapter en lui faisant subir un filtrage de type passe-bas.

Image non disponible
Image Wikipédia

Filtrer ce signal carré permet d’obtenir la tension moyenne VMOY (et parfois, la charge se comporte avantageusement comme un filtre passe-bas). Si la fréquence porteuse est significativement supérieure à la fréquence de coupure du filtre, l'ondulation résiduelle reste faible.

Image non disponible

Rapport cyclique : kitxmlcodeinlinelatexdvp\alpha=\frac{t_{on}}{T}finkitxmlcodeinlinelatexdvp

Tension moyenne : kitxmlcodeinlinelatexdvpV_{MOY}=\frac{1}{T}\int_{0}^{T}v(t)\,\mathrm{d}t=\frac{1}{T}\times \left ( V_{MAX}\cdot \alpha T \right )=\alpha\cdot V_{MAX}finkitxmlcodeinlinelatexdvp

Mathématiquement, la tension « analogique » utile produite en sortie du filtre passe-bas est proportionnelle à l'aire sous la courbe du train d'impulsions modulé. Si vous avez pensé à moyenner le signal du train d'impulsions avec un filtre passe-bas, un rapport cyclique petit (proche de 0 %) produira une tension moyenne basse, et inversement un rapport cyclique grand (proche de 100 %) produira une tension moyenne élevée. Certains composants vont naturellement filtrer les hautes fréquences alors que d'autres non. Dans cet exercice, on commencera par étudier le comportement d'une simple LED.

Il est facile d'allumer ou éteindre une LED. Considérez le code suivant :

 
Sélectionnez
/* PWM V1 Test luminosité LED, version manuelle */

#define LEDBIT   0x40

// on/off temporisation en millisecondes
#define LEDONTIME   300
#define LEDOFFTIME  300

void setup()
{
    // Configuration connecteur 6 en sortie vers la LED
    DDRD |= LEDBIT;
}

void loop()
{
    PORTD |= LEDBIT;    // allumer la LED
    delay(LEDONTIME);

    PORTD &= (~LEDBIT); // éteindre la LED
    delay(LEDOFFTIME);
}

Dans cet exemple, on allume la LED pendant 300 millisecondes, on l'éteint pendant 300 millisecondes, puis on perpétue le cycle périodiquement, toutes les 600 millisecondes. Pour contrôler la LED, réalisez un circuit à base de transistor NPN piloté par la sortie 6 de l'Arduino. Saisissez le code, compilez-le et transférez-le afin de tester le programme. Réduisez les temporisations on/off des LED à 30 millisecondes chacune et répétez l'opération. La LED devrait clignoter plus rapidement. Réduisez à nouveau les temporisations on/off des LED, cette fois à 5 millisecondes chacune et répétez l'opération. Une chose curieuse arrive, la LED ne semble plus clignoter, mais sa luminosité est plus faible. Tandis que les temporisations descendent en dessous de 20 millisecondes, l’œil humain ne distingue plus ces flashs lumineux et les assimile en niveau d'intensité lumineuse continue(1), comme s'il moyennait le signal lumineux. Comme sur une période du signal, la LED est allumée la moitié du temps, elle apparaîtra allumée en continu, mais avec sa luminosité atténuée de moitié par rapport à sa luminosité maximum. Vous pouvez vérifier le phénomène en changeant la temporisation on de la LED à 1 milliseconde, et la temporisation off à 9 millisecondes, perpétuant ainsi un cycle périodique de période 10 millisecondes. La luminosité de la LED sera davantage atténuée puisque celle-ci ne sera allumée que 10 % du temps.

Plutôt que de régler les temporisations manuellement, on peut utiliser la fonction analogWrite() sur une des sorties capables de générer des signaux PWM (les sorties dédiées de la carte sont repérées avec un symbole « ~ » (tilde) sérigraphié au niveau du connecteur). Il se trouve que le connecteur 6 offre cette possibilité, et donc nous n'avons qu'un léger changement à effectuer au niveau du code :

 
Sélectionnez
/* PWM V2 Test luminosité LED, version avec analogWrite */

#define LEDPIN 6

// luminosité entre 0 et 255
#define LEDBRIGHTNESS 230

void setup()
{
}

void loop()
{
    analogWrite(LEDPIN, LEDBRIGHTNESS);
}

Remarquez que le connecteur 6 n'a pas besoin d'être configuré en sortie puisque la fonction analogWrite() s'en charge automatiquement (voir Image non disponibleanalogWrite()). Si vous relevez le signal du connecteur 6 à l'oscilloscope, vous verrez un signal carré à 490 Hz environ, avec un rapport cyclique de 90 % (NDLR car 230/255 ≈ 0,90). Notez que le paramètre LEDBRIGHTNESS pourrait être remplacé par une variable résultant d'une lecture d'entrée analogique avec analogRead(). On peut donc connecter un potentiomètre à une entrée analogique et récupérer la valeur issue de la conversion analogique-numérique comprise entre 0 et 1023. Il reste alors à rééchelonner la plage de valeurs vers une autre plage de valeurs entre 0 et 255 (unsigned char), compatible avec le paramètre en entrée de la fonction analogWrite(), et jouer ainsi sur la luminosité de la LED. Ce changement d'échelle peut être effectué avec la fonction map() de la bibliothèque Arduino :

 
Sélectionnez
result = map(value, fromLow, fromHigh, toLow, toHigh);

Dans notre cas, on utilisera :

 
Sélectionnez
result = map(value, 0, 1023, 0, 255);

Par la suite, connectez un potentiomètre 10 kΩ entre l'alimentation et la masse. Connectez son curseur au connecteur A0 de l'Arduino. Saisissez le code suivant, compilez-le et transférez-le :

 
Sélectionnez

/* PWM V3 Gradateur LED utilisant analogWrite et un potentiomètre */

#define ANALOG_IN_PIN 0
#define LEDPIN 6


void setup()
{
    analogReference( DEFAULT );
}

void loop()
{
    int a;

    a = analogRead( ANALOG_IN_PIN );

    a = map(a, 0, 1023, 0, 255);
    analogWrite(LEDPIN, a);
}

Jouer avec des LED est bien beau, mais on pourrait souhaiter piloter des choses un peu plus intéressantes, par exemple un moteur. Bien entendu, notre circuit de pilotage de LED sera sous-dimensionné pour la plupart des moteurs, mais il sera suffisant moyennant quelques modifications mineures avec un petit moteur à courant continu pour hobbyiste à faible consommation (10 à 15 mA en fonctionnement à vide). Un exemple de circuit de pilotage d'un tel moteur est montré dans la figure ci-dessous :

Image non disponible
Circuit de pilotage d’un moteur avec un transistor bipolaire

Notez tout d'abord qu'une alimentation externe plus puissante est nécessaire. Dans ce cas, une alimentation 15 V à courant continu serait appropriée (NDLR une alimentation réglable à CC régulée de laboratoire 0-15 V et 0-2 A par exemple, soit 30 W au maximum). R1 est choisi aux alentours de 6,8 kΩ pour garantir la saturation du transistor, et C1 aux alentours de 100 nF. D1 est une diode de type 1N4002. Son rôle est d'éviter, ou d'amortir les pics de tension dus à l'inductance du moteur lorsque le transistor bascule de l'état saturé à l'état bloqué(2).

Note de la rédaction

Une première remarque sur la présence du condensateur C1 dans le schéma précédent. On retrouve le même montage avec ce condensateur C1 dans un autre ouvrage du même auteur, avec la seule mention : « The resistor and capacitor at the base are used to shape the incoming pulse to improve performance. » Si la présence de la résistance R1 est nécessaire pour contrôler le courant à la base du transistor, la justification de la présence du condensateur C1 pour « améliorer les performances » ne nous paraît pas évidente a priori. Assurément, vous ne risquez rien à omettre ce condensateur dans un premier temps.

La valeur de la résistance de base R1 doit être calculée, mais l'avantage d'utiliser le transistor en « tout ou rien » (état bloqué ou saturé pour faire de la commutation), c'est qu'elle se calcule très facilement grâce à la datasheet du transistor.

Image non disponible
Transistor NPN : symboles et conventions

Si on prend les caractéristiques du transistor BC547 :

Image non disponible
Extrait datasheet BC547

Le constructeur ne garantit plus le fonctionnement du transistor si :

  • la tension entre le collecteur et l'émetteur dépasse 45 V ;
  • le courant demandé au niveau du collecteur dépasse 100 mA ;
  • la puissance dissipée, sans dissipateur et à la température ambiante 25 °C, dépasse 0,625 W.
Image non disponible

D’après le constructeur du transistor, celui-ci est complètement saturé si le courant de base IB est 20 fois inférieur au courant du collecteur IC. Ensuite, le constructeur donne au moins deux exemples concrets : si IC = 100 mA (I= Imaxi) et IB = 5 mA (vingt fois inférieur) alors le transistor sera saturé, sa tension collecteur-émetteur ne sera évidemment pas de 0 V comme un interrupteur fermé, mais elle s'en approchera, 0,2 V typiquement et jusqu'à 0,6 V maxi garanti dans les conditions de courant données juste avant.

Calcul de la résistance de base

Il faut que le courant de base IB soit 20 fois inférieur au courant de collecteur IC.

Imaginons une charge qui consomme 30 mA, donc IC = 30 mA, il faut que IB soit égal ou très proche de 1,5 mA (idéalement, il faut même être un peu au-dessus des 1,5 mA pour « sursaturer »).
Résistance de base = (Tension de sortie de l'Arduino - VBE(SAT)) / IB (application de la loi des mailles et de la loi d’Ohm)
Résistance de base = (5 – 0,7) / 1,5 mA = 2,8 kΩ, et on mettra une résistance normalisée de 2,7 kΩ.

Pour des charges requérant plus de puissance, un transistor à effet de champ (FET pour Field Effect Transistor) peut être utilisé comme montré dans la figure ci-dessous, par exemple avec un ventilateur de PC dans un boîtier standard. Typiquement, ce genre de moteur s'alimente en 12 V et peut dissiper 1 ou 2 watts. Le transistor EMOSFET ZVN4206A pourrait convenir avec une telle charge puisqu''il peut conduire un courant jusqu'à 600 mA en continu et 8 A en pointe (avec Vdd = 12 V CC).

Image non disponible
Circuit de pilotage d'un moteur de ventilateur avec un transistor EMOSFET (NDLR Mais où est passée la résistance de base ?)

Préparez un circuit de pilotage de moteur en prototype en lieu et place du circuit de pilotage de LED précédent, le connecteur 6 de l'Arduino est conservé pour le pilotage (en mettant de côté provisoirement le circuit de pilotage de LED afin d'y revenir dessus plus tard). Aucune modification du code n'est nécessaire. Une fois le circuit connecté, la vitesse du moteur devrait maintenant varier selon la position du potentiomètre. (NDLR Un tel moteur filtre les hautes fréquences et se comporte comme s'il était alimenté en continu à la tension moyenne déterminée par la position du curseur du potentiomètre.)

Défi

Parfois, on a besoin d'un retour visuel sur la valeur d'une variable, de réaliser un afficheur en quelque sorte. Dans ce cas, on peut réaliser un simple bargraphe à LED pour indiquer la vitesse du moteur, plus la vitesse est élevée et plus il y a de barres allumées. Inutile de réinventer la roue puisqu'un tel dispositif a déjà été réalisé précédemment. Il suffit d'adapter la fonction lightLEDsBar() de l'exercice sur les entrées analogiquesAffichage à LED de l'Arduino. Vous aurez besoin d'un circuit relié au port B de l'Arduino pour piloter les quatre LED.

Finalement, vous pouvez fixer la vitesse du moteur en fonction d'une variable environnementale comme la température ou la luminosité ambiante plutôt qu'utiliser un potentiomètre actionné manuellement. Le potentiomètre peut être remplacé par un simple capteur, tel un LM34 pour acquérir la température, ou bien par une photorésistance avec une résistance pour former un diviseur de tension et acquérir le niveau de luminosité.

Il sera relativement simple et sans danger de faire varier aux extrêmes le niveau de luminosité en utilisant une lampe ou votre doigt pour éclairer ou obscurcir une photorésistance. En comparaison, la plage de variation de la tension d'un capteur de température analogique est plus restreinte et il faudra probablement adapter la plage de tension en conséquence. Vous pouvez aussi souhaiter éloigner le capteur de température des autres composants du circuit afin de les protéger des très hautes ou très basses températures. Par sécurité, n'utilisez pas de flamme en laboratoire pour créer de la chaleur !

Inclure votre code et un schéma de montage approprié, comme d'habitude, et joindre une description des tests réalisés.


précédentsommairesuivant
Si l’œil humain ne fonctionnait pas comme ça, nous ne pourrions pas avoir l'impression de visualiser une animation fluide et continue en regardant la télévision ou un film au cinéma alors que la fréquence des trames vidéo est de 30 et 24 images par seconde respectivement. La fréquence élevée à laquelle défilent les images trompe notre cerveau en créant l'illusion d'un mouvement continu.
Souvenez-vous, le courant qui traverse une inductance ne peut pas changer instantanément. Si le transistor se bloque, la tension aux bornes de l'inductance s'inverse et atteint des valeurs élevées, ce qui provoquera un pic de tension entre le collecteur et l'émetteur du transistor (lois de Kirchhoff). La diode (dite « Image non disponiblediode de roue libre ») telle qu'elle est placée sur la figure permet de limiter cette surtension et donc de protéger le transistor.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Licence Creative Commons
Le contenu de cet article est rédigé par James M. Fiore et est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 non transposé.
Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright © 2017 Developpez.com.