🎛️ Lectures analogiques & PWM

Lisez des capteurs avec analogRead(), générez du PWM avec analogWrite() et maîtrisez la conversion analogique-numérique

Analogique vs Numérique

Le monde physique est analogique : la température, la luminosité, la pression ou le son sont des grandeurs qui varient de manière continue. Un signal numérique, en revanche, ne connaît que deux états : 0 et 1 (LOW et HIGH).

Pour faire le lien entre ces deux mondes, l'Arduino Uno intègre un convertisseur analogique-numérique (ADC) qui transforme une tension analogique (0V à 5V) en une valeur numérique (0 à 1023). C'est grâce à ce convertisseur que votre Arduino peut « comprendre » un capteur de température, un potentiomètre ou une photorésistance.

📊 analogRead() — Lire une valeur analogique

L'Arduino Uno possède 6 entrées analogiques (A0 à A5) connectées au convertisseur ADC 10 bits de l'ATmega328P. La fonction analogRead() lit la tension sur une broche analogique et retourne un entier entre 0 et 1023 :

int valeur = analogRead(A0);  // Lit la broche A0 (0 à 1023)

// Convertir en tension
float tension = valeur * (5.0 / 1023.0);  // 0.0V à 5.0V

ℹ️ Résolution 10 bits : Avec 10 bits, l'ADC peut distinguer 210 = 1024 niveaux de tension différents. C'est suffisant pour la plupart des capteurs courants. Sur les PIC12F683 et PIC16F877A, l'ADC est également en 10 bits, la résolution est donc identique.

🎚️ Exemple : Lire un potentiomètre

Le potentiomètre est le composant analogique le plus simple à utiliser. C'est une résistance variable avec 3 broches : les deux extrémités sont connectées entre 5V et GND, et le curseur central fournit une tension variable de 0V à 5V en fonction de la rotation.

Câblage

Code

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

void loop() {
    int valeur = analogRead(A0);
    float tension = valeur * 5.0 / 1023.0;
    int pourcentage = map(valeur, 0, 1023, 0, 100);

    Serial.print("ADC: ");
    Serial.print(valeur);
    Serial.print("  Tension: ");
    Serial.print(tension, 2);
    Serial.print("V  Position: ");
    Serial.print(pourcentage);
    Serial.println("%");

    delay(200);
}

Ouvrez le moniteur série pour voir la valeur ADC, la tension et le pourcentage changer en temps réel quand vous tournez le potentiomètre.

🔧 La fonction map()

La fonction map() est extrêmement utile pour convertir une plage de valeurs en une autre. Elle effectue une interpolation linéaire :

long resultat = map(valeur, fromLow, fromHigh, toLow, toHigh);

// Exemples courants :
int pwm = map(analogVal, 0, 1023, 0, 255);     // ADC → PWM
int angle = map(analogVal, 0, 1023, 0, 180);   // ADC → angle servo
int temp = map(analogVal, 0, 1023, -40, 125);  // ADC → température

⚠️ Attention : map() travaille avec des entiers. Pour des conversions nécessitant des décimales (ex : tension en volts), utilisez le calcul flottant : float tension = valeur * 5.0 / 1023.0;

📈 analogWrite() — Générer un signal PWM

L'Arduino Uno ne possède pas de vrai convertisseur numérique-analogique (DAC). À la place, il utilise la modulation de largeur d'impulsion (PWM) pour simuler une tension analogique en sortie. La fonction analogWrite() génère un signal PWM sur les broches compatibles :

analogWrite(9, 0);     // 0% duty cycle → 0V moyen → LED éteinte
analogWrite(9, 64);    // 25% duty cycle → ~1.25V moyen
analogWrite(9, 127);   // 50% duty cycle → ~2.5V moyen
analogWrite(9, 191);   // 75% duty cycle → ~3.75V moyen
analogWrite(9, 255);   // 100% duty cycle → 5V continu → LED max

Qu'est-ce que le PWM ?

Le PWM (Pulse Width Modulation) est un signal carré dont on fait varier le rapport cyclique (duty cycle), c'est-à-dire le pourcentage de temps où le signal est à l'état haut. En alternant très rapidement entre 0V et 5V (490 fois par seconde), on obtient une tension « moyenne » proportionnelle au duty cycle. L'œil humain ne perçoit pas le clignotement rapide d'une LED en PWM, il voit simplement une variation de luminosité.

💡 Exemple : Contrôler la luminosité d'une LED

const int LED = 9;  // Broche PWM

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

void loop() {
    // Effet "respiration" : fade in puis fade out
    for (int i = 0; i <= 255; i++) {
        analogWrite(LED, i);
        delay(5);
    }
    for (int i = 255; i >= 0; i--) {
        analogWrite(LED, i);
        delay(5);
    }
}

Ce programme crée un effet de « respiration » : la LED augmente progressivement en luminosité puis diminue, en boucle. Chaque cycle complet dure environ 2.5 secondes (256 × 5 ms × 2).

🎛️ Combiner analogRead + analogWrite

L'une des applications les plus courantes est de lire un potentiomètre avec analogRead() et d'utiliser la valeur pour contrôler la luminosité d'une LED avec analogWrite() :

const int POT = A0;   // Potentiomètre
const int LED = 9;    // LED sur broche PWM

void setup() {
    pinMode(LED, OUTPUT);
    Serial.begin(9600);
}

void loop() {
    int lecture = analogRead(POT);          // 0–1023
    int luminosite = map(lecture, 0, 1023, 0, 255);  // → 0–255
    analogWrite(LED, luminosite);

    Serial.print("Pot: ");
    Serial.print(lecture);
    Serial.print("  LED: ");
    Serial.println(luminosite);
    delay(50);
}

Tournez le potentiomètre : la LED varie de complètement éteinte à pleine luminosité. C'est le même principe utilisé pour contrôler la vitesse d'un moteur DC ou la position d'un servomoteur.

📌 Comparaison avec les PIC

ConceptArduinoPIC12F683
Lire une valeur analogiqueanalogRead(A0)Configurer ADCON0, ADCON1, lancer conversion, lire ADRESH:ADRESL
Résolution ADC10 bits (0–1023)10 bits (0–1023)
Générer du PWManalogWrite(9, 128)Configurer CCP1CON, PR2, CCPR1L, TMR2
Résolution PWM8 bits (0–255)Jusqu'à 10 bits

On voit clairement l'avantage d'Arduino pour le prototypage rapide : une seule ligne de code remplace la configuration de 4 registres sur PIC. Mais comprendre les registres sous-jacents (voir nos tutoriels ADC et PWM PIC) donne une compréhension bien plus profonde.

⚡ Référence de tension (AREF)

Par défaut, l'ADC de l'Arduino utilise 5V comme tension de référence. Cela signifie que la pleine échelle (1023) correspond à 5V. Vous pouvez modifier cette référence pour augmenter la précision sur des tensions plus faibles :

analogReference(DEFAULT);    // 5V (par défaut)
analogReference(INTERNAL);   // 1.1V interne — plus précis pour petites tensions
analogReference(EXTERNAL);   // Tension appliquée sur la broche AREF

Avec la référence interne 1.1V, chaque incrément ADC représente environ 1.07 mV au lieu de 4.88 mV — presque 5 fois plus précis ! Utile pour les capteurs de température ou les mesures de batterie.