Pages: [1] 2   Go Down
Author Topic: PWM 38Khz  (Read 1731 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 56
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Code:
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?

Code:
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
Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 518
Posts: 12321
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Offline Offline
Sr. Member
****
Karma: 8
Posts: 293
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Code:
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?

Code:
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...

poi l'ocr24... forse intendevi ocr4a?
« Last Edit: January 07, 2013, 03:13:51 pm by qsecofr » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Probabile che intendesse OCR4A.


Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

TCCR4A = ((1<<COM4A0) | (1<<WGM40));
TCCR4B = (1<<CS40);
OCR4A = 105;

Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 56
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
TCCR4A = ((1<<COM4A0) | (1<<WGM40));
TCCR4B = (1<<CS40);
OCR4A = 105;

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
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 56
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 518
Posts: 12321
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
ho trovato il mio sketch di prova: (c'è anche il metodo per il calcolo, il suggerimento è di Astrobeed, non mio smiley)
Quote
Quote
#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
  */
}

void loop()
{
 } 

Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
TCCR4A = ((1<<COM4A0) | (1<<WGM40));
TCCR4B = (1<<CS40);
OCR4A = 105;

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/(2*PRESCALER*VALORE_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/(2*OCR4A*2)
Da cui
38000 = 16.000.000/(2*OCR4*2)
Da cui
OCR4A = 16.000.000/(38000*4)

Ed ecco OCR4A a 105.
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 56
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Seguendo il tuo ragionamento con il datasheet dell'ATmega2560 sono riuscito a capire un pò meglio la sequenza di istruzioni.

Domani potrò caricare il nuovo firmware e verificare con l'oscilloscopio cosa accade.

grazie ancora.
Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 518
Posts: 12321
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Leo, prova a riguardare le ultime tre formule, a me pare di vedere almeno due errori smiley-roll-sweat
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Leo, prova a riguardare le ultime tre formule, a me pare di vedere almeno due errori smiley-roll-sweat
A parte l'aver tralasciato una "A (OCR4 al posto di OCR4A) e l'aver approssimato 38095 a 38000?  smiley-sweat
Logged


Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 518
Posts: 12321
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

sì, un ulteriore inghippo è strano per me ma non per lui,  evidentemente, inutile parlarne smiley-grin
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Offline Offline
Jr. Member
**
Karma: 0
Posts: 56
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sì, un ulteriore inghippo è strano per me ma non per lui,  evidentemente, inutile parlarne smiley-grin

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.
Code:
TCCR4A = ((1<<COM4A0) | (1<<WGM40));
TCCR4B = (1<<CS40);
OCR4A = 105;

Sul pin 6, dichiarato come output non accade nulla e non riesco a spiegarmi il perchè.

Spero ancora nel vostro aiuto.
Grazie
Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 518
Posts: 12321
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

 smiley-lol smiley-lol smiley-sweat 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 smiley-grin
Sul resto devi aspettare Leo, il mago è lui in queste cose....
Logged

Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

Pages: [1] 2   Go Up
Jump to: