Ciao a tutti
Per un mio progetto sto cercando di capire come modificare le frequenze delle uscite pwm dell'atmega1284p, che sono a 490hz come impostazione standard.
Ho provato a usare la libreria per il timer 3 "TimerOneThree" ma non funziona.
La libreria pwm.h che usavo per il 328p non funziona.
C'è qualcuno che ha già testato qualcosa di funzionante?
Per il bootloader ho usato il MightyCore-master
Esempio per i pin 4 e 5 in modalità fast PWM la frequenza è data da f_pwm=f_cpu/(prescaler256) sto leggendo a pagina 97 del datasheet del AVR. Come puoi facilmente notare in questa modalità quella di default di Arduino non puoi fare molto, i prescaler sono limitati (1, 8, 64, 256, o 1024). Per altri pin puoi impostare un fast PWM piu flessibile. Per i pin 18 e 19 in fast PWM la frequenza diventa f_pwm=f_cpu/(prescaler(1+TOP) stessi prescaler di prima ma TOP diventa un intero senza segno a 16bit, quindi compreso tra 0 e65536 (sto leggendo a pagina 122).
Come vedi con una piccola spulciatina al datasheet puoi trovare tutto e spiegato anche piuttosto chiaramente, ovviamente il supporto nativo da Arduino non è garantito, dovrai giostrartela con i registri della MCU, ma ti assicuro che non è nulla di complicato.
Ciao
Sto testando i vari timer, impostando in questo modo, nel void setup :
TCCR2B = 0x01;
Eventualmente mi fai un esempio pratico ?
Grazie mille
Ok facciamo un bel esempio, userò il timer 1(pin 18, 19).
-Primo, modalità, mi porto a pagina 130 alla tabella 16-5, scelgo modalità Fast PWM con TOP ICRn, quindi modalità 15, mi segno i valori dei bit WGMnx che sono tutti impostati ad 1 tranne WGMn0
-Secondo, modalità di comparazione, per fast PWM la pagina in questione è la 128 tabella 16-3 scelgo la modalità comparazione non invertente, per entrambi i pin e mi segno i bit corrispondenti per il primo pin dovro impostare a uno il solo bit COMnA1 per il secondo il solo COMnB1.
-Terzo, la frequenza, torniamo alla nostra formulina trovata a pagina 122 f_pwm=f_cpu/(prescaler*(1+TOP), f_cpu è principalmente una costante, la frequenza di clock del nostro processore, prescaler è un valore quantizzato, dalla tabella 16-6 (pagina 131) abbiamo a disposizione 1, 8, 64, 256 e 1024, TOP come abbiamo visto prima è il valore a 16 bit del registro ICR1ora dobbiamo giocare con questi valori pre trovare la frequenza che desideriamo, io voglio una f_pwm da 160Hz, trovo dei valori di prescaler di 64 e ICR1 di 1561.
-Quarto, definiamo il tutto
ICR1 = 1561;
TCCRnA = 1 << COMnA1 | 1 << COMnB1 | 1 << WGMn1;
TCCRnB = 1 << WGMn3 | 1 << WGMn2 | 1 << CSn1 | 1 << CSn0;
e con OCR1A e OCR1B posso gestire il dutycycle con DT 100% => ICR1 == OCR1A.
Spero di averti almeno un po chiarito le idee.
Ho capito qualcosa
devo fare dei test.
L'impostazione dei timer deve essere scritta nel void setup ?
Solitamente si, per regola bisognerebbe evitare di toccare le impostazioni a runtime, salvo casi particolari, in quanto vorrebbe dire ad ogni ciclo loop andare a modificare l'impostazione delle componenti HW. Ovviamente se un timer con apposito switch deve gestire 4 apparecchi capisco la necessità delle modifiche a runtime, ma se il PWM è destinato ad un solo utilizzo, imposto una volta e poi modifico solo il dutycycle.
Stai solo attento alle funzioni che usi di librerie o di Arduino core che non vadano ad interferire con le tue impostazioni e vice versa.
scusami ma copiando il tuo codice mi dà errori di dichiarazione variabili.
uso la versione Arduino 1.6.5 per programmare.
Colpa mia la n simboleggia il numero del timer, quindi va sostituito con 1, ma il mio voleva solo essere un esempio visto che sicuramente nel tuo caso non andrà bene.
ok, eventualmente hai qualche esempio già testato?
Su 328P io non ho mai adoperato analogWrite se non per dei debug, un 1284P non ho mai avuto necessità di adoperarlo, quindi la risposta è no, ma basta leggere il datasheet, di esempi non te ne servono molti visto che su di esso sono anche riportate le formule per i calcolo delle frequenze, che se per caso ti capiterà di trovare in qualche sito che spaccia tutorial 4volte su 5 sono riportate errate.
Ultima cosa di cui devi tenere conto è che OCR = 0 non vuol dire spento ma vuol dire con un dutycycle di 1/TOP questo è dovuto alla struttura dei timer, puo non essere un problema, ma se per esempio lo userai con delle luci a OCR=0 noterai comunque una piccolissima emissione luminosa, in quel caso è necessario quanto imposti OCR=0 abbinare un distacco del pin.
Ciao Roberto
Stavo giusto testando il codice con le tue impostazioni.
La frequenza è corretta 160hz come da calcoli
Usando la funzione analogWrite, il pwm è variabile da 0 a 1561 ovvero lo stesso valore impostato su ICR1
Ora, mi aiuteresti a capire il motivo ?
Ciao Roberto, ho fatto diversi test, ed è tutto ok.
Pian piano ci sto prendendo la mano.
Però non capisco come andare ben alti in frequenza, esempio, se uso il timer1 (pin18-19) con prescaler a 1, e precaricando su ICR1 un valore pari a 255, siamo sui 62khz di pwm.
Con la funzione analowrite posso variare il pwm da (0 a 255)
Se volessi andare ben più in alto con la frequenza pwm che sistema devo usare ?
Virtualmente puoi arrivare ad un pwm con frequenza uguale alla frequenza di clock con prescaler 1 e ICR1 1 ma con impossibilità di gestire il dutycicle, guadagni in frequenza perdi in risoluzione, il mondo è un grande dare e ricevere.
Ti ringrazio comunque per il supporto.
Difficilmente sarei riuscito a venirne fuori 