PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PWM funktioniert nicht



Ozzy
25.12.2007, 14:47
Hi,

ich habe eben schon bei der Hardware-Ecke gepostet, aber möchte hier noch einmal mein Problem vorstellen, falls es doch ein Software-Problem ist. und zwar probiere ich PWM auf dem AtMega128 hinzubekommen.

Hier erst einmal mein Code (Ausschnitt):


void pwm_init( void ) {
DDRB=0xff;
PORTB=0x00;
TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);
TCCR1A = (1<<WGM11)|(1<<WGM11)|(1<<COM1A1)|(1<<COM1A0);
}

void pwm_setpwmvalue( uint16_t value ) {
OCR1A = value;
}


In der main() rufe ich dann erst
pwm_init(); und dann
pwm_setpwmvalue( 100 ); auf. Doch an PB5 ist nichts zu sehen. Habt Ihr eine Idee, woran das liegen könnte???

MfG, und vielen Dank, Ozzy

linux_80
25.12.2007, 15:25
Hi,

evtl. kannst du noch in dem anderen Thread scheiben, dass es hier um das gleiche Thema geht !

Du setzt den Timer in Modus 14, dazu muss doch auch bei ICR ein Wert stehen, mit Defaultwert 0 zählt er nicht weit.

Evtl. auch interessant: Wie schnell wird der AVR getaktet ?


Edit:
Und immer daran denken:
Der AVR macht es so wie man es ihm sagt, und nicht wie man es meint !!

Ozzy
25.12.2007, 15:49
Hi @linux_80; habe ich soeben gemacht.

An sich soll es so etwas ähnliches wie ein Frequenzmodulator werden, das einmal im Voraus. Die Taktung des Atmega beträgt 14,7456Mhz.
Ich kenne mich mit diesen Timer-Geschichten nicht gut aus, das mit dem ICR sagt mir auch nicht viel, aber ich werde mal danach suchen.

Aber warum das jetzt so gar nicht funktioniert...

Ozzy
25.12.2007, 15:56
Habe gerade gesehen, dass es nicht Mode 14, sondern Mode 15 ist, und TOP = OCR1A ist...

H.A.R.R.Y.
25.12.2007, 18:54
Hi,

Dein Code enthält 2xReferenz auf WGM11
"TCCR1A = (1<<WGM11)|(1<<WGM11)|(1<<COM1A1)|(1<<COM1A0);"

Das sieht nach Tipfehler aus. Im Datenbaltt steht eigentlich alles, was man dazu wissen muß und richtig eingegeben läuft der Timer auch an.
Die Ports sind ja auch alle schön auf output gestellt.

Ozzy
26.12.2007, 08:26
@H.A.R.R.Y: danke, das hatte ich (trotz mehrfachen Lesens) nicht gesehen! Muss natürlich richtig:



TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);
TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1)|(1<<COM1A0);

heißen. Werde morgen mal ausprobieren, ob es das war. Denn ansonsten sieht doch alles richtig aus, oder? Oder habe ich etwas vergessen zu initiallisieren?

MfG, Ozzy

roboterheld
26.12.2007, 14:23
da gibt es ein schönes datenblatt über den atmeg128.

sind auch schöne c-beispiele drin, die du suchst.

IRQ
26.12.2007, 17:20
Hallo Ozzy,

ich quäle mich auch gerade mit dem Thema herum. Bin ein Stückchen weiter, bei mir funktioniert der eine PWM-Pin nämlich schon (PB1/OC1A):


TCCR1A = (1<<WGM10)|(1<<COM1A1); // PWM, phase correct, 8 bit.
TCCR1B = (1<<CS11) |(1<<CS10); // set clock/prescaler 1/64 -> enable counter

DDRB = 1<<PB1; // Port B1 als Ausgang
OCR1A=127; // 50%


Muss zugeben, dass ich das Größtenteils aus dem Netz gefischt habe, auch wenn ich es mittlerweile halbwegs durchblicke. Mir ist es aber noch nicht gelungen OC1B zu aktivieren...

Ozzy
26.12.2007, 17:46
Danke, die hatte ich gesehen; hatte aber eben meine Fehler nicht gesehen. Werde dann morgen früh mal probieren, ob jetzt alles funktioniert. Hoffentlich war das auch der einzige Fehler. Falls Euch nichts mehr auf die schnelle einfällt...

MfG, und vielen Dank noch einmal, Ozzy

Ozzy
27.12.2007, 09:04
So, neuer Tag, neuer Versuch! Mit dem Code von IRQ (danke noch einmal), habe ich geschafft, das Ding zum Laufen zu bringen (mit ein paar Änderungen).
Aber leider läuft es noch nicht so, wie ich es gerne hätte, denn das Problem lag wohl beim "Fast PWM"
Ich verwende jetzt diese Konfiguration:


TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1)|(1<<COM1A0);
TCCR1B = (1<<CS10);

Die mir eben nur eine zu geringe Frequenz liefert. Probiere ich dann

TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);
Dann geht nichts mehr.

Habt Ihr eine Idee, woran das liegt? Bin echt am Verzweifeln...


Vielen Dank im Voraus, Ozzy

IRQ
27.12.2007, 11:22
Wenn die Frequenz zu gering ist, liegt das entweder am Oszillator oder am Prescaler (vermutlich letzteres). Glaube den ändert man mit den CS1X Bits.

Hubert.G
27.12.2007, 11:49
Bist du mit WGM12 und WGM13 nicht wieder bei Fast-PWM. Du könntest auch von 10bit auf 9bit zurückgehen dann würde sich die PWM-Frequenz verdoppeln. Wie hoch soll deine PWM-Frequenz denn sein?

IRQ
27.12.2007, 23:29
So, bei mir ist der Durchbruch gelungen :-)

Jetzt hab ich die ganze Registerfummelei endlich durchblickt. Habe jetzt beide PWM-Pins am Counter1 aktivieren und für meine Zwecke konfigurieren können. Letztendlich lag es daran, dass die Angaben für COM1Bx gefehlt haben.

Was untenstehender Code tut, ist dokumentiert. Mir reicht im Gegensatz zu Ozzy 8-bit PWM, daher ist die Konfig etwas anders. Die OCR1x Register geben an, ab wann der Pin auf Low gelegt wird (also je höher der Wert, desto länger liegt HIGH an). Was ganz praktisch ist beim Testen: Prescaler auf 1024 stellen, dann kann man die LED schon blinken sehen :-)

Ich teste das jedoch mit einem Motor (mit nem L293d) und der macht komische Summgeräusche, wenn ich den Prescaler z.B. auf /8 setze. Bei /64 hört man jedoch kräftigere Vibrationen. Ist das normal oder gibts da nen Trick dagegen?


DDRB |= (1<<PB1)|(1<<PB2); // Port B1/B2 als Ausgang

TCCR1A =
(1<<COM1A1)|(0<<COM1A0)| // PB1 auf low, wenn TOP1 (->OCR1A) erreicht
(1<<COM1B1)|(0<<COM1B0)| // PB2 auf low, wenn TOP2 (->OCR1B) erreicht
(0<<WGM11)|(1<<WGM10); // PWM, phase correct, 8 bit

TCCR1B = (0<<CS12)|(1<<CS11)|(1<<CS10); // Prescaler auf /64

OCR1A=127; // On-Zeit für PB1
OCR1B=30; // On-Zeit für PB2

Hubert.G
28.12.2007, 10:16
Mit der PWM schaltest du den Motor ja dauernd ein und aus, das sind die Geräusche. 3kHz PWM-Frequenz sind angeblich ideal, ich habe mich mal ein bisschen gespielt damit im Bereich von 500Hz bis 3kHz und konnte ausser den Geräuschen keine Änderung feststellen, man würde da wahrscheinlich einen Leistungsprüfstand benötigen um etwas konkret festestellen zu können. Ausserdem wird auch zwischen den Motoren ein Unterschied sein.

IRQ
28.12.2007, 11:29
Danke für's Feedback. Wäre es nicht möglich, die Rechtecksignale etwas zu glätten? Wie macht man das Schaltungstechnisch am einfachsten? Elko gegen Masse, oder ist der nicht schnell genug? Kapazität?

*Edit: Habe gerade das hier gefunden:

http://www.mikrocontroller.net/articles/Pulsweitenmodulation#DA-Wandlung_mit_PWM

Scheint nicht ganz so einfach zu sein, wenn man das sauber machen will...

Hubert.G
28.12.2007, 11:56
Ich würde versuchen die PWM-Frequenz in einen Bereich zu legen in dem sie nicht so stört. Alles andere bringt nur zusätzliche Verluste und keinen weiteren positiven Effekt.