Forum: Mikrocontroller und Digitale Elektronik Atmega88 PWM Tastverhältnis/DutyCycle bestimmen


von Felix K. (felix_xyz)


Lesenswert?

Hallo,
vor dem Problem erst einmal die Beschreibung des Aufbaus:
Ich versuche einen Wert über eine PWM Signal bzw den DutyCycle von einem 
Atmega88 zu einem anderen zu übertragen.
Genutzt werden sollen nur >20PWM% und <80PWM%. Also eigentlich ganz 
simpel. Die Atmegas laufen beide mit einem 8Mhz Quarz. Meine Vorstellung 
war nun eine Frequenz (100Hz-300Hz) zu nehmen und im Sende-Atmega 
einfach den DutyCycle zu verändern. Dieser soll dann am Empfangs-Atmega 
über PinB0 / ICP1 ausgemessen werden und dann diesem „stabil“ zur 
Verfügung stehen.
Mein Problem ist nun, dass der DutyCycle nicht schwanken darf. Doch 
leider schwankt das ermittelte Signal manchmal und manchmal nicht…
Meine Frage an euch ist nun:
Habe ich beim Auswerten des PWM Signals einen Fehler gemacht?  Dass der 
Fehler beim erzeugen vom PWM Signal liegt kann ausgeschlossen werden. 
Ich habe bereits eine stabile PWM-Quelle als Sender benutzt. Mit 
demselben schwankenden Ergebnis :(

Hoffe es kann mir jemand helfen!
Gruß Felix

Zum Auswerten verwende ich folgenden Code:

unsigned long DC_Array[11]={0,0,0,0,0,0,0,0,0,0};
unsigned char PWMOK=1;
unsigned long ic_zp_A1 = 0;
unsigned long ic_zp_B   = 0;
unsigned long ic_zp_A2, ISR_A1, ISR_A2, ISR_B;
unsigned long Ziel=0;
unsigned long DutyCycle;

int main (void)
{
TCCR1B |= (1<<ICES1)  | (0<<CS11) | (1<<CS10) |(1<<ICNC1);
TIMSK1 |= (1<<ICIE1);
sei();

while(1)      //Endlosschleife
  {
    ic_zp_A1=ISR_A1;//-ISR_A2;
    ic_zp_B=ISR_B;//-ISR_A2;
    if((ic_zp_A1>ic_zp_B))  //Komplett ungültige Werte filtern
    {
      for (x=9;x>0;x--) //immer 10 Werte schieben und vergleichen
      {
      DC_Array[x]=DC_Array[x-1];
      }
      DC_Array[0]=((ic_zp_B*10000)/ic_zp_A1);
      for (x=9;x>0;x--)
      {
        if (DC_Array[x]==DC_Array[x-1])
          {PWMOK=1;}
        else
          {PWMOK=0;}
      }
      //Nur wenn 10Messungen denselben Wert ergeben haben
if (PWMOK==1)
{
        DutyCycle0=DC_Array[0];
        DutyCycle=DutyCycle0/39;
        UpdateDisplay=0;
        if ((DutyCycle>200)||(DutyCycle<50))
        {
          Unterprogramm();
        }
        else
        {
        }
      }
    }
}
}
//########################### ISR Routine ###########################
ISR (TIMER1_CAPT_vect)
{
cli();
  if (TCCR1B & _BV(ICES1))
  {
    ISR_A1 = ICR1;
    TCNT1=0;
    TCCR1B &=~(1<<ICES1);//auf fallende Flanke Triggern
  }
  else
  {
    ISR_B = ICR1;
    TCCR1B |= (1<<ICES1);//auf steigende Flanke triggern
  }
sei();
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.