Probleme mit PWM Erzeugung

OP #2008102
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!!
1
void pwm_generator(void)
2
{
3
  DDRD |= (1<<PD5);
4
  TCCR2A  |=  (1<<WGM21) |  (1<<WGM20);    //Modevorwahl Fast-PWM
5
  TCCR2A  |=  (1<<COM2A1) |  (0<<COM2A0);    //clear on Compare-match
6

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

12
}
13

14

15
ISR (TIMER2_OVF_vect)    //Interrupt Overflow Timer2
16
{
17
  
18
  OCR2A;    //Vergleichsregister neu beschreiben
19
  
20
}
OP #2008385
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
1
void pwm_generator(void)
2
{
3
  OCR2A=255;
4
  OCR2B=255;
5
  DDRB |= (1<<PB3);
6
  TCCR2A  |=  (1<<WGM21) |  (1<<WGM20);    //Modevorwahl Fast-PWM
7
  TCCR2A  |=  (1<<COM2A1) |  (0<<COM2A0);    //clear on Compare-match
8

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

15

16
ISR (TIMER2_OVF_vect)    //Interrupt Overflow Timer2
17
{
18
  OCR2A;    //Vergleichsregister neu beschreiben
19
  OCR2B;
20
}
OP #2008708
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 :(
1
void pwm_generator(void)
2
{
3
  OCR2A=1;
4
  OCR2B=1;
5
  DDRB |= (1<<PB3);
6
  DDRD |= (1<<PD3);
7
  TCCR2A  |=  (1<<WGM21) |  (1<<WGM20);    //Modevorwahl Fast-PWM
8
  TCCR2A  |=  (1<<COM2A1) |  (0<<COM2A0);    //clear on Compare-match
9

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

16

17
ISR (TIMER2_OVF_vect)    //Interrupt Overflow Timer2
18
{
19
  OCR2A;    //Vergleichsregister neu beschreiben
20
  OCR2B;
21
}
OP #2008879
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.
1
void pwm_generator(void)
2
{
3
  DDRB |= (1<<PB3);
4
  OCR2A=100;
5
  TCCR2A  |=  (1<<WGM21) |  (1<<WGM20);    //Modevorwahl Fast-PWM
6
  TCCR2A  |=  (1<<COM2A1) |  (0<<COM2A0);    //clear on Compare-match
7

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

14

15
ISR (TIMER2_OVF_vect)    //Interrupt Overflow Timer2
16
{
17
  OCR2A;    //Vergleichsregister neu beschreiben
18
}
Gast #2008885
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
#2008892
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
#2009226
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)
#2009827
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren