AVR – Chapitre 6 – Lire des valeurs analogiques (ADC)

Analogique vs. numérique

Les valeurs analogiques sont à opposer aux valeurs discrètes et logiques. Voici quelques comparaisons entre les deux mondes, avec des exemples pratiques :

Vision analogique Vision logique (numérique)
la porte est à peine ouverte (0.01) la porte est ouverte (1)
le réservoir est presque vide (0.1) le réservoir contient de l’essence (1)
le premier a parcouru 99% du chemin (0.99) le premier n’est pas encore arrivé (0)
il reste 17% de batterie (0.17) il reste de la batterie (1)

Oui, il est frustrant de ne pas atteindre le niveau de détails qui nous semble trivial au quotidien, au sein d’un programme purement logique.

L’ADC

Pour palier à ce manque, il a été ajouté aux microcontrôleurs un ou plusieurs canaux convertisseurs analogique vers numérique. Ceux-ci sont représentés par les broches ADC d’un microcontrôleur, pour « Analog to Digital Converter ».

L’ATTiny85 peut supporter jusqu’à 4 canaux ADC, chacun ayant une résolution de 10 bits, soit 1024 valeurs. Comme pour les PWM (Modulation de signal pulsé), leur utilisation dépend d’une horloge et d’un diviseur.

La théorie

Du point de vue de l’exécution, il s’agit d’approximer une tension inconnue (Vin) contenue entre 0 et une tension de référence (Vref).

Ainsi, le résultat est retourné sous la forme d’un entier entre 0 et 1023 :

ADC = [\frac{V_{IN} \times 1024}{V_{REF}}]

La configuration

Les registres de configuration de l’ADC sont ADMUX, ADCSRA et ADCSRB. Je vais faire l’impasse sur le registre ADCSRB, il permet des options avancées non essentielles pour le moment. Bien entendu, vous retrouverez tous ces registres dans la documentation (À partir de la page 134).

Le registre ADMUX

Bit 7 6 5 4 3 2 1 0
ADMUX REFS1 REFS0 ADLAR REFS2 MUX3 MUX2 MUX1 MUX0

Les bits REFS 2 à 0 déterminent la tension de référence Vref utilisée pour la comparaison.

REFS2 REFS1 REFS0 Vref
0 0 0 Vcc (i.e. la tension d’alimentation fournie au microcontrôleur)
0 0 1 Aref (i.e. tension externe fournie sur la broche Aref/PB0 du microcontrôleur)
0 1 0 1.1V
0 1 1 réservé (ne pas utiliser)
1 1 0 2.56V sans condensateur de découplage sur Aref/PB0
1 1 1 2.56V avec condensateur de découplage sur Aref/PB0

Les bits MUX 3 à 0 indiquent quel canal sélectionné (je ne parlerai ici que des canaux simples).

MUX3 MUX2 MUX1 MUX0 Canal
0 0 0 0 ADC0/PB5
0 0 0 1 ADC1/PB2
0 0 1 0 ADC2/PB4
0 0 1 1 ADC3/PB3
1 1 1 1 ADC4 il s’agit d’un capteur de température interne. Surprise !

Enfin le bit ADLAR indique l’alignement du résultat (1 pour gauche, 0 pour droite).

Le registre ADCSRA

Il s’agit du registre de contrôle, qui va permettre de démarrer la conversion et de savoir quand celle-ci est terminée.

Bit 7 6 5 4 3 2 1 0
ADCSRA ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0

Les bits ADPS 2 à 0 configure le diviseur (page 136 de la documentation). Le bit ADEN doit être à 1 pour que la conversion puisse fonctionner, mais ceci ne la démarre pas.

Passer le bit ADSC à 1 démarre la conversion. Il repasse à zéro dès que celle-ci est finie.

Le bit ADIE permet de déclencher une interruption lors de la fin d’une conversion, et le bit ADIF témoigne de la fin de la conversion. Dans le cas d’une utilisation sans interruption il est important de le positionner à 1 à la fin de la boucle, sinon la lecture restera bloquée sur la même valeur. Lors de l’utilisation de l’interruption, le chargement de sa procédure réinitialisera automatiquement ADIF, il n’y a donc plus besoin d’y toucher.

Le résultat

Puisqu’il s’agit d’un convertisseur 10 bits, il n’est pas possible de rendre le résultat sur un seul registre de 8 bits. Il y a donc deux façons d’organiser le résultat :

  • aligné à gauche (ADLAR = 1) : les 8 bits les plus forts sont dans le registre haut, et les 2 derniers bits dans le registre bas
    Bit 7 6 5 4 3 2 1 0
    ADCH ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2
    ADCL ADC1 ADC0 -   -     -    -     -      -
  • aligné à droite (ADLAR = 0) : les 2 bits les plus forts sont dans le registre haut, et les 8 derniers bits dans le registre bas
    Bit 7 6 5 4 3 2 1 0
    ADCH -   -     -    -     -      -    ADC9 ADC8
    ADCL ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0

Pour choisir quelle format vous sied le mieux, l’alignement à gauche permet de comparer rapidement le résultat sur 8 bit avec une précision moyenne, alors que l’alignement à droite offre une meilleure précision mais contraint à l’utilisation d’un entier codé sur 16 bits (cf. exemple plus loin).

 Un exemple simple : la photorésistance

Comme vous le savez surement, la photorésistance est un composant électronique à deux pôles, dont la résistance dépend de la luminosité ambiante. Voici un schéma pour la mettre en œuvre :

adc_schem

La résistance R3 est à prévoir en fonction de la photorésistance R1. Celles-ci étant montées en diviseur de tension, on mesurera donc une tension comprise entre :

\frac{R_3}{R_{1}_{MAX} + R_{3}} \times V_{REF} et \frac{R_3}{R_{1}_{MIN} + R_{3}} \times V_{REF}

Pour ma part, j’ai utilisé une résistance R3 de 4,7kΩ et une résistance R1 de 20kΩ, sur un circuit de 5V soit :

\frac{4.7k}{20k + 4.7k} \times 5 \simeq 1V et \frac{4.7k}{0 + 4.7k} \times 5 = 5V

Ainsi, la valeur retournée par l’ADC devrait être comprise entre 205 et 1023.

Le but ici est d’activer la diode dès que la photorésistance R1 atteint un certain seuil (i.e. dès qu’il fait trop sombre), et de l’éteindre dès qu’on y voit suffisamment clair, à la manière de l’éclairage public qui s’allume à la tombée de la nuit, et s’éteint quand le soleil brille. On laissera une marge entre les deux pour éviter un va-et-vient lors de la pénombre. Il faudra veiller également à ce que la diode ne soit pas orienté vers la résistance pour ne pas fausser sa mesure.

 

Pour aller plus loin

Je n’ai présenté ici l’utilisation que pour un seul canal simple, mais il est assez facile d’en utiliser plusieurs à la suite ; le choix du canal se faisant avec le registre ADMUX, il est facile de reconfigurer les bits 3 à 0 en fonction du canal désiré, à la fin de l’interruption (juste avant la ligne ADCSRA |= (1 << ADSC); ).

Il est également possible de ne pas utiliser les interruptions. Dans ce cas, il est nécessaire d’ajouter la ligne suivante une fois la valeur lue, au risque de voir la conversion retourner toujours le même résultat :

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*