Mesure analogique

Posted on lun. 14 août 2023 in Datalogging, Arduino

Introduction

La première étape pour notre datalogger est de mesurer la valeur d’un fissuromètre de type potentiométrique. En le câblant comme un diviseur de tension, on pourra obtenir une sortie en tension proportionnelle à l'ouverture du capteur.

Le Convertisseur Analogique-Numérique (CAN)

Sans entrer dans les détails, la puce au cœur de l'Arduino UNO R3 intègre un convertisseur analogique-numérique (CAN, ou ADC en anglais pour Analog to Digital Converter) 10 bits.

Ce convertisseur est indispensable pour mesurer une tension : le microcontrôleur ne raisonne qu'en binaire, soit en zéros et uns. Il faut donc traduire la tension entre deux bornes du microcontrôleur (une valeur analogique) en une valeur numérique, et c'est le rôle du CAN.

Le nombre de bits d'un CAN détermine, toutes choses égales par ailleurs, la résolution que l'on peut attendre de notre mesure. Il va en effet encoder la valeur analogique sur une trame de N bits, soit 2^N valeurs possibles. Avec un CAN 10 bits, on a 1 024 valeurs possibles (de 0 à 1 023). Si l'on prend une tension d'entrée entre 0 et 5 V (tension d'alimentation de l'arduino via USB), on a grossièrement une équivalence 1 bit = 4.88 mV. Ceci veut également dire que, pour qu'une variation de tension soit détectée par le CAN, celle-ci doit être d'au moins 4.88 mV (en positif comme en négatif).

Lecture d’une mesure analogique

Avec le framework Arduino, la lecture d’une mesure analogique se fait via l’instruction analogRead()

int analog_reading;

void setup() {
  Serial.begin(9600);
}

void loop() {
  analog_reading = analogRead(A0);
  // les constantes A0, A1… A5 sont fournies par le framework Arduino pour identifier facilement la broche d’entrée.
  Serial.println(analog_reading);
  delay(2000);
}

Ce code donne bien le résultat attendu, à savoir une valeur entre 0 et 1023 (suivant la position du potentiomètre) toutes les 2 secondes.

0
0
283
284
964
962
1020
1020
1021

Maintenant, il faut essayer de se passer de la fonction delay() pour ne pas bloquer le μC pendant ces intervalles (pendant le delay(), l’ATMEGA ne peut plus rien faire). Ça se fait avec la fonction millis() qui renvoie le nombre de millisecondes écoulées depuis le lancement du programme (avec toutefois un rollover au bout d’un certain temps).

#define delay_millis 2000

int analog_reading;
long current_millis = 0;
long prev_millis = 0;
long diff_millis = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  current_millis = millis();
  diff_millis = current_millis - prev_millis;
  if(diff_millis > delay_millis) {
    analog_reading = analogRead(A0);
    Serial.println(analog_reading);
    prev_millis = current_millis;
  }
}

Les résultats sont toujours corrects.

Conversion des résultats

Maintenant il faut convertir les résultats en mm, puisque je veux mesurer l’ouverture d’un fissuromètre. Soit je passe par la fonction map, (mais qui ne peut renvoyer qu’un int), soit je fais un produit en croix. Pas mal plus simple pour moi d’utiliser map sur des micromètres: mon potentiomètre a 50 mm de course, soit une résolution (grossièrement) de 0,05 mm (le changement d’un bit de poids faible, LSB, indique un changement de 0,05 mm ou 50 μm).

uint16_t value_micros = 0;
void loop() {
// snip
if(diff_millis > delay_millis) {
    analog_reading = analogRead(A0);
    Serial.print(analog_reading);
    Serial.print("bin = ");
    value_micros = map(analog_reading, 0, 1023, 0, 50000);
    Serial.print(value_micros);
    Serial.println("μm");
    prev_millis = current_millis;
  }
}
548bin = 26783μm
768bin = 37536μm
1018bin = 49755μm
1023bin = 50000μm
1023bin = 50000μm
1022bin = 49951μm
674bin = 32942μm
0bin = 0μm

Développements ultérieurs

J’aimerais bien exploiter directement les registres de l’ATMEGA328P pour récupérer les valeurs converties de l’ADC sans passer par les fonctions du framework Arduino.