PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PWM mit ATmega644



Dirk
02.09.2015, 08:51
Hallo ATmega Spezialisten,

ich stehe auf dem Schlauch.

Ich möchte eine PWM von 10 kHz mit den Timern 0 und 1 des ATmega644 erzeugen.

Gewünschte Bedingungen:
F_CPU = 20 MHz
Timer 0: PWM Mode 3 (Fast PWM, TOP 0xFF, Prescaler 8 )
Timer 1: PWM Mode 14 (Fast PWM, TOP ICR1, Prescaler 8 )

Timer 0:


TCCR0A = (1<<COM0A1)|(0<<COM0A0)|(1<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(1<<WGM00);
TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(1<<CS01)|(0<<CS00);


Timer 1:


TCCR1A = (1<<COM1A1)|(0<<COM1A0)|(1<<COM1B1)|(0<<COM1B0)|(1<<WGM11)|(0<<WGM10);
TCCR1B = (0<<ICNC1)|(0<<ICES1)|(1<<WGM13)||(1<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10);
TCCR1C = 0;
ICR1 = 249; // 10kHz


Was ist mein Problem?
Timer 0 produziert eine wunderbare PWM mit 10 kHz (genau 9766 Hz).
Timer 1 zeigt mit Oszi aber eine PWM von 20 kHz.

Kann mir jemand sagen, was ich übersehe?

oberallgeier
02.09.2015, 09:35
.. ich stehe auf dem Schlauch .. F_CPU = 20 MHz .. Timer 1: PWM Mode 14 (Fast PWM, TOP ICR1, Prescaler 8 ) ..Hmmm, zuerst mal nur so: die Nullen werden üblicherweise nicht geschrieben; zum Start sind die Register genullt und meist schaltet man zur Laufzeit nicht dauernd um . . . WENN Du etwas explizit löschen möchtest dann ist dies üblich:

TCCR1A &= ~(1<<COM1A1)|(1<<COM1B1); // Clear/set OC1A/OC1B on Cmp Match S132
So. Deine Timer1-initialisierung, modifiziert (und jedenfalls für MICH übersichtlicher und informativer - NUR Befehle machen selbst Profis nicht oft)

TCCR1A |= (1<<COM1A1)|(1<<COM1B1); // Clear/set OC1A/OC1B on Cmp Match
TCCR1A |= (1<<WGM11); // Mode Fast PWM, TOP ICRn, 1. Teil
TCCR1B |= (1<<WGM13)|(1<<WGM12); // Mode Fast PWM, TOP ICRn, 2. Teil
TCCR1B |= (1<<CS11); // clkI/O/8 (From prescaler)
// => 20e6/8 = 2 500 000
TCCR1C = 0; // Wo in Deinem Code wird denn
// IRGENDEIN Bit auf 1 gesetzt ??
// Würde ich nicht coden
ICR1 = 249; // 10kHz (F_CPU / (Prescaler * (ICR1 + 1)))
// Die 10k sind ein netter Wunsch aber ..
// .. das Timing Diagramm auf S 121 des
// ATmega164A-PA_bis_1284-P_8272G_01-15
// erklärt, dass es doch 20 kHz sind.
// Daher der Name "FAST"-PWMAnmerkung: Fehler vorbehalten, ich habs ja nicht getestet ;-))

Bei mir wird z.B. so initialisiert
// ===== s. Dokument ATmega164A-PA_bis_1284-P_8272G_01-15
// ================================================== =========================== =
// == PWM-Routinen zur Motoransteuerung
void TC1PWM_init(void) //Init Timer/Counter1 f Erzeugung des PWM-Signals
{ //
TCCR1A &= ~(1<<COM1A1)|(1<<COM1B1); // Clear/set OC1A/OC1B on Cmp Match S132
// DISABLED OC1A/OC1B bzw Port PB1/B2, ERST mit Motorstart enablen
TCCR1A |= (1<<WGM10); // Dazu noch
TCCR1B |= (1<<WGM12); // Fast PWM, 8 Bit TOP=0xFF=dez255 133
TCCR1B |= (1<<CS11); // Prescaler ist clk/8 => 9,8 kHz 135
// theoretisch: 20 MHz / 8 / 255 => 9,803922 kHz, DMM-Messung 9,78 kHz
TIMSK1 &= ~(1<<OCIE1A)|(1<<OCIE1B); // T/C1 Oput CmpA+B Match intrrpt dsabld
TIMSK1 &= ~(1<<TOIE1); // T/C1 Ovrflw intrrpt dsabled ~S137
OCPWM1 = 0; // PWM auf Null setzen
OCPWM4 = 0; // PWM auf Null setzen
isum12 = isum34 = 0;
ie_mot12 = ie_mot34 = 0;
ie_alt12 = ie_alt34 = 0;
} // Ende void TC1PWM_init(void)
// ================================================== =========================== =

PS: Kleine Erkläuterung zum Nullen eines Bits
TCCR1A &= ~(1<<COM1A1);
TCCR1A ... Ziel
& ... UND-Operator
&= ... das UND als Zuweisungsoperator,
=> weist das Ziel als Parameter zu
~ ... der unäre Operator bildet das
Bit-Komplement => "1" (in 1<<COM1A1)
wird zur "0"

Dirk
02.09.2015, 10:03
Hi oberallgeier,

danke für deine schnelle Antwort!


Die 10k sind ein netter Wunsch aber ..
.. das Timing Diagramm auf S 121 des
ATmega164A-PA_bis_1284-P_8272G_01-15
erklärt, dass es doch 20 kHz sind.
Daher der Name "FAST"-PWM
Ja, aber genau von der Seite 121 stammt ja meine Formel zur Berechnung von TOP (ICR1 = 249):
f_PWM = f_I/O / (N * (1 + TOP))
... also:
f_PWM = 20000000 / (8 * (1 + 249))
= 20000000 / 2000
= 10000 Hz = 10 kHz

Denkst du, das stimmt so nicht?

oberallgeier
02.09.2015, 10:31
.. Ja, aber genau von der Seite 121 stammt ja meine Formel zur Berechnung von TOP (ICR1 = 249) .. Denkst du, das stimmt so nicht?Hmmmmm, also bei Dokumentationen mit mehr als 500 Seiten denke ich nicht mehr soooo oft, da hilft mir z.B. manchmal der Frequenzanalysator weiter . . .

Auf Seite 121 der von mir genannten Dokumentation steht keine einzige Formel. Die von Dir zitierte Formel steht in der zitierten Dokumentation auf Seite 122 - und sorry für diese Pingeligkeit. Warum hast Du Dich entschieden, das Clear/Set-Bit zu aktivieren? Was bewirkt das ? Da steht doch im Abschnitt 16.10.3 Fast PWM mode weit unten (S 122) noch ne Anmerkung dazu !? Wie geschrieben - für mich sind die Erklärungen nicht immer soooo verständlich mit all den Flags auf wenn und aber . . . ;-)

Searcher
02.09.2015, 11:55
... Kann mir jemand sagen, was ich übersehe?

Die Konfiguration scheint mir richtig zu sein. Die OCR Register der beiden Timer werden aber zu unterschiedlichen Zeiten aktualisiert. Timer0 im Mode 3 update OCRn at TOP, Timer1 im Mode 14 update OCRx at BOTTOM.

Problem könnte deshalb vielleicht im übrigen Programm liegen?

Gruß
Searcher

Dirk
02.09.2015, 12:40
@oberallgeier:
Clear/Set-Bit?
Meinst du COM1A1/COM1A0? Die habe ich auf nicht-invertierende PWM (1:0) eingestellt.

@searcher:

Die OCR Register der beiden Timer werden aber zu unterschiedlichen Zeiten aktualisiert. Timer0 im Mode 3 update OCRn at TOP, Timer1 im Mode 14 update OCRx at BOTTOM.
Das muss ich mir ansehen. Vielleicht mit Mode 1 (8-Bit Fast PWM)? Aber: Kann dadurch die PWM Frequenz anders sein als in der Berechnung, die ja für alle Fast-PWM Modi gelten müßte?

Problem könnte deshalb vielleicht im übrigen Programm liegen?
Das besteht zum Test nur aus einer Schleife, in der der PWM-Wert rauf und runter gezählt wird. Die PWM funktioniert auch bei beiden Timern gut, d.h. die angeschlossenen Motoren werden normal angesteuert.

Searcher
02.09.2015, 13:11
@searcher:
Das muss ich mir ansehen. Vielleicht mit Mode 1 (8-Bit Fast PWM)? Aber: Kann dadurch die PWM Frequenz anders sein als in der Berechnung, die ja für alle Fast-PWM Modi gelten müßte?

Mode 1 für Timer1 könntest Du ja mal ausprobieren. PWM Frequenz sollte sich normalerweise nicht durch den Updatezeitpunkt der OCRn ändern. Wenn die COM Bits aber bei beiden Timern gleich zB auf nicht invertierendem PWM stehen, könnte der Beschreibzeitpunkt der OCRn durch das Programm unterschiedliche Auswirkungen haben. Ich habe das nicht komplett durchdacht und versuche jetzt aber nicht weiterzudenken :) ...

Mir fiel nur nix Besseres ein - außer Meßfehler oder HW-Fehler (zB Kurzschluß zu irgendetwas, daß noch einen Zyklus hinzufügt) Wie gesagt, Konfiguration scheint mir richtig zu sein.



Das besteht zum Test nur aus einer Schleife, in der der PWM-Wert rauf und runter gezählt wird. Die PWM funktioniert auch bei beiden Timern gut, d.h. die angeschlossenen Motoren werden normal angesteuert.

Programm auf das unbedingt notwendigste reduzieren und wenn Fehler noch drin, das Minimalprogramm mal posten.

Gruß
Searcher

Dirk
02.09.2015, 18:05
@Searcher:
Ich habe jetzt mal die 8-Bit Fast-PWM (Mode 5: WGM13:10 = 0101) getestet:
Timer 1:


TCCR1A = (1<<COM1A1)|(0<<COM1A0)|(1<<COM1B1)|(0<<COM1B0)|(0<<WGM11)|(1<<WGM10);
TCCR1B = (0<<ICNC1)|(0<<ICES1)|(0<<WGM13)||(1<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10);

Das geht auch, ist aber auch lt. Oszi eine 20 kHz PWM.

Merkwürdig ...

Hat jemand von euch ein Oszi oder Frequenzmesser und kann evtl. mal den Mode 14 nachmessen?

oberallgeier
02.09.2015, 19:42
.. Hat jemand von euch ein Oszi oder Frequenzmesser und kann evtl. mal den Mode 14 nachmessen?Kann ich machen, mach ich gern, denn es interessiert mich ja selbst. Aber ich hab grad stundenlages Herumspielen mit dem Oskar an einer SDA bei I²C-Taktraten zwischen 40 k und 500 k hinter mir, hab diese Bildschirmrätsel eben abgeschaltet und weggeräumt. Sprich: für heut is der Riemen runter. ABer vielleicht hat jemand anders Lust - TV is eh mies, Wetter s..feucht . . .

Trotz allem: schönen Abend.

Übrigens - der Code sieht weiterhin - ähhhh - xxxzensiert (*ggg*) aus.

Dirk
02.09.2015, 19:58
So, ich gebe auf. Ich habe mehrere Modi, Prescaler und TOP Werte probiert:
Ergebnis: Frequenz bleibt konstant, egal welche Werte ich einsetze. PWM ist aber von 0 bis 100% Duty nutzbar.
Lediglich die Änderungen an COM1A1/COM1A0 und COM1B1/COM1B0 zeigen Wirkung: Tatsächlich wird das PWM Signal invertiert.

Jetzt kommt der Hammer:
Dies hier:


TCCR1A = (1<<COM1A1)|(0<<COM1A0)|(1<<COM1B1)|(0<<COM1B0)|(1<<WGM11)|(0<<WGM10);
TCCR1B = (0<<ICNC1)|(0<<ICES1)|(1<<WGM13)||(1<<WGM12)|(0<<CS12)|(0<<CS11)|(0<<CS10);

Was denkt ihr, was passieren müßte (Auflösung: Timer gestoppt)?
Bei mir: PWM 20 kHz.
Ich gebe auf.

P.S.: Kann man vor Auslieferung eines ATmega z.B. Bits in TCCRxA/B so festlegen, dass sie via Programm im Flash nicht mehr zu ändern sind?
Oder kann man so etwas in einem Bootloader machen?
Grund der Frage: Ich habe das ATmega644 Board nicht neu, sondern gebraucht übernommen.
Mich irritiert nämlich, dass alle Änderungen (bis auf COM1A1/COM1A0 und COM1B1/COM1B0) keinen erkennbaren Effekt auf die Timerfunktion haben.

markusj
02.09.2015, 21:43
Dirk, in der Zeile zu TCCR1B ist ein Fehler. Du hast || geschrieben, macht ein logisches statt binärem Oder. Damit wird TCCR1B mit dem Wert 1 beschrieben.was das bewirkt.

mfG
Markus

Dirk
02.09.2015, 22:10
Schöne Sch***se, da habe ich jetzt Stunden sinnlos zugebracht!

Danke Markus! Danke.

Das war's.

Searcher
03.09.2015, 07:55
Schöne Sch***se, da habe ich jetzt Stunden sinnlos zugebracht!


Asche über Dein Haupt und über meines :(;):)

Gruß
Searcher