Pages: 1 [2]   Go Down
Author Topic: PWM push pull....help! [RISOLTO]  (Read 1742 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 327
Posts: 22635
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Offline Offline
Sr. Member
****
Karma: 0
Posts: 268
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
« Last Edit: December 26, 2012, 09:50:06 am by ekjk » Logged

Offline Offline
Sr. Member
****
Karma: 0
Posts: 268
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

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

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.

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


Offline Offline
Sr. Member
****
Karma: 0
Posts: 268
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 123
Posts: 9308
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Scordati di farlo direttamente col 328 a meno che non ti accontenti di bassi valori di frequenza, poche centinaia di Hz.
Il solo modo è utilizzare un inverter esterno che ti fornisce il valore negato del PWM e di conseguenza i due pwm tra loro complementari.
Logged

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

Scordati di farlo direttamente col 328 a meno che non ti accontenti di bassi valori di frequenza, poche centinaia di Hz.
Il solo modo è utilizzare un inverter esterno che ti fornisce il valore negato del PWM e di conseguenza i due pwm tra loro complementari.

Ubi major minor cessat  smiley-sweat
Logged


Offline Offline
Sr. Member
****
Karma: 0
Posts: 268
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quindi non esiste il modo con fastpwm per avere su un pin l'uscita che ne so a 40Khz e su un altro invertita?

Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 123
Posts: 9308
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quindi non esiste il modo con fastpwm per avere su un pin l'uscita che ne so a 40Khz e su un altro invertita?

Col PWM hardware no, col PWM software si però vale solo per frequenze molto basse, poche centinaia di Hertz.
Hai solo due possibilità, soluzione semplice usare un inverter sul pin pwm per sdoppiare il segnale e ottenere la sua versione negata, soluzione complicata usare un micro che prevede la modalità complementare per il pwm, non mi pare esista su nessuno degli AVR utilizzati per Arduino.
Logged

MC
Offline Offline
God Member
*****
Karma: 14
Posts: 917
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi intrometto per un chiarimento semi off topic, che alla fine non lo è.

Mi sono sempre domandato una cosa, una porta logica invertente non altera in alcun modo (anche se trascurabile) il timing del segnale?
Mi riferisco ad un leggero ritardo sui fronti di salita e discesa.
Logged

Vi è una spiegazione scientifica a tutto.
La fede è solo quell'anello che si porta al dito dopo il matrimonio.

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 123
Posts: 9308
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi sono sempre domandato una cosa, una porta logica invertente non altera in alcun modo (anche se trascurabile) il timing del segnale?

Il timing no, inteso come frequenza portante e durata del duty cycle, però introduce un piccolo delay, dovuto al tempo di propagazione della porta, nei cambi fronte della porzione di segnale che passa attraverso la porta.
In pratica il pwm che passa attraverso l'inverter cambia di stato con un delay di svariati nanosecondi rispetto al segnale originale, a seconda della frequenza del pwm questa cosa può essere trascurabile oppure può essere necessario compensare con una qualche tipo di linea di ritardo sul pwm originale.

Logged

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

usare un micro che prevede la modalità complementare per il pwm, non mi pare esista su nessuno degli AVR utilizzati per Arduino.
L'Attiny85 ha 4 uscite PWM di cui 2 collegate allo stesso timer ed invertite l'una rispetto all'altra. Come si vede dalla figura qui sotto, i pin OC1B e /OC1B sono collegati al timer 1 ma con uscita invertita.


* ATTINY25-pinout.jpg (24.97 KB, 798x166 - viewed 23 times.)
Logged


Offline Offline
Sr. Member
****
Karma: 0
Posts: 268
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Forse possiamo dire TOPIC RISOLTO

Ho trovato un codice in rete di un tizio inglese penso, che ha fatto un modulazione pwm in push pull...allora copio lo sketch e vedo in realtà con l'oscilloscopio che effettivamente una uscita è dritta e una negata...molto bene, ma la frequenza intorno ai 16Khz.

Così smanetto un pò e riesco a modificare la frequenza portandola a 50Khz ed inoltre controllo il duty di entrambe in modo indipendente, non come se avessi una sola uscita e l'avessi negata perchè in quel caso avrei che se il duty di una è 90% l'altra è 10%.
Invece così vario il duty tramite la variabile count da un minimo di 2% ad un max di 95% circa...aggiustabile a piacimento...però bisogna avere un oscillo perchè se non lo avevo col cavolo che riuscivo solo via software a far combaciare i valori dei reigistri OCR1A e B..

Questo è un semplice controllo pwm molto abbozzato...comunque la parte di variazione di duty funziona.

Code:
#define PIN_PRI_A   9    // OCR1A - high-active primary drive
#define PIN_PRI_B   10   // OCR1B - low-active primary drive


#define PUSH_PULL   true // false = OCR1A only, true = OCR1A + OCR1B


#define TIMER1_PRESCALE   1     // clock prescaler value
#define TCCR1B_CS20       0x01  // CS2:0 bits = prescaler selection


#define PERIOD_US   20
#define PERIOD_TICKS (microsecondsToClockCycles(PERIOD_US / 2) / TIMER1_PRESCALE)



int count=0;
int duty=2;
float Verror=0;

float Vset=512.0;
float Vact;

unsigned long last=0;
unsigned long wait=20;
boolean first=true;

void setup()
{
  
  pinMode(A0, INPUT); //input tensione
  digitalWrite(A0, LOW);
  
  
  analogWrite(PIN_PRI_A,128);    // let Arduino setup do its thing
  analogWrite(PIN_PRI_B,128);

  TCCR1B = 0x00;                 // stop Timer1 clock for register updates
  
    // Clear OC1A on match, P-F Corr PWM Mode: lower WGM1x = 00
  TCCR1A = 0x80 | 0x00;

// Configure Timer 1 for Freq-Phase Correct PWM
//   Timer 1 + output on OC1A, chip pin 15, Arduino PWM9
//   Timer 1 - output on OC1B, chip pin 16, Arduino PWM10


// If push-pull drive, set OC1B on match

 TCCR1A |= 0x30;


 ICR1 = PERIOD_TICKS;           // PWM period
 OCR1A = duty;      // ON duration = drive pulse width//ucita 9
 OCR1B = duty+156;      //  ditto - use separate load due to temp buffer reg //usita 10
 TCNT1 = OCR1A - 1;             // force immediate OCR1x compare on next tick

// upper WGM1x = 10, Clock Sel = prescaler, start Timer 1 running
 TCCR1B = 0x10 | TCCR1B_CS20;
}

void loop()
{
   OCR1A = duty+count;      // con count vario il duty delle due uscite nello stesso modo
   OCR1B = duty+156-count;  
      
      if(first)
      {
          delay(2000);
          first=false;
      }
      
      Vact=analogRead(A0);
  
      
      Verror=100.0*(Vset-(float)(Vact))/Vset;
         
    
        if(millis()-last>=wait)
        {
          last=millis();
          
            if(Verror<0) count--;
            if(Verror>0) count++;

          if(count<0) count=0; //min duty 2%
          if(count>=70) count=70; //max duty 95%
        }
      

}
« Last Edit: December 29, 2012, 04:40:46 am by ekjk » Logged

Pages: 1 [2]   Go Up
Jump to: