Go Down

Topic: PWM push pull....help! [RISOLTO] (Read 2206 times) previous topic - next topic

ekjk

Dec 25, 2012, 06:02 pm Last Edit: Dec 29, 2012, 07:09 pm by ekjk Reason: 1
Ciao a tutti e Buona Natale.
Sto tentando di realizzare un controllo PWM in cui avere due uscite in push pull, ovvero una dritta e una negata con arduino uno.

utilizzo questo codice per settare il pin digitale 3 per avere una quadra a 100khz con duty variabile impostando OCR2B.

Code: [Select]

TCCR2A = 0x23; // imposto "pin high on overflow", e "clear on compare match with OCR2B
 TCCR2B = 0x09;  // seleziono come sorgente di clock I 16MHz di sistema senza prescaler
 OCR2A = 159;  // inizializzo il top level match a 159 ->f_PWM=100kHz



Vorrei avere la stessa cosa su un altro pin digitale, che però sia invertito rispetto a questo e che quindi segua il comportamento negato di questo.

Quali registri devo impostare?

Grazie

ekjk

Non c'è nessuno che mi possa aiutare?

qsecofr


Ciao a tutti e Buona Natale.
Sto tentando di realizzare un controllo PWM in cui avere due uscite in push pull, ovvero una dritta e una negata con arduino uno.

utilizzo questo codice per settare il pin digitale 3 per avere una quadra a 100khz con duty variabile impostando OCR2B.

Code: [Select]

TCCR2A = 0x23; // imposto "pin high on overflow", e "clear on compare match with OCR2B
  TCCR2B = 0x09;  // seleziono come sorgente di clock I 16MHz di sistema senza prescaler
  OCR2A = 159;  // inizializzo il top level match a 159 ->f_PWM=100kHz



Vorrei avere la stessa cosa su un altro pin digitale, che però sia invertito rispetto a questo e che quindi segua il comportamento negato di questo.

Quali registri devo impostare?

Grazie


... prima cosa: forse a Natale qualcuno va anche a parenti o è pieno di prosecco e non risponde... non avere fretta...
... per i motivi di qui sopra Leo è sicuramente molto molto molto più ferrato di me sui pwm ed i timers...
... se ti accontenti di me fai male :D
... mi vengono a mente tre soluzioni: la prima, forse più scontata, è di attaccare un interrupt al timer e poi dentro all'interrupt fai quello che vuoi (circa perchè devi andare veloce...) ....
la seconda è hardware: ci pianto una porta logica in uscita al pin.
la terza è di nuovo software: bit COM1A1 e COM1A2 (per timer1... per timer 2 sarà immagino uguale solo con il due) del registro TCCR1A... guarda verso il fondo di questo documento... se metti i due bit alti hai l'uscita invertita...
http://www.avrbeginners.net/architecture/timers/timers.html
...e detto così sembra fatta ma invece secondo me questa ultima soluzione non ti risulterà possibile perchè ti inverte in automatico tutti e due i canali/pin del timer (almeno credo) quindi dovresti ricorrere a 2 timer alla stessa frequenza al che dubito che la sincronia sia possibile...

leo72

Una soluzione semplicissima è quella di attivare l'interrupt al raggiungimento di OCR2B e dentro la corrispondente ISR (routine di gestione dell'interrupt) metti un piccolo codice che alterna lo stato su un pin a tua scelta, con uscita invertita (basta una semplice variabile di stato di cui alterni il valore).

ekjk

#4
Dec 26, 2012, 11:32 am Last Edit: Dec 26, 2012, 11:53 am by ekjk Reason: 1
Grazie delle risposte,

Leo, potresti per favore scrivermi le due righe che servono per attivare l'interrupt su 0cr2b?

leo72


Leo, potresti per favore scrivermi le due righe che servono per attivare l'interrupt su 0cr2b?

Scusa, tu usi il canale A del timer, quindi devi agganciarlo al OCR2A.

TIMSK2 |= (1<<OCIE2A);

Poi scrivi la tua ISR:
Code: [Select]
ISR(TIMER2_COMPA_vect) {
..
..
}


Prova

ekjk

Ho provato con questo codice

Code: [Select]


ISR(TIMER2_COMPA_vect)
{
  if(flag)  {PORTD = B00100000; flag=false;}
  if(!flag) {PORTD = B00000000; flag=true;}
}


Ma così ottengo un segnale sovrapposto al mio e più stretto di duty cycle....why?

leo72


Ho provato con questo codice

Code: [Select]


ISR(TIMER2_COMPA_vect)
{
  if(flag)  {PORTD = B00100000; flag=false;}
  if(!flag) {PORTD = B00000000; flag=true;}
}


Ma così ottengo un segnale sovrapposto al mio e più stretto di duty cycle....why?

Allora devi invertire il segno. Sul duty cicle è normale che sia leggermente diverso, qui stai facendo un segnale PWM con la tecnica del bit-banging quindi un minimo di differenza c'è rispetto al segnale che ottieni facendo pilotare il segnale direttamente al timer.

ekjk

Ho provato ad invertire lo stato del flag ma il risultato è lo stesso.
Sullo stato alto del mio segnale (Ton) ho esattamente in mezzo al Ton il segnale generato con la isr, ed ha un Ton molto breve rispetto all'altro..
Non capisco come sia possibile dato che dovrebbe andare a 1 solo al raggiungimento del valore di compare e non prima.

leo72

Ma che modalità usi per il timer 2? Non è che forse il contatore incrocia 2 volte OCR2A e quindi generi 2 interrupt?

ekjk

Dovrebbe essere la CTC.
Questo è quello che uso, preso pari pari da internet

// Configurazione del Timer2 per funzionare in modo fast PWM su OC2B (pin 3 di Arduino)
  // set pin high on overflow, clear on compare match with OCR2B
  TCCR2A = 0x23; // imposto "pin high on overflow", e "clear on compare match with OCR2B
  TCCR2B = 0x09;  // seleziono come sorgente di clock I 16MHz di sistema senza prescaler
  OCR2A = 159;  // inizializzo il top level match a 159 ->f_PWM=100kHz

Se qualcuno poi mi potesse spiegare gentilmente il significato di 0x23 e 0x09 gli sarei molto grato. Non capisco che bit si vadano a settare in questo modo

leo72


Dovrebbe essere la CTC.

La CTC non interagisce con i pin esterni. Si sfrutta per gestire il timer come semplice contatore. Sei sicuro?

Quote

Questo è quello che uso, preso pari pari da internet

Ah.. ecco...
quindi non sai com'è stato configurato il timer? Io sinceramente non mi sono messo a recuperare la modalità partendo dai registri modificati, pensavo avessi già fatto il setup tu  ;)

Quote


// Configurazione del Timer2 per funzionare in modo fast PWM su OC2B (pin 3 di Arduino)
  // set pin high on overflow, clear on compare match with OCR2B
  TCCR2A = 0x23; // imposto "pin high on overflow", e "clear on compare match with OCR2B
  TCCR2B = 0x09;  // seleziono come sorgente di clock I 16MHz di sistema senza prescaler
  OCR2A = 159;  // inizializzo il top level match a 159 ->f_PWM=100kHz

Qui c'è scritto "configurazione del Timer 2 per funzionare in modo fast PWM", quindi non è la CTC...

Quote

Se qualcuno poi mi potesse spiegare gentilmente il significato di 0x23 e 0x09 gli sarei molto grato. Non capisco che bit si vadano a settare in questo modo

Beh, devi aprire il datasheet, prendere quei valori "infilati" nei registri e recuperare i bit che modificano. Solo così sai come viene impostato il timer.

ekjk

Intanto grazie per la pazienza  :)

Mi sono sforzato più volte di leggere il datasheet ma faccio fatica coi timer.

Ho necessità di generare due quadre complementari tutto qua. La frequenza e il duty vorrei poterli impostare.
Ovviamente se aumenta il duty di una quello dell'altra deve diminuire.

leo72

Ho controllato, effettivamente il timer viene impostato in Fast PWM con OCRA come top.

Ti consiglio la lettura di questa pagina:
http://www.arcfn.com/2009/07/secrets-of-arduino-pwm.html
spiega come manipolare i timer in generale, il 2 nello specifico.
Ti sarà d'aiuto.

ekjk

Grazie mille, ci riprovo.

Go Up