Go Down

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

astrobeed


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.


leo72


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.

ekjk

#27
Dec 28, 2012, 08:19 pm Last Edit: Dec 29, 2012, 10:40 am by ekjk Reason: 1
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: [Select]

#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%
       }
     

}

Go Up