www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega32 PWM dead time


Autor: Lesso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Ich habe eine Frage, ich komme nicht drauf wie ich das am einfachsten 
machen kann, für euch aber wohl kein Problem ich habe den Quellcode 
hier:
#include <avr/io.h>
 
int main()
{
  DDRD = (1 << PD4) | (1 << PD5); 
 
  TCCR1A = (1<<COM1A1) | (1<<WGM11) | (1<<COM1B1) |(1<<COM1A0);
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
 
  ICR1 = 9;
 
 
  OCR1A = 4;
  OCR1B = 4;
 
 
  while( 1 )
    ;  
}
Also eine PWM mit 50% duty cycle und PD4 und PD5 sind jeweils 
invertierend, das Problem, ich brauche eine kleine dead time dazwischen, 
nur wie kann ich das mit dem AVR am einfachsten bewerkstelligen? Habt 
ihr ne Idee? denn auch wenn ich jetzt den OCR1A auf 3 setze dann habe 
ich zwar nur einmal eine Flanke die an den beiden Ausgängen gleichzeitig 
in umgekehrter Richtung laufen, aber ich darf eben garkeine 
gleichzeitigen Spannungsänderungen haben, deshalb die dead time.

Vielen Dank schonma im vorraus

Lesso

Autor: Jim G. (jimg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einfachste lösung, auch wenn ich von meine Nachposter erschlagen werde.
Du baust zwischen OCR1A und OCR1B folgendes ein:
 for(i=0;i<d;i++){
 }

Diese schleife macht im Grunde garnichts, außer den µC für ein kurzen 
Moment zu beschäftigen. Dannach macht der µC einfach weiter im 
Programm...

Vergiss nicht nach
int main()
{
folgende zeile:
int i,d;

in d kannst du ein Wert speichern bis wohin der µC erst zählen muss, 
bevor er weiter macht... Kannst auch alternativ d weg lassen und den 
Wert direkt hinschreiben.

wie schnell der µC gezählt hat, liegt an seine Frequenz. 
(logischerweise)... daher kann man, wenn man die Frq. kennt, genau 
bestimmen wie lange er warten soll.

Ach ja... warum ich gleich geschlagen werde:
Du beschäftiges den kompletten µC und  der kann wärend der "sinnlosen" 
Schleife nichts machen, außer i aufwärts zählen.

EDIT:
#include <avr/io.h>
 
int main()
{
  DDRD = (1 << PD4) | (1 << PD5); 
 
  TCCR1A = (1<<COM1A1) | (1<<WGM11) | (1<<COM1B1) |(1<<COM1A0);
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
 
  ICR1 = 9;
 
 
  OCR1A = 4;
  OCR1B = 4;
 
 
  while( 1 )
    ;  
}


^^ Irgend eine wichtige Komponente fehlt da noch...
while(1);
 ist zwar eine Schleife, aber du führst dein Programm außerhalb der 
Schleife aus... der µC macht also dies nur einmal beim Start und 
niewieder. Weiß ja nicht, was der µC genau um großen und ganzen machen 
soll.
Soll er das nur einmal beim start machen?

Autor: Lesso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, Danke für deinen Post

Nein das soll er immer machen heißt das mein Progamm müsste so ausehen:
#include <avr/io.h>
 
int main()
{ int i;
  DDRD = (1 << PD4) | (1 << PD5); 
 
  TCCR1A = (1<<COM1A1) | (1<<WGM11) | (1<<COM1B1) |(1<<COM1A0);
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
 
  ICR1 = 9;
 
 
  while( 1 )
  {  OCR1A = 4;
     for(i=0;i<100;i++)
     OCR1B = 4;
  };  
}

Oder muss ich hier trotzdem den OCR1A auf 3 setzen?
Mein Takt ist 6MhZ heißt das also er wartet 0,1ms mit dieser Schleife?
Achja, und mein µC hat sowieso nichts anderes zu tun als diese 2 PWM zu 
erzeugen, also ist es egal wie ausgelastet er nur mit diesen PWM ist.
Danke

Autor: lesso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aber das kann ja garnicht funktionieren weil der timer ja nen interrupt 
auslöst wenn er bei 10 ist und dabei werden ja die beiden pwm 
gleichzeitig gesetzt bzw. Gelöscht werden aber gibts eine andere 
möglichkeit zb. Den timer 0 oder 2 zu verwenden ? Aber bei denen kann 
ich ja keine obergrenze einstellen wo mein interrupt auslöst der ist ja 
immer bei 255 oder?

Autor: Jim G. (jimg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welcher Interrup?

Das was ich sehe, sieht nach kein Interrup aus. Kann auch sein, dass ich 
bei AVRs den Interrup noch nicht kenne... Habe bis jetzt nur SAB-µC 
programmiert.


Ich würde es so schreiben:
#include <avr/io.h>
 
int main()
{ int i;

  do
  {
  DDRD = (1 << PD4) | (1 << PD5); 
 
  TCCR1A = (1<<COM1A1) | (1<<WGM11) | (1<<COM1B1) |(1<<COM1A0);
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
 
  ICR1 = 9;  

   OCR1A = 4; 
     for(i=0;i<100;i++)
     {}
   OCR1B = 4;
  }
  while(1);  
}


Autor: lesso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo
Habe deinen code probiert aber es funktioniert nicht hat noch jemand 
eine idee?

Mfg

Autor: Mehmet Kendi (mkmk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Stichwort heisst "Dead Time Generator" und ist z.Bsp. bei einigen 
AtTiny's eingebaut (z.Bsp. AtTiny45).

Autor: Lesso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja diese µC kenn ich wo das eingebaut ist, allerdings habe ich den nicht 
bei der Hand und möchte ihn auch nicht extra nur für diese 
verhältnismäßig "einfache" Anwendung kaufen. Muss doch auch eine andere 
Möglichkeit geben

Autor: Jim G. (jimg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du auch die Verzögerung groß genung gewählt... du muss 
berücksichtigen, dass der mit voller Kapa zählt... also 16Mio 
Zählvorgänge in der Sekunde... und da er nur bis 100 zählt schaft er das 
in 0,00000625 Sekunden (6,25µs)... kann eventuel was kurz sein. Ich weiß 
ja nicht wieviel zeit unterschied sein muss. Ich würde zum test wirklich 
mal was übertreiben und 50ms wählen, also bis 800.000 zählen lassen.

Ach ja... die Zählgeschwindigkeit ist +-... ich gehe mal davon aus, dass 
du keinen Quarz angschlossen hast, der genau 16Mhz liefert.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn der µC eh nichts anderes tun soll. Polle die ganze Zeit den 
Ausgangspin der PWM und wenn er gesetzt wird wartest deine "Totzeit" ab 
und dann schaltest ihn erst auf 0. Analog hierzu dann das 1 setzen.

Statt dem pollen kann man das natürlich auch per Interrupt lösen. Dann 
eben die Interrupts die der Timer bereitstellt nutzen.

Autor: Lesso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, kannst mir das genauer erklären verstehe gerade nicht ganz wie du 
das meinst !?
Danke

Autor: Jim G. (jimg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Interrup ist eine Anweisung, die neben den Hauptprogramm läuft...

der Timer-interrup kann also im Hintergrund zählen und unterbricht das 
Hauptprogramm und führ seine anweisung aus... nach der anweisung macht 
das Hauptprogramm an der stelle weiter, wo es auf gehört hat.

Autor: Lesso (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, was ein Interrupt ist, weiß ich, nur was "Gast" mit seinem Posting 
meinte, hab ich absolut nicht verstanden

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jim G. schrieb:
>
>   TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
>   ICR1 = 9;
> 

Deine PWM dauert also 10 CPU-Zyklen, das ist sportlich.
Da kannst Du nichts mehr in C machen und erst recht nichts mit 
Interrupts.

Die einzige Möglichkeit ist purer Assembler.
Aber da ist der Mega32 mit Atombomben auf Pantoffeltierchen geschossen.
Ein ATtiny13 reicht da dicke.

>
>    OCR1A = 4;
>      for(i=0;i<100;i++)
>      {}
>    OCR1B = 4;
> 

Das ist Quatsch.
Es ist wurscht, wann Du die PWM-Register setzt, sie werden immer mit 
TCNT1 verglichen. Ein gleicher Wert setzt also die Pins zur gleichen 
Zeit.


Peter

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>      for(i=0;i<100;i++)
>      {}

Was ich hier so die letzten Tage gelesen habe könnte es sein, dass 
dieser Code-Schnippsel sowieso vom Compiler wegoptimiert wird?

Autor: MeinerEiner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wird wegoptimiert, weil nutzlos.
Die Zählvariable als volatile markieren, dann bleibt sie drin.
Oder in der for ein nop ausführen lassen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.