Aumentare la frequenza PWM.

Il microcontrollore dispone di diversi timer che possono svolgere diverse funzioni, in particolare generare un segnale PWM. Affinché il timer possa generare PWM, è necessario prima configurarlo modificando il registro del timer. Quando lavoriamo nell'IDE di Arduino, i timer vengono configurati a nostra insaputa nella libreria Arduino.h e ottengono effettivamente le impostazioni desiderate dagli sviluppatori. E queste impostazioni a volte non corrispondono ai nostri design: la frequenza PWM predefinita è bassa, le capacità dei timer non sono completamente utilizzate. Diamo un'occhiata al PWM standard dell'ATmega328 (Arduino UNO/Nano/Pro Mini):
Timer       Pin              Frequenza      Risoluzione
Timer0     D5 e D6      976 Hz            8 bit (0-255)
Timer 1    D9 e D10    488 Hz            8 bit (0-255)
Timer 2    D3 e D11    488 Hz            8 bit (0-255)
In effetti, tutti i timer possono facilmente emettere un segnale PWM a 64 kHz e il Timer 1 è generalmente a 16 bit e alla frequenza fornita da Arduino potrebbe funzionare con una risoluzione di 15 bit anziché 8, ovvero 32768 gradazioni di riempimento invece di 256. Allora perché tale ingiustizia? Il Timer 0 si occupa della temporizzazione ed è impostato per scorrere con precisione in millisecondi. E il resto dei timer viene semplicemente impostati su basso livello, in modo che utente non abbia problemi inutili.  Questo approccio è generalmente comprensibile, ma farebbero almeno un paio di funzioni standard per una frequenza più alta???.
Impostazione della frequenza PWM tramite registri.
il microcontrollore è configurato a basso livello tramite i registri, quindi la generazione PWM è configurata tramite i registri timer. Successivamente, troverai diversi "pezzi" di codice già pronti che devi solo inserire nel setup() e la frequenza PWM verrà riconfigurata (cambia prescaler e la modalità di funzionamento del timer). Puoi ancora lavorare con il segnale PWM usando la funzione analogWrite(), controllando il riempimento PWM sui pin standard.

Pin D5 e D6 (Timer 0) - 8 bit.
// Pin D5 e D6 - 62.5 kHz
TCCR0B = 0b00000001; // x1
TCCR0A = 0b00000011;  // fast pwm 
// Pin D5 e D6 - 31.4 kHz
TCCR0B = 0b00000001; // x1
TCCR0A = 0b00000001; // phase correct
// Pin D5 e D6 - 7.8 kHz
TCCR0B = 0b00000010; // x8
TCCR0A = 0b00000011; // fast pwm
//Pin D5 e D6 - 4 kHz
TCCR0B = 0b00000010; // x8
TCCR0A = 0b00000001; // phase correct
// Pin D5 e D6 - 976 Hz - predefinito
TCCR0B = 0b00000011; // x64
TCCR0A = 0b00000011; // fast pwm
// Pin D5 e D6 - 490 Hz
TCCR0B = 0b00000011; // x64
TCCR0A = 0b00000001; // phase correct
// Pin D5 e D6 - 244 Hz
TCCR0B = 0b00000100; // x256
TCCR0A = 0b00000011; // fast pwm
// Pin D5 e D6 - 122 Hz
TCCR0B = 0b00000100; // x256
TCCR0A = 0b00000001; // phase correct
//Pin D5 e D6 - 61 Hz
TCCR0B = 0b00000101; // x1024
TCCR0A = 0b00000011; // fast pwm
// Pin D5 e D6 - 30 Hz
TCCR0B = 0b00000101; // x1024
TCCR0A = 0b00000001; // phase correct
Importante! Quando si cambia la frequenza sui pin D5 e D6, si perderanno le funzioni di tempo (millis(), delay(), pulseIn(), setTimeout() e altre), non funzioneranno correttamente. Anche le biblioteche che li utilizzano smetteranno di funzionare!

Pin D9 e D10 (Timer 1) - 8 bit.
// Pin D9 e D10 - 62.5 kHz
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00001001; // x1 fast pwm
// Pin D9 e D10 - 31.4 kHz
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00000001; // x1 phase correct
// Pin D9 e D10 - 7.8 kHz
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00001010; // x8 fast pwm
// Pin D9 e D10 - 4 kHz
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00000010; // x8 phase correct
// Pin D9 e D10 - 976 Hz
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00001011; // x64 fast pwm
// Pin D9 e D10 - 490 Hz - predefinito
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00000011; // x64 phase correct
// Pin D9 e D10 - 244 Hz
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00001100; // x256 fast pwm
// Pin D9 e D10 - 122 Hz
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00000100; // x256 phase correct
// Pin D9 e D10 - 61 Hz
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00001101; // x1024 fast pwm
// Pin D9 e D10 - 30 Hz
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00000101; // x1024 phase correct

Pin D9 e D10 (Timer 1) - 10 bit.
// Pin D9 e D10 - 15.6 kHz 10bit
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00001001; // x1 fast pwm
// Pin D9 e D10 - 7.8 kHz 10bit
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00000001; // x1 phase correct
// Pin D9 e D10 - 2 kHz 10bit
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00001010; // x8 fast pwm
// Pin D9 e D10 - 977 Hz 10bit
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00000010; // x8 phase correct
// Pin D9 e D10 - 244 Hz 10bit
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00001011; // x64 fast pwm
// Pin D9 e D10 - 122 Hz 10bit
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00000011; // x64 phase correct
// Pin D9 e D10 - 61 Hz 10bit
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00001100; // x256 fast pwm
// Pin D9 e D10 - 30 Hz 10bit
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00000100; // x256 phase correct
// Pin D9 e D10 - 15 Hz 10bit
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00001101; // x1024 fast pwm
// Pin D9 e D10 - 7.5 Hz 10bit
TCCR1A = 0b00000011; // 10bit
TCCR1B = 0b00000101; // x1024 phase correct

Pin D3 e D11 (Timer 2) - 8 bit.
// Pin D3 e D11 - 62.5 kHz
TCCR2B = 0b00000001; // x1 
TCCR2A = 0b00000011; // fast pwm 
// Pin D3 e D11 - 31.4 kHz
TCCR2B = 0b00000001; // x1 
TCCR2A = 0b00000001; // phase correct 
// Pin D3 e D11 - 8 kHz
TCCR2B = 0b00000010; // x8 
TCCR2A = 0b00000011; // fast pwm 
// Pin D3 e D11 - 4 kHz 
TCCR2B = 0b00000010; // x8 
TCCR2A = 0b00000001; // phase correct 
// Pin D3 e D11 - 2 kHz
TCCR2B = 0b00000011; // x32 
TCCR2A = 0b00000011; // fast pwm 
// Pin D3 e D11 - 980 Hz
TCCR2B = 0b00000011; // x32 
TCCR2A = 0b00000001; // phase correct 
// Pin D3 e D11 - 980 Hz
TCCR2B = 0b00000100; // x64 
TCCR2A = 0b00000011; // fast pwm
// Pin D3 e D11 - 490 Hz - predefinito
TCCR2B = 0b00000100; // x64 
TCCR2A = 0b00000001; // phase correct 
// Pin D3 e D11 - 490 Hz 
TCCR2B = 0b00000101; // x128 
TCCR2A = 0b00000011; // fast pwm 
// Pin D3 e D11 - 245 Hz
TCCR2B = 0b00000101; // x128 
TCCR2A = 0b00000001; // phase correct 
// Pin D3 e D11 - 245 Hz 
TCCR2B = 0b00000110; // x256 
TCCR2A = 0b00000011; // fast pwm 
// Pin D3 e D11 - 122 Hz 
TCCR2B = 0b00000110; // x256 
TCCR2A = 0b00000001; // phase correct 
// Pin D3 e D11 - 60 Hz 
TCCR2B = 0b00000111; // x1024 
TCCR2A = 0b00000011; // fast pwm 
// Pin D3 e D11 - 30 Hz 
TCCR2B = 0b00000111; // x1024 
TCCR2A = 0b00000001; // phase correct

Esempio di utilizzo.
void setup() 
     // Pin D5 e D6 - 7.8 kHz 
     TCCR0B = 0b00000010; // x8 
     TCCR0A = 0b00000011; // fast pwm 
     // Pin D3 e D11 - 62.5 kHz
     TCCR2B = 0b00000001; // x1 
     TCCR2A = 0b00000011; // fast pwm 
     // Pin D9 e D10 - 7.8 kHz 10bit 
     TCCR1A = 0b00000011; // 10bit 
     TCCR1B = 0b00000001; // x1 phase correct 
     analogWrite(3, 15); 
     analogWrite(5, 167); 
     analogWrite(6, 241); 
     analogWrite(9, 745); // intervallo 0-1023 
     analogWrite(10, 345); // intervallo 0-1023
     analogWrite(11, 78); 
void loop() 
{
}
Se vuoi davvero o hai davvero bisogno di PWM overclocked sul timer di sistema (zero) senza perdere le funzioni del tempo, puoi regolarle come segue:
#define micros() (micros() >> CORRECT_CLOCK) 
#define millis() (millis() >> CORRECT_CLOCK) 
void fixDelay(uint32_t ms) 
     delay(ms << CORRECT_CLOCK); 
}
Le #define devono essere posizionate prima che le librerie siano collegate in modo che entrino nel codice e sostituiscano le funzioni. L'unica cosa è che non funzionerà per regolare il delay() all'interno di un'altra libreria in questo modo, puoi usare fixDelay() per te stesso come scritto sopra. La cosa più importante è CORRECT_CLOCK. Questo è un numero intero uguale al rapporto tra il divisore del timer predefinito e quello nuovo impostato (per l'overclocking PWM). Ad esempio, impostiamo il PWM su 8 kHz. Dall'elenco sopra, vediamo che il divisore predefinito è 64 e 7,8 kHz sarà 8, ovvero 8 volte meno. CORRECT_CLOCK imposta quello appropriato.
#define CORRECT_CLOCK 8 
void fixDelay(uint32_t ms) 
    delay(ms << CORRECT_CLOCK); 
void setup() 
     pinMode(13, 1); 
     // Pin D5 e D6 - 4 kHz 
     TCCR0B = 0b00000010; // x8 
     TCCR0A = 0b00000001; // phase correct 
void loop() 
      digitalWrite(13, !digitalRead(13)); 
      fixDelay(1000); 
}

Libreria PWM.
Oltre a selezionare manualmente i registri, è disponibile una libreria già pronta che consente di modificare la frequenza PWM di Arduino.
La libreria PWM è una potente libreria che permette di modificare la frequenza PWM sui microcontrollori ATmega48 / 88 / 168 / 328 / 640 / 1280 / 1281 / 2560 / 2561, da questi il 328 è su UNO/Nano/Mini e il 2560 è su Arduino Mega.
  • Consente di impostare qualsiasi frequenza PWM.
  • Quando si lavora con timer a 8 bit, è disponibile un solo canale (ad esempio, D3, D5, D9 e D10 rimarranno sull'ATmega328).
  • Consente di lavorare con timer a 16 bit a una risoluzione maggiore (16 bit invece degli 8 standard).
  • La libreria è scritta molto difficile, non sarà possibile dividerla pezzo per pezzo.
  • Guarda gli esempi nella cartella della libreria.
Crea il tuo sito web gratis! Questo sito è stato creato con Webnode. Crea il tuo sito gratuito oggi stesso! Inizia