PWM push pull....help! [RISOLTO]

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.

 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

Non c'è nessuno che mi possa aiutare?

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

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

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

Grazie delle risposte,

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

ekjk:
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:

ISR(TIMER2_COMPA_vect) {
 ..
 ..
}

Prova

Ho provato con questo codice

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?

ekjk:
Ho provato con questo codice

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.

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.

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

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

ekjk:
Dovrebbe essere la CTC.

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

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 :wink:

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

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.

Intanto grazie per la pazienza :slight_smile:

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.

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

Ti consiglio la lettura di questa pagina:

spiega come manipolare i timer in generale, il 2 nello specifico.
Ti sarà d'aiuto.

Grazie mille, ci riprovo.

Se hai bisogno di 2 segnali simili ma invertiti, perché non li fai entrambi con la tecnica del bit-banging?
Imposti il timer 2 in modalità contatore (la CTC, appunto) e ad ogni overflow del timer scambi i livelli dei 2 pin che ti servono.

ciao, ho guardato il link ma non ci ho capito tanto di più, nel senso che non capisco tutti quei simboli usati tipo la tilde o _BV() ecc.

Nel caso del modo CTC, non con overflow ma con compare register, a che frequenza posso arrivare? Mi accontento di 100KHz.

Ho provato ma non mi funziona con il timer 2.

No esiste una libreria in cui ti danno metodi per impostare il pin di uscita, freq e duty?
Io ci sto sclerando con sti timer

Ho passato 3 ore su questi timer ma non mi funziona nulla.
Dovrebbe essere semplice creare due uscite invertite tra loro...non vorrei usare un componente in più per forza

ekjk:
ciao, ho guardato il link ma non ci ho capito tanto di più, nel senso che non capisco tutti quei simboli usati tipo la tilde o _BV() ecc.

~ è il simbolo di inversione, quindi ~1 equivale a 0. Per cui se io faccio ~(1<<TOIE2) significa che metto ad 1 il bit TOIE2 in un byte di registro, e poi ne inverto il valore, quindi diventa tutto ad 1 ed a 0 solo il bit TOIE2. Facendo un AND logico poi spengo quel bit.

No esiste una libreria in cui ti danno metodi per impostare il pin di uscita, freq e duty?
Io ci sto sclerando con sti timer

Usa la PWM Frequency, è una lib che permette di avere un segnale PWM di una determinata frequenza su un qualsiasi pin:
http://playground.arduino.cc/Code/PwmFrequency

Grazie, ma per invertire poi tale segnale generato su un pin utilizzando quella libreria?