Lisez des capteurs avec analogRead(), générez du PWM avec analogWrite() et maîtrisez la conversion analogique-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.
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.
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.
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() 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;
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
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é.
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).
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.
| Concept | Arduino | PIC12F683 |
|---|---|---|
| Lire une valeur analogique | analogRead(A0) | Configurer ADCON0, ADCON1, lancer conversion, lire ADRESH:ADRESL |
| Résolution ADC | 10 bits (0–1023) | 10 bits (0–1023) |
| Générer du PWM | analogWrite(9, 128) | Configurer CCP1CON, PR2, CCPR1L, TMR2 |
| Résolution PWM | 8 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.
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.