Ciao a tutti,
per una barriera IR, sto cercando di ottenere un segnale pwm a 38Khz.
Sto utilizzando un Arduino Mega.
Ho trovato questo codice per ottenere tale segnale sul pin digitale 10, lavorando a livello dei registri.
const byte LED = 10; // Timer 2 "A" output: OC2A
void setup() {
pinMode (LED, OUTPUT);
// set up Timer 2
TCCR2A = _BV (COM2A0) | _BV(WGM21); // CTC, toggle OC2A on Compare Match
TCCR2B = _BV (CS20); // No prescaler
OCR2A = 209; // compare A register value (210 * clock speed)
// = 13.125 nS , so frequency is 1 / (2 * 13.125) = 38095
} // end of setup
void loop() { }
Non ho dimestichezza con la gestione dei registri, così al fine di ottenere il segnale sul pin 6 ho visto che bisogna agire sul timer4.
Ho quindi modificato il codice banalmente come segue, ma non funziona.
Potete aiutarmi?
const byte LED = 6;
void setup() {
pinMode (LED, OUTPUT);
// set up Timer 4
TCCR4A = _BV (COM4A0) | _BV(WGM41);
TCCR4B = _BV (CS40); // No prescaler
OCR24 = 209; // compare A register value (210 * clock speed)
// = 13.125 nS , so frequency is 1 / (2 * 13.125) = 38095
} // end of setup
Ma che frequenza ottieni?
Se cerchi "barriera ad infrarossi" trovi un mio Topic con il suggerimento di Astro che con tre righe mi ha fatto ottenere i 38KHz (circa... precisi non li avrai mai), però mi pare si trattasse del timer 2.
Etan:
Ciao a tutti,
per una barriera IR, sto cercando di ottenere un segnale pwm a 38Khz.
Sto utilizzando un Arduino Mega.
Ho trovato questo codice per ottenere tale segnale sul pin digitale 10, lavorando a livello dei registri.
const byte LED = 10; // Timer 2 "A" output: OC2A
void setup() {
pinMode (LED, OUTPUT);
// set up Timer 2
TCCR2A = _BV (COM2A0) | _BV(WGM21); // CTC, toggle OC2A on Compare Match
TCCR2B = _BV (CS20); // No prescaler
OCR2A = 209; // compare A register value (210 * clock speed)
// = 13.125 nS , so frequency is 1 / (2 * 13.125) = 38095
} // end of setup
void loop() { }
Non ho dimestichezza con la gestione dei registri, così al fine di ottenere il segnale sul pin 6 ho visto che bisogna agire sul timer4.
Ho quindi modificato il codice banalmente come segue, ma non funziona.
Potete aiutarmi?
const byte LED = 6;
void setup() {
pinMode (LED, OUTPUT);
// set up Timer 4
TCCR4A = _BV (COM4A0) | _BV(WGM41);
TCCR4B = _BV (CS40); // No prescaler
OCR24 = 209; // compare A register value (210 * clock speed)
// = 13.125 nS , so frequency is 1 / (2 * 13.125) = 38095
} // end of setup
non funziona ma cosa fa?
la cosa che mi viene in mente è che il timer 2 è a 8 bit mentre il 4 è a 16...
Cmq prova queste righe di codice messe nel setup.
Dovrebbero impostare il timer 4 dell'Atmega2560 in modalità Phase Correct PWM ad 8 bit con top fissato da OCR4A. se non ho fatto male i conti, hai i tuoi 38095 Hz sul pin D6.
[quote author=Michele Menniti link=topic=141298.msg1061383#msg1061383 date=1357580646]
Ma che frequenza ottieni?
Se cerchi "barriera ad infrarossi" trovi un mio Topic con il suggerimento di Astro che con tre righe mi ha fatto ottenere i 38KHz (circa... precisi non li avrai mai), però mi pare si trattasse del timer 2.
Grazie Michele per il suggerimento.
Sono a corto di pin ed il 6 era perfetto.
In ogni caso mi metto a studiarmi anche il tuo post.
[/quote]
ho trovato il mio sketch di prova: (c'è anche il metodo per il calcolo, il suggerimento è di Astrobeed, non mio :))
#define TX 11
void setup()
{
pinMode(TX, OUTPUT);
OCR2A = 209;
TCCR2A = 0b01000011;
TCCR2B = 0b00001001;
/*
Ad OCR2A si deve associare il risultato di
(clock/frequenza_da_ottenere/2)-1
Esempio (Arduino a 16MHz)
per 38000Hz: 16000000/38000/2=210-1=209
per 40000Hz: 199
*/
}
Grazie mille!
Li proverò domattina appena rimetto le mani sul sistema.
Ti andrebbe di dettagliare meglio il codice in modo da capire i valori che metti nei registri e come hai fatto i conti?
Grazie ancora
La prima cosa da fare è scegliere la modalità di generazione dell'onda.
In questo caso ho scelto la Phase Correct PWM ad 8 bit del timer 4, che, ricordo, è a 16 bit ma può essere configurato appunto per lavorare anche ad 8/9/10 bit in alcune modalità. La Phase Correct PWM, rispetto alla Fast PWM che viene spesso scelta, permette di avere un segnale perfettamente quadro, con le fasi High e Low perfettamente simmetriche.
Per far ciò ho settato ad 1 il bit WGM40 nel registro TCCR4A.
Scelta la modalità, ho scelto il canale ed il comportamento. Volevi agire sul pin D6, che è il pin OC4A, per cui ho scelto di cambiare lo stato del pin (da alto a basso e viceversa) ogni volta che il valore del contatore del timer raggiungesse il valore del registro OCR4A. Per fare ciò ho settato ad 1 il bit COM4A0 sempre nel registro TCCR4A.
Adesso arriviamo al valore di OCR4A.
Per la modalità Phase Correct PWM, la formula da usare per calcolare la frequenza è
Fpwm = Fsys/(2PRESCALERVALORE_MAX*2)
Il PRESCALER è il fattore di divisione del clock di sistema. Ho usato un fattore /1, quindi nessuna divisione del clock. Per selezionare questa voce ho settato ad 1 il bit CS40 nel registro TCCR4B.
VALORE_MAX è il valore massimo del registro o, in alternativa, il valore di OCR4A.
Avendo messo PRESCALER ad 1, con Fsys pari a 16 MHz, la formula è
Fpwm = 16.000.000/(2OCR4A2)
Da cui
38000 = 16.000.000/(2OCR42)
Da cui
OCR4A = 16.000.000/(38000*4)
Michele non ho risposto per mancanza di interesse ma per assenza di connessione.
E' ovvio che ho posto il quesito e che mi interessano molto i vostri commenti e aiuti.
Purtroppo non sono riuscito a rilevare gli inghippi di cui parlavi, ti sarei grato se me li facessi rilevare.
Anche perchè il codice di Leo non mi funziona.
XD XD ma no Etan, mica mi riferivo a te! il "lui" è il programma che si comporta a prescindere dal mio ragionamento. Spiego l'errore che ho fatto: dalle mie reminiscenze elementari ricordavo che una serie di * e / portevano essere invertire tra loro senza che cambiasse il risultato, invece era una mia confusione; allora facevo 16.000.000/38000*4 ignorando la parentesi e non mi usciva (OVVIAMENTE) 105, poi ci sono arrivato, volevo evitare di parlarne ma ora mi hai costretto ad uscire allo scoperto
Sul resto devi aspettare Leo, il mago è lui in queste cose....
Si ma niente! Sull'oscilloscopio ho sempre un segnale a 0V.
Tu l'hai provato?
Ho provato sull'Arduino UNO, usando i corrispondenti pin OC0A e OC1A, ed a me i led si accendono. A questo punto ho dei dubbi sulla corrispondenza fra canali dei timer e pin dell'Arduino MEGA dello schema che ho allegato alcuni post fa.