Guides Arduino

Potentiomètre Arduino PWM : Contrôler une LED, un Servo et un Moteur

Maîtrisez le potentiomètre Arduino et le PWM : ADC 10-bit, map(), filtrage, 4 projets concrets (LED, servo, moteur, sélecteur) et upgrade ADS1115.

5 avril 202611 min de lectureÉquipe Didactico

Un soir d’octobre 2024, un étudiant INSAT m’envoie une vidéo : sa LED censée gradiente proprement clignote nerveusement à chaque rotation du potentiomètre. Le code semble correct, le câblage aussi. Sur l’oscilloscope, je vois immédiatement le coupable : un signal analogique parfaitement propre… transformé en sortie PWM qui saute de 5 unités à 23 puis revient à 7. Pas de moyenne glissante, pas de filtrage, pas de zone morte. Le potentiomètre est sans doute le composant le plus simple de l’électronique — une résistance variable à trois pattes — et pourtant 80 % des débutants l’utilisent mal. Dans ce guide complet, on va voir comment lire un potentiomètre proprement, comprendre le PWM Arduino jusque dans ses fréquences cachées, et construire quatre projets concrets : LED gradable, vitesse de servo, vitesse de moteur DC, et sélecteur de mode à 5 positions.

1. Le potentiomètre, résistance variable à 3 pattes

Un potentiomètre est techniquement un diviseur de tension réglable. Trois pattes : deux extrémités (souvent notées 1 et 3) et un curseur central (patte 2, le “wiper”). Quand on tourne, le curseur se déplace le long d’une piste résistive, modifiant le rapport de division.

     +5V  ----+
              |
             [1]
              |  Piste resistive
              .       (10 k typique)
              .   <----- Curseur sortant
              .         vers Arduino A0
              |
             [3]
              |
     GND  ----+

Si le curseur est au milieu, on lit 2,5 V à la patte 2. À fond à gauche, 0 V. À fond à droite, 5 V. C’est ce signal continu et variable que l’Arduino convertit en nombre.

2. Types de potentiomètres

Type Caractéristique Usage typique Prix Tunisie
Rotatif linéaire (B) Variation proportionnelle Réglage générique, débutants 1 – 2 DT
Rotatif logarithmique (A) Variation logarithmique Volume audio 1,5 – 3 DT
Linéaire slider Curseur droit Mixage audio, animatronique 3 – 6 DT
Multi-tours (10/20 tours) Précision haute Calibration laboratoire 5 – 12 DT
Trimmer Petit, ajustement unique Calibration interne d’un PCB 0,3 – 0,8 DT
Numérique I2C/SPI Pilotable par code Auto-calibration, télécommande 8 – 20 DT

Pour 90 % des projets Arduino, prenez un potentiomètre rotatif linéaire B10K (10 kΩ). C’est le standard universel.

3. L’ADC 10-bit d’Arduino expliqué

Le microcontrôleur ATmega328P de l’Arduino UNO intègre un convertisseur analogique-numérique 10 bits. Cela signifie qu’il transforme une tension continue 0-5 V en un entier compris entre 0 et 1023 (2^10 = 1024 niveaux). Précision théorique : 5 V / 1024 = 4,88 mV par pas.

int valeur = analogRead(A0);  // 0 a 1023

Sur un ESP32, l’ADC est 12 bits (0 à 4095, 0,80 mV par pas) — quatre fois plus précis. Sur un Arduino Due, c’est aussi 12 bits.

Limites de l’ADC interne

L’ADC d’Arduino UNO partage son convertisseur entre toutes les broches analogiques et présente du bruit (typiquement ±2 LSB). Pour des mesures précises (cellule de charge, capteur de force), passez à un ADS1115 (16 bits, ±0,1 % linéarité) que nous traitons en section 8.

Vitesse d’analogRead() : environ 100 µs par lecture, soit 10 000 lectures par seconde maximum. Largement suffisant pour un potentiomètre tourné à la main.

4. Le PWM : fréquences, duty cycle et broches

Arduino ne sait pas générer un vrai signal analogique en sortie (pas de DAC sur UNO). Il triche en utilisant le PWM (Pulse Width Modulation) : il envoie un signal carré 0-5 V à fréquence fixe, mais en faisant varier le rapport temps HIGH / temps total (duty cycle) entre 0 % et 100 %. Le moyen d’une LED (ou la bobine d’un moteur) lisse ce signal et perçoit une intensité variable.

Duty 25%   ──┐    ┌───┐    ┌───┐    ┌──
            │    │   │    │   │    │
           HIGH LOW HIGH LOW HIGH LOW

Duty 75%   ──┐         ┌───────┐    ┌──
            │         │       │    │
          HIGH  LOW   HIGH    LOW  HIGH

La fonction analogWrite(broche, valeur) attend une valeur entre 0 (toujours LOW = 0 %) et 255 (toujours HIGH = 100 %). À ne pas confondre avec analogRead qui renvoie 0-1023.

Broches PWM sur Arduino UNO et leurs fréquences

Broches Timer Fréquence par défaut
D3, D11 Timer 2 490 Hz
D5, D6 Timer 0 980 Hz
D9, D10 Timer 1 490 Hz

Les broches D5 et D6 sont à 980 Hz car Timer 0 sert aussi à millis() et delay(). Si vous changez sa fréquence, vous cassez la mesure du temps. Pour un moteur DC, 490 Hz est parfois trop lent et donne un sifflement audible : utilisez plutôt D9/D10 et changez le prescaler du Timer 1 pour monter à 31 kHz (silencieux).

// Augmenter la frequence PWM des broches D9 et D10 a 31 kHz (silencieux)
TCCR1B = (TCCR1B & 0b11111000) | 0x01;

5. La fonction map() et ses pièges

Lecture potentiomètre = 0-1023. Sortie PWM = 0-255. Sortie servo = 0-180°. Pour convertir, on utilise map() :

int pot = analogRead(A0);            // 0-1023
int pwm = map(pot, 0, 1023, 0, 255); // 0-255
analogWrite(9, pwm);

Trois pièges courants :

  1. map() ne contraint pas : si pot = 1100 (lecture aberrante), pwm = 274. Toujours ajouter pwm = constrain(pwm, 0, 255); derrière.
  2. map() utilise des entiers : pour des valeurs flottantes, écrivez votre propre fonction mapFloat().
  3. map() inverse : map(pot, 0, 1023, 255, 0) inverse le sens — pratique si votre câblage est dans le mauvais sens.

6. Filtrer la lecture pour stabiliser

Une lecture brute oscille typiquement de ±2 LSB. Sur 1024 niveaux, ce n’est rien. Mais une fois mappé sur 0-180° (servo), ±2 LSB devient ±0,4°, soit un servo qui tremble en permanence — inacceptable. Trois techniques cumulables :

Moyenne glissante

const byte N = 8;
int buffer[N];
byte idx = 0;
long somme = 0;

int lirePot() {
  somme -= buffer[idx];
  buffer[idx] = analogRead(A0);
  somme += buffer[idx];
  idx = (idx + 1) % N;
  return somme / N;
}

Filtre exponentiel (plus économe en mémoire)

float potFiltre = 0;
const float ALPHA = 0.15;

void loop() {
  int brut = analogRead(A0);
  potFiltre = ALPHA * brut + (1 - ALPHA) * potFiltre;
}

Zone morte (hystérésis)

int dernier = -10;
void loop() {
  int actuel = analogRead(A0);
  if (abs(actuel - dernier) > 3) {  // 3 LSB de tolerance
    dernier = actuel;
    appliquerValeur(actuel);
  }
}
Recette anti-tremblement

Pour un servo piloté par potentiomètre : moyenne glissante sur 8 lectures + zone morte de 4 LSB + délai minimum de 30 ms entre deux écritures servo. Vous obtenez un mouvement parfaitement stable. C’est la recette que nous appliquons sur les bras robotiques au FabLab Sfax.

7. Quatre projets complets

Projet 1 — LED gradable proprement

const byte POT = A0;
const byte LED = 9;

float valFiltree = 0;

void setup() {}

void loop() {
  int brut = analogRead(POT);
  valFiltree = 0.2 * brut + 0.8 * valFiltree;
  int pwm = map((int)valFiltree, 0, 1023, 0, 255);
  analogWrite(LED, pwm);
  delay(15);
}

Pour rendre la luminosité perçue linéaire (l’œil voit en logarithmique), appliquez une courbe gamma :

int pwm = pow(valFiltree / 1023.0, 2.2) * 255;

Projet 2 — Vitesse et position d’un servo SG90

#include <Servo.h>
Servo srv;
const byte POT = A0;

void setup() {
  srv.attach(9);
}

void loop() {
  static long somme = 0;
  somme = somme - (somme >> 3) + analogRead(POT);
  int filtre = somme >> 3;  // moyenne sur 8
  int angle = map(filtre, 0, 1023, 0, 180);
  srv.write(angle);
  delay(20);
}

Projet 3 — Vitesse moteur DC via L298N

Câblage : potentiomètre sur A0, ENA du L298N sur D9 (PWM), IN1 sur D7, IN2 sur D8. Bouton sur D4 inverse le sens.

const byte POT = A0;
const byte ENA = 9;
const byte IN1 = 7;
const byte IN2 = 8;
const byte BTN_SENS = 4;
bool avant = true;

void setup() {
  pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(BTN_SENS, INPUT_PULLUP);
  // PWM 31 kHz silencieux sur D9/D10
  TCCR1B = (TCCR1B & 0b11111000) | 0x01;
}

void loop() {
  if (digitalRead(BTN_SENS) == LOW) {
    avant = !avant;
    delay(200);  // anti-rebond grossier
  }
  digitalWrite(IN1,  avant ? HIGH : LOW);
  digitalWrite(IN2, !avant ? HIGH : LOW);

  int pot = analogRead(POT);
  int pwm = map(pot, 0, 1023, 0, 255);
  if (pwm < 30) pwm = 0;  // zone morte demarrage moteur
  analogWrite(ENA, pwm);
}

Projet 4 — Sélecteur de mode à 5 positions

Un seul potentiomètre = 5 modes distincts pour un projet (Stop / Lent / Normal / Rapide / Turbo).

byte modeActuel = 99;

void loop() {
  int pot = analogRead(A0);
  byte mode;
  if (pot < 200)        mode = 0;  // Stop
  else if (pot < 410)   mode = 1;  // Lent
  else if (pot < 615)   mode = 2;  // Normal
  else if (pot < 820)   mode = 3;  // Rapide
  else                   mode = 4;  // Turbo

  if (mode != modeActuel) {
    modeActuel = mode;
    appliquerMode(mode);
    Serial.print("Mode "); Serial.println(mode);
  }
}

void appliquerMode(byte m) {
  static const byte vitesses[5] = {0, 80, 150, 200, 255};
  analogWrite(9, vitesses[m]);
}
🎛️
PACK DEBUTANT

Composants Arduino + Potentiomètres

Lot de potentiomètres B10K, breadboard 830 points, LEDs RGB, résistances. Le pack idéal pour démarrer vos projets PWM avec Arduino UNO ou Elegoo UNO R3.

Voir les composants →

8. Upgrade pro : ADS1115 16-bit I2C

Quand 10 bits ne suffisent plus (cellule de charge, capteur de pH, mesures différentielles précises), passez à l’ADS1115 de Texas Instruments. Quatre canaux 16 bits différentiels, communication I2C, jusqu’à 860 échantillons/seconde, PGA intégré (gain réglable de 2/3 à 16). Précision pratique : ±0,01 %.

#include <Wire.h>
#include <Adafruit_ADS1X15.h>

Adafruit_ADS1115 ads;

void setup() {
  Serial.begin(115200);
  if (!ads.begin()) {
    Serial.println("ADS1115 introuvable");
    while (1);
  }
  ads.setGain(GAIN_ONE);  // +/-4.096V, 1 LSB = 0.125mV
}

void loop() {
  int16_t v = ads.readADC_SingleEnded(0);  // 0-32767 (en mode unipolaire)
  float volts = ads.computeVolts(v);
  Serial.print(volts, 4); Serial.println(" V");
  delay(100);
}

Au FabLab Sfax, nous utilisons l’ADS1115 systématiquement pour les projets de PFE en mesure de précision : mesure de tension de pile à hydrogène, capteur de pression différentielle, électrode pH-mètre. Disponible chez Didactico.

FAQ — Potentiomètre Arduino PWM

Quelle valeur de potentiomètre choisir : 1k, 10k ou 100k ?

Pour Arduino, le standard universel est 10 kΩ. Trop faible (1 kΩ) consomme inutilement de courant à travers le diviseur. Trop élevé (100 kΩ et plus) rend la lecture plus sensible au bruit (l’impédance d’entrée de l’ADC ne lit plus aussi proprement). 10 kΩ est le compromis idéal pour 95 % des projets.

Pourquoi ma lecture saute entre deux valeurs ?

L’ADC d’Arduino UNO présente naturellement un bruit de ±2 LSB. C’est normal. Trois solutions : (1) ajoutez un condensateur de 100 nF entre le wiper et GND pour lisser le signal ; (2) implémentez une moyenne glissante sur 8 lectures dans le code ; (3) ajoutez une zone morte (hystérésis) de 3-4 LSB avant d’appliquer la valeur.

analogWrite() fonctionne-t-il sur toutes les broches Arduino ?

Non. Sur Arduino UNO, seules les broches 3, 5, 6, 9, 10 et 11 supportent analogWrite() matériel (PWM). Sur Mega : 13 broches. Sur Nano : identique à UNO. Sur ESP32 : presque toutes les broches via les canaux LEDC. Pour faire du PWM logiciel sur les autres broches, utilisez la librairie SoftPWM (mais qualité moindre, consomme du CPU).

Comment faire du PWM silencieux sur un moteur DC ?

La fréquence par défaut (490 ou 980 Hz) est dans le spectre audible et fait “chanter” certains moteurs. Solution : changer le prescaler du Timer 1 pour pousser les broches D9 et D10 à 31 kHz : TCCR1B = (TCCR1B & 0b11111000) | 0x01;. Le sifflement disparaît et le rendement du moteur s’améliore.

Puis-je remplacer un potentiomètre par un signal externe ?

Oui. Tout signal continu 0-5 V est lisible par analogRead() : capteur LM35 (température), photorésistance LDR (luminosité), capteur de courant ACS712 (jusqu’à 30 A), sortie d’un autre Arduino, signal d’un PLC industriel via opto-isolateur. Vérifiez juste que la tension ne dépasse jamais 5 V (5,5 V endommage l’ATmega328P).

Quelle différence entre ADC 10-bit (Arduino) et 16-bit (ADS1115) ?

10 bits = 1024 niveaux, 1 LSB = 4,88 mV. 16 bits = 65 536 niveaux, 1 LSB = 0,125 mV (avec gain 1 sur ADS1115). En pratique, l’Arduino est suffisant pour potentiomètres, joysticks, photorésistances. L’ADS1115 devient indispensable pour des mesures fines (cellule de charge, thermocouple amplifié, pH-mètre), des mesures différentielles, ou des mesures précises de tension/courant.

Un joystick Arduino, c’est juste deux potentiomètres ?

Exactement. Un joystick analogique type Arduino (KY-023) contient deux potentiomètres 10K à 90° l’un de l’autre + un bouton-poussoir activé par appui sur le manche. Lecture : x = analogRead(A0); y = analogRead(A1); bouton = digitalRead(2);. Tout ce que vous avez appris sur le potentiomètre s’applique : filtrage, zone morte au centre (~512 ±20), map() vers la plage utile.

Conclusion

Le potentiomètre est le composant qui m’a fait comprendre, il y a des années, le concept de signal analogique, de quantification, de bruit et de filtrage. Quatre concepts qui resservent ensuite partout : capteurs, audio, mesure, contrôle. Maîtrisez la lecture propre d’un potentiomètre, le PWM en sortie, la fonction map() et un bon filtre, et vous avez les briques de 70 % des projets Arduino.

Chez Didactico Tunisie, basée à Sfax, nous tenons en stock permanent les potentiomètres B10K rotatifs, sliders linéaires, multi-tours pour calibration, trimmers, joysticks analogiques KY-023, ADS1115, drivers L298N, Arduino UNO R3, Elegoo UNO, Raspberry Pi et tout l’écosystème Espressif (ESP32, ESP8266). Livraison 24-48h dans toute la Tunisie pour les étudiants ENIT, INSAT, ISBS, ISET et ESPRIT. Pour aller plus loin, lisez notre guide Arduino UNO R3 complet avec 10 projets.

Vous avez un projet PWM en tête ? Décrivez-le dans les commentaires, je sélectionnerai les plus intéressants pour les prochains tutoriels FabLab Sfax.

🛒 Matériel nécessaire pour ce guide

Tout le matériel de ce tutoriel est disponible chez Didactico — livraison 24-48h partout en Tunisie, paiement à la livraison.

Voir toute la catégorie « Composants électroniques » →

📘 Guides liés : Bouton Poussoir Arduino : Débounce, Pull-up et Interruptions en Tunisie · Feu de Signalisation LED Arduino : du Tricolore au Carrefour Intelligent