L’Arduino est aussi un voltmètre

L’Arduino et son microcontrôleur ATmega328 de chez Microchip ont déjà été présentés sur ce site. Parmi ses nombreuses fonctions, ce microcontrôleur intègre un convertisseur ADC à 10 bits, c’est à dire qu’il peut convertir une tension en entrée sur une échelle de 0 à 1023.

La conception de ce convertisseur permet de lui faire mesurer une tension inconnue, par rapport à un intervalle connu (sa tension de référence). On peut ainsi mesurer sur une plage de 0 à 5v (tension d’alimentation) ou par rapport à une tension de référence interne de 1,1v. On peut aussi utiliser une tension externe (Vref) que l’on peut fixer librement (dans une certaine limite quand même).

Analyse d’un convertisseur Analogique

Voici un schéma de ce bloc de conversion analogique vers numérique (Analog Digital Converter) tiré de la documentation du constructeur :

Assez étonnamment, dans ce schéma on trouve plusieurs composants, mais pas de convertisseur ADC. Au contraire, on y trouve un convertisseur DAC (convertisseur numérique vers analogique) ; ce n’est pas une faute de frappe !

Pour la petite histoire, un de mes profs de DUT m’avait affirmé doctement que :

Tout ce qui se trouve dans une boucle négative d’un ampli voit sa fonction inversée…

On a ici une application de ce principe ! Regarder le trio « 10-Bit DAC », « Sample and Hold Comparator » et « Conversion Logic » qui collaborent pour assurer cette fonction de convertisseur analogique vers numérique.

Voici le principe de fonctionnement de cet ensemble :

  1. La logique de conversion applique une valeur numérique 0 au DAC qui lui produit une tension de sortie nulle aussi ;
  2. Le comparateur fait la soustraction analogique entre la sortie (nulle) du DAC et la tension à mesurer provenant du multiplexeur d’entrées ;
  3. Si la sortie du comparateur est positive (niveau HAUT), la logique va s’incrémenter de 1 et va appliquer cette nouvelle valeur au DAC ; retour au pas 2 ;
    Si la sortie du comparateur est négative (niveau BAS), la logique a dépassée la valeur de la tension a mesurer et la conversion est terminée.

Et voilà ! On vient de réaliser une fonction de conversion successive d’une tension analogique vers une valeur numérique. Dans la pratique, le système est un peu plus optimisé et utilisera probablement une progression par dichotomie.

On peut imaginer que ce type de conversion prend du temps et l’on voit que le schéma initial que la logique est d’ailleurs contrôlée par une horloge fournie par le Prescaler. D’après la documentation, il faut effectivement compter entre 13 et 25 temps d’horloge pour réaliser une conversion de 10 bits.

Il existe d’autres logiques de conversion beaucoup plus rapides mais surtout coûteuses, comme les convertisseurs « flash » (Wikipedia.org Convertisseur analogique-numérique).

Un voltmètre

Revenons à notre application pour laquelle nous souhaitons mesurer la tension de l’alimentation de l’Arduino. Malheureusement, on ne peut pas mesurer une tension avec une référence inférieure (la référence interne est à 1,1v seulement). Par contre on peut très bien faire l’inverse, c’est à dire mesurer la tension de référence de 1,1v avec comme intervalle la tension d’alimentation ; l’erreur de la valeur lue (différente de 1,1v) permettra d’estimer la tension d’alimentation réellement utilisée.

La documentation du constructeur donne :

      Vin * 1024
ADC = -----------
         Vref

Si l’on utilise Vin = 1.1v et Vref = Valim, on obtient après conversion :
Valim = Vref = (Vin * 1024) / ADC

Il ne nous reste qu’à configurer le bloc convertisseur pour effectuer une conversion sur 10 bits de la tension d’alimentation. Je ne vais pas rentrer dans les détails, je préfère rédiger un article spécifique ultérieurement sur ce sujet.

Configuration des registres du bloc ADC

ADMUX – ADC Multiplexer Selection Register

  • AVcc with external capacitor at AREF pin : REFS1 = 0 ; REFS0 = 1
  • Single Ended Input 1.1V (Vbg) : MUX3..0 = 1110

ADCSRA – ADC Control and Status Register A

  • ADC Enable : ADEN = 1
  • ADC Start Conversion : ADSC = 0 (1 : pour lancer la conversion)
  • ADC Prescaler Selections : ADPS2:0 = 100 (Division Factor 16)

Note sur le diviseur (ADC Prescaler), la fréquence d’entrée de conversion ne doit pas dépasser 200 KHz pour avoir un résultat correct sur 10 bits. L’Arduino étant cadencé à 16 MHz, il faut diviser la fréquence au-moins par :

16 MHZ / 200 KHz = 8

ADCSRB – ADC Control and Status Register B

Tout à zéro.

Réduction du bruit pendant la conversion

Dans la documentation, il est recommandé de mettre le processeur en sommeil (ADC Noise Reduction mode) juste après avoir lancé la conversion. Le processeur est réveillé automatiquement à la fin de la conversion (sauf si une autre interruption se produit avant).

Pour le moment, je n’ai pas eu de succès pour réveiller le CPU en fin de conversion. On utilisera une boucle pour attendre la fin de la conversion.

Conversion et calculs

Nous voilà à la fin de la configuration du bloc convertisseur. Il ne reste plus qu’à le faire fonctionner.

Lancer la conversion :
Écrire dans ADCSRA, le bit ADSC à 1

Attendre la fin de la conversion :
Vérifier que le même bit ADSC retombe à 0.

Récupérer le résultat de la conversion :
Lire les 2 registres ADCL & ADCH, dans cet ordre, ADCL contenant les 8 bits de poids faible et ADCH les 2 derniers bits de poids fort.

Avec la formule Valim = (Vin * 1024) / ADC trouvée précédemment et en prenant Vin = 1.1 v, et sachant que 1,1 * 1024 = 11264 / 10 on obtient la tension d’alimentation (en décivolts) avec un division d’entiers :

const unsigned ADC = ADCL + ADCH * 256 ;
const unsigned VAlim = 11264 / ADC) ;

Précision

Il ne faut pas s’attendre quand même à une excellente précision de la mesure puisque le constructeur s’engage sur la tension de la diode bandgap dans un intervalle de 1,0 à 1,2v à 20°C, ce qui donne une erreur de +/- 10%.

Quand on consulte les graphiques de variation en fonction de la tension d’alimentation et en fonction de la température (du circuit intégré, pas ambiante), on se limite à une variation pour 30°C et entre 3,5 et 5,5v de l’ordre de 1,125 à 1,133v, ce qui donne un écart de 4mv et une valeur moyenne de 1.129v.

Une mesure de contrôle en fonctionnement permettrait de calculer la valeur réelle de la diode et d’affiner le calcul en remplaçant la valeur de 1,1v dans les formules.