Modificare frequenza del PWM di Arduino


Ciao,

in questo post vedremo come cambiare la frequenza del PWM di Arduino,
se volete potete vedere questo post come un'integrazione al precedente post sul PWM (dove invece abbiamo variato la luminosità di un led cambiando il duty cycle con la funzione "analogWrite").

Infatti in alcuni casi potrebbe essere necessario modificare l'alternanza tra segnale alto e basso del segnale (frequenza appunto), a causa del comportamento anomalo del dispositivo pilotato.






Cos'è la frequenza? Vediamolo in 2 parole.

Per prima cosa dobbiamo sapere cos'è il periodo. Il periodo è il tempo che impiega un'onda a compiere un'oscillazione e tornare alla situazione iniziale.
Ad esempio il periodo del segnale che vedete sopra è di 50 nanosecondi (semionda positiva + semionda negativa).

La frequenza è l'inverso del periodo, quindi in questo caso 1/50 nanosecondi = 0.02 gigaHertz ovvero 20 megaHertz.


Per default le frequenze del PWM sui pin di Arduino sono:
  • 976 Hz sui pin 5 e 6 (frequenza base 62500 Hz)
  • 488 Hz sui pin 9,10, 3, 11 (frequenza base 31250 Hz)

Queste frequenze sono ottenute dividendo le frequenze base (62500 e 31250 Hz) per 64.
Purtroppo non posso decidere la frequenza sui pin "a piacere" ma posso solo dividere le frequenze base per dei divisori fissi.


i divisori sono:

  • 1, 8, 64, 256, 1024 per i pin 5, 6, 9 e 10.
  • 1, 8, 32, 64, 128, 256 e 1024 per i pin 3 e 11.


Grazie a questo codice, presente sul sito Arduino.cc, è facilmente possibile modificare le frequenze agendo su 3 registri del micro (TCCR0B, TCCR1B, TCCR2B).
Il codice è abbastanza semplice, ma può sembrare un po' ostico per chi non conosce le operazioni a bit. (se volete approfondire qui un approfondimento sempre trovato sul sito ufficiale di Arduino)

Come spiegato nel codice linkato sopra, è molto rischioso modificare i divisori perchè "cambiamenti sui pin 3, 5, 6 e 11 possono bloccare le funzioni delay() e millis()" e che "cambiamenti sui pin 9 e 10 causeranno malfunzionamenti con la libreria Servo.

Ecco come utilizzarlo, mettete la funzione "setPwmFrequency" nel vostro codice, poi richiamatela dando come parametri il pin sul quale volete modificare la frequenza e il divisore per il quale volete dividere la frequenza base.

Ecco un esempio:




Ecco il segnale letto sul pin 11 del nostro Arduino:



Come potete vedere in basso a destra la frequenza letta è 488Hz (31250 diviso 64)

Proviamo ora a cambiare il divisore, è sufficiente cambiare la riga:
"setPwmFrequency(11, 64);"
ad esempio in:
"setPwmFrequency(11, 8);"

Ecco il risultato, la frequenza è cambiata ed ora possiamo leggere 3.91KHz (31250 diviso 8)



Questo è tutto!
Per qualsiasi domanda lascia pure un commento qui sotto.

Seguimi sulle mie pagine per rimanere sempre aggiornato sui nuovi post!

4 commenti:

  1. Grazie per la spiegazione esaustiva e sintetica al punto giusto.
    Vorrei capire come pilotare un BLDC inviando tre PWM sfasati di 120° tra loro.
    con la sua spiegazione riuscirei a modificare i 6 singoli PWM per i rispettivi stadi 3 Alti e 3 Bassi. ma non riesco a capire come stabilire i ritardi di partenza per i tre diversi segnali. ho letto qualcosa sui Prescaler etc ma di altri MCU, non Atmel.
    potrebbe aiutarmi, non pretendo altro che un indirizzamento ad altre fonti che spiegano come intervenire sui registri dall'IDe di Arduino.
    grazie mille
    Raffaele D'Antonio

    RispondiElimina
  2. ciao, ma il codice va messo tutto o solo la stringa? :
    {
    pinMode (11, OUTPUT); //setta la porta 11 come uscita
    setPwmFrequency(11, 64); //applica il divisore 64 sul timer del pin 11
    }

    RispondiElimina
    Risposte
    1. Ciao, va messo tutto, ovviamente se devi integrare il codice in un altro non puoi mettere 2 cicli loop ne 2 setup

      Elimina
  3. OK quindi li aggiungo ognuno nelle proprie sezioni però a me serve solo il pin 6 per un servo e il 2 per un contatto micron interruttore normalmente aperto

    RispondiElimina

Lascia un commento qui sotto, ti risponderò il prima possibile!

Altri Post