ESP32: PWM e dimming di LED e motori con LEDC

Pubblicato il 19/07/2026 ESP32

Accendere o spegnere un LED con digitalWrite() è il primo esercizio con qualunque microcontrollore. Il passo successivo — farlo diventare più o meno luminoso in modo graduale, o controllare la velocità di un motorino DC — richiede il PWM (Pulse Width Modulation): un segnale digitale che si accende e spegne molto rapidamente, dove la percentuale di tempo "acceso" (duty cycle) determina la potenza media percepita dal carico.

Perché LEDC e non un semplice delay

Si potrebbe simulare il PWM a mano con delay() o delayMicroseconds(), ma occuperebbe la CPU al 100% e non reggerebbe frequenze utili per motori o audio. L'ESP32 ha invece un periferico hardware dedicato, LEDC (LED Control), che genera il segnale in autonomia: la CPU imposta i parametri una volta sola e il segnale continua a uscire dal pin senza ulteriore intervento del programma.

Configurazione base (Arduino core 3.x)

const int PIN_LED = 5;
const int FREQ_HZ = 5000;   // frequenza del PWM
const int RISOLUZIONE = 8;  // bit: 8 bit = valori 0-255

void setup() {
  ledcAttach(PIN_LED, FREQ_HZ, RISOLUZIONE);
}

void loop() {
  for (int duty = 0; duty <= 255; duty++) {
    ledcWrite(PIN_LED, duty);
    delay(10);
  }
  for (int duty = 255; duty >= 0; duty--) {
    ledcWrite(PIN_LED, duty);
    delay(10);
  }
}

Con questo sketch il LED si accende e spegne gradualmente in un effetto "respiro" continuo, senza che la CPU debba gestire il timing del singolo impulso: se ne occupa il periferico hardware.

Scegliere frequenza e risoluzione giuste

  • LED: 1-5 kHz bastano, l'occhio umano non percepisce lo sfarfallio già sopra i 100 Hz circa; risoluzioni a 8 bit (256 livelli) sono più che sufficienti per una dissolvenza fluida.
  • Motori DC piccoli: 20-25 kHz evita il fastidioso fischio udibile che si sente a frequenze più basse (il motore stesso "canta" alla frequenza del PWM se questa cade nel range udibile).
  • Servo motori: i servo standard non vogliono un PWM qualunque, ma un impulso specifico ripetuto ogni 20ms con larghezza tra 1 e 2 ms — per quello conviene usare la libreria ESP32Servo invece di configurare LEDC a mano, gestisce automaticamente i parametri corretti.

Attenzione al limite corrente dei pin GPIO

Il PWM controlla la potenza media, ma il pin dell'ESP32 può erogare al massimo circa 12-20mA in modo sicuro (dipende dal pin e dalla configurazione). Un motore DC anche piccolo assorbe molto di più: va sempre pilotato tramite un transistor o un driver dedicato (es. modulo con MOSFET, o driver L298N/DRV8871 per motori più grandi), mai collegato direttamente al pin GPIO. Il PWM va al gate/ingresso di controllo del driver, non al carico.

Un caso pratico: dimmer con controllo da web

Combinando LEDC con un piccolo web server (vedi il tutorial dedicato "ESP32 come Web Server") si ottiene un dimmer controllabile da smartphone in pochissimo codice:

server.on("/luminosita", HTTP_GET, [](AsyncWebServerRequest *request){
  if (request->hasParam("val")) {
    int val = request->getParam("val")->value().toInt();
    ledcWrite(PIN_LED, constrain(val, 0, 255));
  }
  request->send(200, "text/plain", "OK");
});

Un dettaglio da non trascurare: valida sempre l'input ricevuto (qui con constrain()) prima di scriverlo sul PWM — un valore fuori range non danneggia l'hardware LEDC in sé, ma è buona norma non fidarsi mai ciecamente di un parametro arrivato da rete.