ESP32 PWM PINS
Con Arduino IDE e la scheda ESP32 la funzione analogWrite() lavora in modo standard, tuttavia disponiamo di nuove funzioni più flessibili che ci permettono di configurare parametri come la frequenza e risoluzione del segnale PWM generato.
Se una frequenza di 1000Hz e risoluzione di 8-bit ci bastano possiamo usare analogWrite() come abbiamo sempre fatto. In caso contrario qui a seguire vediamo le nuove API per configurare e gestire il generatore di PWM.
Quali sono i pins PWM su ESP32?
A differenza delle board arduino UNO, NANO, MEGA ecc che hanno un numero limitato di pin PWM, su ESP32 tutti i pin possono essere collegati ad un canale PWM, tranne quei pin specificati "only input" che sono D35(GPIO35), D34(GPIO34), VN(GPIO39) e VP(GPIO36). Abbiamo a disposizione però solo 16 canali PWM e ci sono 21 pins ed ognuno lo possiamo assegnare ai 16 canali del generatore PWM. Come vedremo è possibile assegnare ad un canale PWM più di un pin se necessario.
Le API ledc
Tre sono le principali funzioni da conoscere: ledcSetup(),
ledcAttachPin() e
ledcWrite(). Qui di seguito sono documentate tutte con tanto di esempio al simulatore
online wokwi.
ledcSetup()
Questa funzione è da chiamare nel setup() per configurare il generatore PWM. Essa prende 3 argomenti descritti di seguito:
- ch - è il canale, ci sono 16 canali da 0÷15 per ESP32.
- freq - è la frequenza del segnale PWM.
- res - è la risoluzione espressa in bit: 8, 9, 10 ecc. 1÷14-bit (1÷20-bit per ESP32).
-
Restituisce la frequenza
freq se la
configurazione è andata a buon fine, diversamente restituisce 0 ad indicare
che nulla è stato configurato.
Esempio:
ledcSetup(0, 1000, 8); // canale 0, f = 1000Hz, risoluzione 8-bit
ledcAttachPin()
Tutti i pin possono generare un segnle PWM, ad eccezione di: GPIO34,
GPIO35,
GPIO36
e
GPIO39. Questa funzione serve ad assegnare il
pin
al canale
ch. Vedi anche
ledcDetachPin().
- pin - qualunque pin ad eccezione di: GPIO34, GPIO35, GPIO36 e GPIO39.
- ch è il canale usato prima nella funzione ledcSetup().
Esempio:
Questo esempio mette in evidenza il fatto che più pin possono essere associati
ad un canale.
ledcWrite()
Attenzione che adesso per modificare il pwm non dobbiamo agire sul pin ma sul
canale che abbiamo in precedenza associato al pin tramite la funzione
ledcAttachPin().
- ch è il canale a cui abbiamo associato il pin.
- pwmValue è il valore che vogliamo dare al PWM, sarà nel range 0÷255 se abbiamo configurato la risoluzione a 8-bit.
Esempio:
ledcWrite(0, 127); // assegna un PWM di valore 127 al canale 0
ledcDetachPin()
Dopo avere scollegato il pin dal canale PWM lo possiamo usare normalmente come un GPIO. Vedi ledcAttachPin().
- pin è il pin da scollegare dal canale a cui era connesso.
Esempio:
ledcDetachPin(10); // scollega pin 10 dal canale a cui era connesso
ledcChangeFrequency()
Questa funzione è simile a ledcSetup(). Essa permette di modificare la frequenza e risoluzione del segnale PWM generato dal canale ch:
- ch - è il canale, ci sono 16 canali da 0÷15 per ESP32.
- freq - è la frequenza del segnale PWM.
- res - è la risoluzione espressa in bit: 8, 9, 10 ecc. 1÷14-bit (1÷20-bit per ESP32).
-
Restituisce la frequenza
freq se la
configurazione è andata a buon fine, diversamente restituisce 0 ad indicare
che nulla è stato configurato.
Esempio:
ledcRead()
La funzione è l'opposto di ledcWrite(). Essa restituisce il valore del PWM assegnato al canale ch tramite ledcWrite().
ledcReadFreq()
La funzione restituisce la frequenza a cui lavora il canale ch configurato in precedenza tramite ledcSetup() o ledcChangeFrequency().
ledcWriteTone()
Questa funzione genera un segnale PWM sul canale ch, alla frequenza freq con un duty cycle del 50%.
- ch - è il canale, ci sono 16 canali da 0÷15 per ESP32.
- freq - è la frequenza del segnale PWM.
-
Restituisce la frequenza
freq se la
configurazione è andata a buon fine, diversamente restituisce 0 ad indicare
che nulla è stato configurato.
Esempio:
ledcWriteNote()
Questa funzione opera in modo simile alla funzione ledcWriteTone() ma al posto di specificare la frequenza specifichiamo la nota e l'ottava.
- ch - è il canale, ci sono 16 canali da 0÷15 per ESP32.
- note - è una delle note specificate in note_t type.
- oct è l'ottava tra 1 e 8.
- Restituisce la frequenza
freq se la
configurazione è andata a buon fine. diversamente restituisce 0 ad indicare
che nulla è stato configurato.
Esempio:
Uno sketch di esempio
Lo sketch di esempio si limita ad incrementare il pwm disponibile sui pins 19
e 21 entrambe assegnati al canale 0. Ricordiamo che al massimo ci sono 16
canali disponibile per cui al massimo possiamo avere 16 pin PWM indipendenti. Per comodità il codice viene scritto nella funzione setup() e voi dovete solo aggiungere la funzione loop() vuota.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #define LEDBLUE 21 #define LEDRED 19 void setup() { Serial.begin(115200); double result = ledcSetup(0, 875, 11); // ch 0, f 875Hz, res 11-bit if (!result) Serial.println("errore"); Serial.println(result); ledcAttachPin(LEDRED, 0); // attach LEDRED on ch 0 ledcAttachPin(LEDBLUE, 0); // attach LEDBLUE on ch 0 for (uint16_t i=0; i<2048; i++) { delay(15); ledcWrite(0, i); if (i == 2047) Serial.println("Ok"); } } |
La riga 6 configura il canale 0 del generatore PWM. La riga 7 verifica che la configurazione richiesta sia andata a buon fine, diversamente stampa la scritta errore. La riga 8 stampa la variabile result che in questo caso vale 874 anziché 875Hz come specificato. Alle righe 10 e 11 assegniamo al canale 0 i pin 19 e 21.
Il ciclo for (riga 13÷17) incrementa la variabile i ogni 15 millesimi di secondo, fino a che il valore di i è uguale al massimo valore permesso dalla risoluzione a 11-bit cioè 2047 e quindi stampa OK sul terminale.
Lo sketch al simulatore wokwi lo trovate cliccando il seguente link: esp32_pwm.ino.
Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale