mikrocontroller.net

Forum: Compiler & IDEs Probleme mit PWM Erzeugung


Autor: Simon Hi (himmsi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich hab folgendes Problem. Ich möchte am Port D Pin 5 eines Atmega88 ein 
PWM Signal generieren. Allerdings klappt das ganze nicht. Im folgenden 
meine PWM Initialisierung.

Vielen Dank schon mal für Eure Hilfe!!
void pwm_generator(void)
{
  DDRD |= (1<<PD5);
  TCCR2A  |=  (1<<WGM21) |  (1<<WGM20);    //Modevorwahl Fast-PWM
  TCCR2A  |=  (1<<COM2A1) |  (0<<COM2A0);    //clear on Compare-match

  TCCR2B  |=  (0<<WGM22);                //Modevorwahl Fast-PWM
  TCCR2B  |=  (0<<CS22) |  (1<<CS21) |  (1<<CS20);  //Vorteiler N=23
    
  TIMSK2  |=  (1<<TOIE2);            //Interrupt bei Overflow enable

}


ISR (TIMER2_OVF_vect)    //Interrupt Overflow Timer2
{
  
  OCR2A;    //Vergleichsregister neu beschreiben
  
}

Autor: Magnus M. (magnetus) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OC2A liegt an PB3. Um an PD5 eine PWM zu nutzen musst du den Timer0 
verwenden.

Gruß,
Magnetus

Autor: Simon Hi (himmsi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Au ja, stimmt!

Aber da ich an dem Port D pin 3 auch ein PWM Signal benötige habe ich 
jetzt das Programm mal noch folgendermaßen abgeändert. Ist das Programm 
dann so richtig, um am Port B Pin 3 und am Port D Pin 3 ein PWM Signal 
zu bekommen?

Ich hab nämlich bis jetzt keinen wirklichen Erfolg damit gehabt.

Grüße Simon
void pwm_generator(void)
{
  OCR2A=255;
  OCR2B=255;
  DDRB |= (1<<PB3);
  TCCR2A  |=  (1<<WGM21) |  (1<<WGM20);    //Modevorwahl Fast-PWM
  TCCR2A  |=  (1<<COM2A1) |  (0<<COM2A0);    //clear on Compare-match

  TCCR2B  |=  (0<<WGM22);                //Modevorwahl Fast-PWM
  TCCR2B  |=  (0<<CS22) |  (1<<CS21) |  (1<<CS20);  //Vorteiler N=23
    
  TIMSK2  |=  (1<<TOIE2);            //Interrupt bei Overflow enable
}


ISR (TIMER2_OVF_vect)    //Interrupt Overflow Timer2
{
  OCR2A;    //Vergleichsregister neu beschreiben
  OCR2B;
}

Autor: XXX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ist das
TCCR2B  |=  (0<<WGM22);
             ^
wirklich das, was du willst?

Such mal nach Bitmanipulation!

Gruß
JJ

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon Hi schrieb:

> Ich hab nämlich bis jetzt keinen wirklichen Erfolg damit gehabt.

Nun ja.
Bei Vergleichswerten von 255 würde ich bei einer PWM die auf einem 8-Bit 
Timer läuft auch nicht wirklich grossartig etwas an den Ausgangspins 
erwarten

Autor: Simon Hi (himmsi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die zügige Antwort!!

@ Gast: Ja hast recht, um WGM22 zu setzten muss es mit ner 1 verodert 
werden.

@ Karl heinz Buchegger: Ja natürlich, des sind ziemlich kurze Impulse ;)

So müsste es jetzt eigentlich passen, oder? Allerdings funktioniert es 
noch immer nicht so, wie ich eigentlich will :(
void pwm_generator(void)
{
  OCR2A=1;
  OCR2B=1;
  DDRB |= (1<<PB3);
  DDRD |= (1<<PD3);
  TCCR2A  |=  (1<<WGM21) |  (1<<WGM20);    //Modevorwahl Fast-PWM
  TCCR2A  |=  (1<<COM2A1) |  (0<<COM2A0);    //clear on Compare-match

  TCCR2B  |=  (1<<WGM22);                //Modevorwahl Fast-PWM
  TCCR2B  |=  (0<<CS22) |  (1<<CS21) |  (1<<CS20);  //Vorteiler N=32
    
  TIMSK2  |=  (1<<TOIE2);            //Interrupt bei Overflow enable
}


ISR (TIMER2_OVF_vect)    //Interrupt Overflow Timer2
{
  OCR2A;    //Vergleichsregister neu beschreiben
  OCR2B;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon Hi schrieb:

> So müsste es jetzt eigentlich passen, oder? Allerdings funktioniert es
> noch immer nicht so, wie ich eigentlich will :(

Und was willst du?


> ISR (TIMER2_OVF_vect)    //Interrupt Overflow Timer2
> {
>   OCR2A;    //Vergleichsregister neu beschreiben
>   OCR2B;
> }

Interessanter Code.
Nur bewirkt er nichts.

Autor: Simon Hi (himmsi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich möchte eigentlich ne Motorsteuerung für zwei Gleichstrommotoren zum 
laufen bekommen. Die Vorwahl der Drehrichtung und die anderen 
Programmteile sind bereits fertig und funtionieren, wenn ich den Port, 
auf dem ich das PWM Signal ausgeben möchte, manuell auf "High" setze.

Nun versuche ich bereits seit mehreren Tagen die PWM zum Laufen zu 
bekommen. Da dies mein erstes Projekt mit PWM ist und ich erst wenig 
Erfahrung mit Mikrocontrollern habe, habe ich noch leichte Probleme mit 
dem Lesen und verstehen des Datenblatts. Soviel zu meiner 
"Vorgeschichte".

Jetzt zum Programm. Ich habe zu Beginn erst mal die Definition für die 
PWM an PB3 (OC2A) durchgeführt. Da ich im Datenblatt gelesen habe, dass 
man die PWM mit ner anderen Schrittweite am Port PD3 (OC2B) auch noch 
anlegen kann, dachte ich, man könnte das so deklarieren. Aber dem 
scheint nicht so.

Also möchte ich erst mal das Problem mit mit der PWM am PB3 lösen.

Ich komm einfach nicht weiter und weiß nicht wo ich mit der Fehlersuche 
ansetzen soll. Die folgende Dekleration müsste nach meinem Verständnis 
eigentlich passen (jetzt erst mal um ein PWM Signal am PB3 zu bekommen. 
Wenn ich allerdings mit dem Oszi am Port PB3 das Signal anschaue, kann 
ich keine PWM erkennen.
void pwm_generator(void)
{
  DDRB |= (1<<PB3);
  OCR2A=100;
  TCCR2A  |=  (1<<WGM21) |  (1<<WGM20);    //Modevorwahl Fast-PWM
  TCCR2A  |=  (1<<COM2A1) |  (0<<COM2A0);    //clear on Compare-match

  TCCR2B  |=  (1<<WGM22);                //Modevorwahl Fast-PWM
  TCCR2B  |=  (1<<CS22) |  (1<<CS21) |  (1<<CS20);  //Vorteiler N=1024
    
  TIMSK2  |=  (1<<TOIE2);            //Interrupt bei Overflow enable
}


ISR (TIMER2_OVF_vect)    //Interrupt Overflow Timer2
{
  OCR2A;    //Vergleichsregister neu beschreiben
}

Autor: Bernadette (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deswegen benutze ich BASCOM:

Config Timer1=Pwm,Pwm=9,Compare A Pwm=Clear Up,Compare B 
Pwm=Disconnect,Prescale = 1

Locate 1 , 1 : Lcd "PWM-Test"
Wait 1

Cls
Do

U1 = Getadc(1)

If U1 > 512 Then
   Direction = 1 : U1 = U1 - 512
Else
   Direction = 0 : U1 = 513 - U1
End If

If U1 > 510 Then U1 = 510

Pwm1a = U1

loop

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon Hi schrieb:

> Ich komm einfach nicht weiter und weiß nicht wo ich mit der Fehlersuche
> ansetzen soll.

Warum hat dein Code, als ich vor 3 Minuten hier reingesehen habe, noch 
ganz anders ausgesehen? Da war das Schalten auf Output bzw das Setzen 
von OCR2A noch nicht drinnen.

Poste deinen Originalcode!
Wenn der umfangreich ist, dann erzeuge ein Demoprojekt, das in sich 
vollständig ist und dein Problem zeigt.

Aber wenn du deinen Code extra fürs Forum jedesmal händisch umarbeitest, 
dann weiß man nie ob du in deinem realen Projekt dieselben Probleme 
hast!

Ein Demoprojekt nur für die PWM mit dem Timer 2 wäre sowieso angebracht. 
Dann könntest du nämlich ein komplettes Programm zeigen und nicht immer 
nur äußerst seltsame Ausschnitte, wie zb die Overflow ISR

Autor: Simon Hi (himmsi)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So ich hab den Code nun angehängt. Die Overflow ISR stammt aus 
vorherigen versuchen, als ich versucht habe, die Pulsweite zu verändern.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hier

  TCCR2A  |=  (1<<WGM21) |  (1<<WGM20);    //Modevorwahl Fast-PWM
  TCCR2B  |=  (1<<WGM22);                //Modevorwahl Fast-PWM


ergibt Modus 7.
In diesem Modus ist OCRA aber der Top-Wert und nicht der Vergleichswert. 
Du willst Modus 3 (der Timer läuft durch von 0 bis 0xFF, beide OCR 
Register stehen zur PWM Erzeugung zur Verfügung), darfst also WGM22 
nicht setzen.

(Siehe Tabelle 17-8 auf Seite 155 im Datenblatt)

Autor: Simon Hi (himmsi)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Vielen dank für den Hinweis!!

Aus dem Datenblatt konnte ich diesen Unterschied nicht ablesen. Jetzt 
hab ich es geändert und es funktioniert!! Das mit dem PWM Signal am Port 
PD3 hab ich jetzt auch hinbekommen.

Vielen Dank nochmal!!

Im Anhang nochmal der funktionierende Code.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon Hi schrieb:
> Vielen dank für den Hinweis!!
>
> Aus dem Datenblatt konnte ich diesen Unterschied nicht ablesen.

Drum ist diese Tabelle im Datenblatt so interessant. Da stehen die 
wesentlichen Eckpunkte aller Timer-Modi drinnen. Das ist eigentlich 
meistens mein erster Anlaufpunkt, wenn ich einen Timer Modus auswähle.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was hängt bei dir eigentlich am Port C?

Hintergrund: Du schaltest mir in deinem Programm etwas zuviel an den DDR 
Registern rum.
Wenn du dem Port C am Ende der lese_Eingang die unteren 4 Bits auf 
Ausgang schaltest, sind die Pullups dort noch aktiv. zb ein Taster der 
dort nach Masse gedrückt ist, ist für den AVR dann ein Kurzschluss am 
Ausgang nach Masse. Nicht gut!

In den meisten Programmen stellt man die DDRx am Anfang des Programms 
korrekt ein und dann werden sie in Ruhe gelassen!

Ich seh in deinem Programm eigentlich keinen guten Grund, warum man 
diese 4 Bits am C-Port jemals von Eingang auf Ausgang schalten möchte.

Selbiges für die Motor-Pins. Es gibt im Programm keinen wirklichen 
Grund, warum die alle 100ms erneut auf Ausgang geschaltet werden müssen.

Autor: Simon Hi (himmsi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab am Port C Pin 0 bis Pin 3 ein Display angeschlossen. Das hab ich 
während der Entwicklung des Programms für die Ausgabe von Zuständen 
verwendet. Ist also noch ein überbleibsel. Den Code muss ich erst noch 
ein bisschen bereinigen.

Autor: Simon Hi (himmsi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zudem befinden sich am gleichen Port noch meine vier Taster - ebenfalls 
auf Pin 0 bis Pin 3. Deshalb muss ich immer zwischen Eingang und Ausgang 
umschalten.

Autor: Simon Hi (himmsi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab's geändert. Zu Beginn werden jetzt meine Ausgänge definiert und 
anschließend nicht mehr verändert.

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.