Hi,
ich habe ein Problem. Ich möchte eine PWM mit einer Frequenz von 50Hz
erzeugen.
Das TUT zur PWM habe ich gelesen, daraus entstanden aber noch ein paar
Fragen.
Zur Ausgangssituartion:
Ich habe einen Atmega88 mit 8Mhz (CLKDIV8-Fuse= 0).
Möchte über den Timer 1 die PWM erzeugen und am PinB 1 ausgeben.
Folgendes habe ich schon rausgefunden:
1. PB1 als Ausgang und CPU-Takt definieren:
#define F_CPU 8000000
PORTB |= (1<<PB1);
DDRB |= (1<<PB1);
2. PMW initialisieren:
TCCR1A = (1<<COM11)|(1<<WGM10)|(1<<WGM11); //Nichtinv. PWM, 10Bit PWM
TCCR1B = (1<<CS12); //Prescaler 254
//Dadurch komme ich laut meiner Berechnung auf:
//eine Tastrate von 630 takte pro 20ms
3. Zählwerte einstellen:
Hier liegt der Hase im Pfeffer begraben.
Ich verstehe es so:
OCR1A = 629; //630-1 Ergibt die Periodendauer von 20ms
0CR1B = von 0-629 // Ergibt das Tastverhältnis
Ist das soweit ok?
Getestet habe ich es noch nicht. Aber ich bin mir irgendwie sicher das
das auch nicht so geht.
Es kommt mir so wenig/einfach vor. :-/
Danke schon mal für die Antworten und einen schönen Tag
der Kai
Kai W. schrieb:> ich habe ein Problem. Ich möchte eine PWM mit einer Frequenz von 50Hz> erzeugen.
Wozu? Servo-Ansteuerung?
> TCCR1A = (1<<COM11)|(1<<WGM10)|(1<<WGM11); //Nichtinv. PWM, 10Bit PWM> TCCR1B = (1<<CS12); //Prescaler 254>> //Dadurch komme ich laut meiner Berechnung auf:> //eine Tastrate von 630 takte pro 20ms
Du musst dich entscheiden.
Entweder du gibst die 10 Bit auf, oder du gibst die 630 Takte für die
20ms auf.
Aber eines von beiden musst du aufgeben, denn die beiden Dinge können
nicht gleichzeitig erfüllt werden.
> Ist das soweit ok?
Nein.
Karl Heinz Buchegger schrieb:> Wozu? Servo-Ansteuerung?
nein um einen definierten Wert zuhaben den ich erreichen möchte.
Also eigene Aufgabenstellung.
Außerdem mit einem Tastverhältnis von 0-100%, Servos brauchen doch
1-2ms high und den rest low oder?!
> Du musst dich entscheiden.> Entweder du gibst die 10 Bit auf, oder du gibst die 630 Takte für die> 20ms auf.
Verstehe ich nicht. Ich kann doch mit 10Bit bis 1024 zählen.
>> Ist das soweit ok?>> Nein.
Hab ich mir gedacht
Kai W. schrieb:> um einen definierten Wert zuhaben den ich erreichen möchte
Na, dann definiere mal!
Brauchst du die Frequenz von 50Hz exakt oder willst du bis 1024
zählen?
Kai W. schrieb:> Karl Heinz Buchegger schrieb:>>> Wozu? Servo-Ansteuerung?>> nein um einen definierten Wert zuhaben den ich erreichen möchte.> Also eigene Aufgabenstellung.>> Außerdem mit einem Tastverhältnis von 0-100%, Servos brauchen doch> 1-2ms high und den rest low oder?!
Schon.
Aber die Wiederholrate ist 20ms. Und gerade Neulinge kleben zu sehr an
diesen 20ms, die in Wirklichkeit völlig unkritisch sind.
>> Du musst dich entscheiden.>> Entweder du gibst die 10 Bit auf, oder du gibst die 630 Takte für die>> 20ms auf.>> Verstehe ich nicht. Ich kann doch mit 10Bit bis 1024 zählen.
Schon. Aber du musst IMMER bis 1024 zählen. Sonst ist es keine 10 Bit
PWM. Der Begriff '10 Bit PWM' impliziert, dass der Zählbereich des
Timers von 0 bis 1023 geht. Immer.
D.h. entweder eine 10 Bit PWM, oder eine PWM die bis 630 geht (was dann
keine 10 Bit mehr sind). Aber beides gleichzeitig geht nicht.
Du kannst nicht zu deinem Kumpel sagen: Du zählst jetzt immer bis 10,
aber bei 6 fängst du wieder bei 0 an.
In dieser Anweisung ist ein logischer Fehler :-)
Sieh dir die anderen PWM-Modi an. Es gibt auch welche, in denen du den
Wert, bis zu dem zu zählen ist vorgeben kannst. (Im Datenblatt bei den
Timermodi in der Spalte 'TOP' nachsehen. Wenn dort ein Register steht,
dann ist das so ein Modus)
Also: was ist dir wichtiger?
die 20ms (und damit ein Zählbereich bis 630 und daher eine PWM die du in
630 Abstufungen betreiben kannst), oder die 10 Bit (und damit 1024
Abstufungen der PWM)?
Wenn du sowohl die 20ms als auch die 10-Bit haben willst, dann ist deine
einzige Schraube, an der du noch drehen kannst, die Taktfrequenz bzw.
der Vorteiler. Mit dem Vorteiler alleine geht es sich nicht aus, bleibt
nur noch die Taktfrequenz. Aber das will man eigentlich meistens nicht
wirklich
Ah ok, ich habe gedacht, das das die Auflösung der PWM ist.
Jetzt ist es klar. Was ich will. Beides lernen ;-)
Fangen wir doch mal mit den 20ms an.
Wäre das dann nur im Register TCCR1A:
TCCR1A = (1<<COM11);
Und den Wert gebe ich im Register TCNT1 ein?
Also die
TCNT1 = 629;
Wenn ich das hinbekommen habe setzt ich mich dann mit der 10Bit PWM
auseinander. Aber eins nach dem Anderen.
Danke schon mal.
Ich hab was vergessen.
Laut Datasheet müsste das der PWM Mode 8 (PWM, phase and frequency
correct) sein.
da ist der TOP ICR1.
dann müsste dann:
TCCR1A = (1<<COM11)|(1<<WGM13);
oder?
Kai W. schrieb:> Ich hab was vergessen.> Laut Datasheet müsste das der PWM Mode 8 (PWM, phase and frequency> correct) sein.
vergiss mal das phase and frequency correct.
Da geht es um ganz was anderes.
Konzentrier dich erst mal nur auf die Fast-PWM Modi
Diese Modi gibt es
1
Mode WGM13 WGM12 WGM11 WGM10 Timer/counter mode TOP
Du suchst einen Modus, für den gilt
a) Es ist ein Fast-PWM Modus
b) Du kannst die Obergrenze bis zu der gezählt wird, frei festlegen
Aus a) folgt, dass nur die Modi 5, 6, 7, 14 und 15 in Frage kommen.
Aus b) folgt, dass du keine fixen TOP Werte brauchen kannst, damit sind
die Modi 5, 6 und 7 aus dem Rennen, denn bei denen steht in der Spalte
TOP eine fixe Zahl.
Bleiben nur die Modi 14 bzw 15 übrig.
Beide Modi sind Fast-PWM Modi und du kannst per Register festlegen, bis
wie weit dein Zähler zählen wird. Der einzige Unterschied besteht darin,
dass du diese Zählgrenze einmal ins Register ICR1 schreibst und im
anderen Modus ins Register OCR1A.
Welchen der beiden Modi man dann nimmt, hängt davon ab, welches der
beiden Register man gerade nicht braucht. Will man gleichzeitig mit dem
Timer noch Input Capture machen, dann braucht man das ICR1 Register für
den Input Capture und kann es daher nicht zur PWM-Festlegung benutzen.
Will man nicht 1 sondern 2 PWM Ausgänge mit dem Timer machen, dann
braucht man die beiden Compare Match Register OCR1A und OCR1B für die
Festlegung des jeweiligen Tastgrads und kann daher den Modus 15 nicht
benutzen.
Bei dir ist es egal. Du willst weder das eine machen noch das andere.
Daher würde ich der Einfachheit halber den Modus 14 wählen, mit ICR1 als
TOP Register. Damit bleibt dir der A-Kanal des Timers zur PWM Erzeugung
frei und du kannst OCR1A zur festlegung des Tastgrades benutzen, die PWM
kommt am Pin OC1A raus und die COM-Bits COM1A0 und COM1A1 sind für
normal/invertiert zuständig (da ist überall das 'A' drinnen. A wie
A-Kanal vom Timer)
In ICR1 kommen daher die 630 (629 um genau zu sein)
und damit zählt dann der Timer laufend von 0 bis 629. Und da du dich
(hoffentlich) nicht verrechnet hast, bedeutet das, das der Timer das in
1 Sekunde mit dem gewählten Vorteiler und bei der vorgegebenen
Taktfrequenz genau 50 mal schafft. Voila - damit hast du deine 20ms
Modus 14 bedeutet also, dass (siehe Tabelle) WGM13, WGM12, WGM11 auf 1
gesetzt werden müssen und WGM10 bleibt auf 0.
Dann scrollst du im Datenblatt ein wenig hoch und suchst dir die
Tabelle, die für diesen Modus für die COM Bits zuständig ist. In deinem
Fall ist das die Tabelle 16.2 - weil es sich ja um einen Fast PWM Modus
handelt und kriegst damit die COM Bits.
Sicherheitshalber noch nachsehen, in welchem Konfigurationsregister
jedes einzelne der so festgestellten Bits ist ....
... und du hast alle Zutaten beisammen um den Timer konfigurieren zu
können.
Kai W. schrieb:> Und den Wert gebe ich im Register TCNT1 ein?>> Also die>> TCNT1 = 629;
Nein.
Das TCNT1 Register ist der eigentliche Zähler, der Mechanismus der
zählt.
Wenn du einen Wecker hast, den du um 7 Uhr läuten lassen willst,
fummelst du ja auch nicht an den Zahrädern rum, sondern du stellst den
Zeiger des Läutwerks auf 7 Uhr.
Das TCNT1 Register, das lässt du in Ruhe. Das sind 'die Zahnräder'
deiner Uhr, äh, Timers.
Karl Heinz zuerst einmal DANKE für deine ausführliche Antwort.
ich finde es immer sehr schön Beiträge von dir zu lesen.
Sie fordern das denken, und man lernt immer wieder dazu, ohne
überfordert zu sein. TOP
Jetzt ist es klar. Ich habe mich von der "frequenz" leiten lassen.
Das nachste war, das ich fast pwm ausgeschlossen habe, das 50hz ja nicht
fast sondern eher slow sind.
Wenn ich jetzt den Modus 14 wähle, dann scheib ich den Zählwert in den
Register ICR1. Ok.
Schreibe ich den vergleichswert, um die Tastrate einzustellen in den
Register
OCR1?
Kai W. schrieb:> Wenn ich jetzt den Modus 14 wähle, dann scheib ich den Zählwert in den> Register ICR1. Ok.> Schreibe ich den vergleichswert, um die Tastrate einzustellen in den> Register> OCR1?
OCR1 gibt es nicht.
Du meinst OCR1A
Siehe
> Bei dir ist es egal. Du willst weder das eine machen noch das> andere. Daher würde ich der Einfachheit halber den Modus 14 wählen,> mit ICR1 als TOP Register. Damit bleibt dir der A-Kanal des Timers> zur PWM Erzeugung frei und du kannst OCR1A zur festlegung des> Tastgrades benutzen, die PWM kommt am Pin OC1A raus und die> COM-Bits COM1A0 und COM1A1 sind für normal/invertiert zuständig> (da ist überall das 'A' drinnen. A wie A-Kanal vom Timer)
Hi
>Schreibe ich den vergleichswert, um die Tastrate einzustellen in den
Register OCR1?
OCR1 gibt es nicht. Der Timer1 hat zwei Compare-Register: OCR1A und
OCR1B.
Du kannst damit an den Ausgängen OC1A und OC1B zwei PWM erzeugen.
MfG Spess
Ahhh ok.
habe ich überlesen.
Ich fasse zusammen:
Wenn ich 2 PWM mit einem Timer machen möchte Modus 14
Dabei wird in den ICR1 gebe ich den Zählwert ein.
In OCR1A das Tastverhältnis für PB1
In OCR1B das Tastverhältnis für PB2
Input Capture fällt dann weg, weil ich im ICR1 einen Wert vorgegeben
hab.
Im Modus 15 kann ich eine PWM mit einem Tastverhältnis an PB2 ausgeben.
In OCR1A Scheibe ich meinen Zählwert.
In OCR1B das Tastverhältnis.
Der IRC1 bleibt frei, da hier die Incapturefunktion ihren wert rein
schreibt, wenn diese aktiv ist.
Richtig?
Kai W. schrieb:> Im Modus 15 kann ich eine PWM mit einem Tastverhältnis an PB2 ausgeben.> In OCR1A Scheibe ich meinen Zählwert.> In OCR1B das Tastverhältnis.
Gut erkannt (und nenn den 'Zählwert' den 'Top-Wert'. Denn das ist auch
der Begriff der im Datenblatt benutzt wird. Dann gibt es keine
Missverständnisse).
Trotzdem: Gut erkannt.
So mancher hat dass nicht so schnell kapiert, warum er bei OCR1A als
Top, den OCR1A nicht mehr zur Einstellung des Tastgrades verwenden kann.
Danke.
Was mir grade aufgefallen ist, der OCR1A/B ist doch nur jeweils ein 8bit
register oder? Das heist dann ja das ich garnicht bis 629 zählen kann.
Der ICR1 setzt sich doch aus dem ICR1H und ICR1L zusammen, also 16bit.
Daraus schließe ich, das mit gewählter Prescaler doof gewählt ist.
Für 8 bit zu große werte, und bei 16 bit, eine Menge auflösung
verschenkt.
Wenn ich den Prescaler auf 8 setzte, habe ich bei 20ms 20.000 Takte.
Also eine viel größere Auflösung.
Oder wieder was übersehen?
Kai W. schrieb:> Danke.>> Was mir grade aufgefallen ist, der OCR1A/B ist doch nur jeweils ein 8bit> register oder?
Nö.
Das wär ein bischen widersinnig bei einem 16-Bit Timer
> Der ICR1 setzt sich doch aus dem ICR1H und ICR1L zusammen, also 16bit.
Ja, aber darum musst du dich nicht kümmern.
Das macht der Compiler für dich.
Du beschreibst ICR1 und der Compiler dröselt das auf in ICR1H und ICR1L.
Und bei den OCR1A/OCR1B Registern ist es ganz genau gleich.
Für dich als C-Programmierer SIND das 16 Bit Register (auch wenn es die
in Wirklichkeit gar nicht gibt). Denn: wozu hat man denn einen Compiler,
wenn man sich dann erst recht wieder um jeden Kleinscheiss selber
kümmern muss :-)
> Daraus schließe ich, das mit gewählter Prescaler doof gewählt ist.> Für 8 bit zu große werte, und bei 16 bit, eine Menge auflösung> verschenkt.
Ja, so ist das manchmal.
Allerdings: In den wenigsten Fällen spielt die exakte PWM Frequenz
irgendeine spezielle Rolle. Ob du LEDs mit 150Hz dimmst, oder mit 200Hz
ist Jacke wie Hose. Gedimmt müssen sie werden und das Blinken darf man
nicht sehen. Die Frequenz darf also nicht zu klein sein und man benötigt
genügend Abstufungen im Tastgrad - das ist das Entscheidende.
(Und genau deshalb war auch meine erste Frage nach einer
Servo-Ansteuerung. Denn das ist eine der Ausnahmen, bei der es nicht
egal ist, ob man ca. 50Hz oder ca. 400Hz hat)
Karl Heinz Buchegger schrieb:> Ja, aber darum musst du dich nicht kümmern.
Das ist mir klar. War nur zur vollständigkeit.
Achso Vollständigkeit:
Hatten ja 2 fälle.
Die PWM mit Exakter f haben wir jetzt ja behandelt.
Fall 2 wäre dann ja eine ca. PWM f.
Dazu setzte ich die Bits des Registers TCCR1A so das ich Modus 5-7 habe.
Jenachdem habe ich dann ja eine 8 bis 10 Bit PWM mit einem
entsprechenden TOP-WERT (ich lerne die Begriffe ;-) ).
Das Tastverhältniss wird dann wieder im OCR1A/B eingestellt.
ich glaube, ich habe die (fast PWM) verstanden.
Danke !
Ich flippe noch aus,
zuhause direkt an den PC.
TCCR1A = (1<<WGM13)|(1<<WGM12)|(1<<WGM11)|(1<<COM1A1);// PWM MODUS 15
(Fast PWM ICR1)
TCCR1B = (1<<CS11); //Prescaler 8
ICR1 = 20000;
Und OCR1A auf 1000, und siehe da eine f von 1kHz
ich kann an ICR1 rumschrauben wie ich woll es ändert nix....
zum kotzen und ich finde den fehler nicht, alles doppelt überprüft, nix
:-(
@ Kai W. (Gast)
> TCCR1A = (1<<WGM13)|(1<<WGM12)|(1<<WGM11)|(1<<COM1A1);// PWM MODUS 15>(Fast PWM ICR1)
Nö. WGM13 und WGM12 liegen in einem anderen Register. Ausserdem ist das
PWM Mode 14
> TCCR1B = (1<<CS11); //Prescaler 8
Nämlich hier drin.
>ich kann an ICR1 rumschrauben wie ich woll es ändert nix....
Eher so.
1
TCCR1A=(1<<WGM11)|(1<<COM1A1);// PWM MODUS 14 (Fast PWM ICR1)
ich habe mich jetzt doch für den Modus 15 entschieden.
meine Idee war das ich noch ein Signal über die Input Capture einlesen
kann.
Muss ich hierzu nur ICES1 auf 1 setzen und dann kann ich im IRC1 den
Zählwert ablesen?
Also ich hab die ganze zeit noch geschaut.
Ich bekomme den Inputcapture auf timer 1 nicht eingestellt.
meine Idee war zusätzlich zur Timierconfig von oben noch folgendes zu
konfigutieren:
TCCR1B = (1<<ICES1);
ich habe es im TUT so verstanden das immer wenn die Flanke erkannt wird,
der aktuelle wert aus dem ICR1 in das TIFR Register kopiert wird.
Oder ist das noch mehr?
Kai W. schrieb:> meine Idee war zusätzlich zur Timierconfig von oben
wenn du üben willst, dann mach nicht alles auf einmal.
Fang mit dem Input Capture mit einem normal durchlaufenden Timer an.
> noch folgendes zu> konfigutieren:>> TCCR1B = (1<<ICES1);
damit stellst du ein, welche Flanke (steigend oder fallend) den Capture
triggert.
> ich habe es im TUT so verstanden das immer wenn die Flanke erkannt wird,> der aktuelle wert aus dem ICR1 in das TIFR Register kopiert wird.
Nö. Aus dem Zählregister, als TCNT1 ins ICR1.
Aus dem ICR1 kannst du dir den Wert abholen.
> Oder ist das noch mehr?
Einen Interrupt an das Capture Ereignis binden, damit man sich den Wert
auch zeitnah abholt.
Und ... das wars dann auch schon. Input Capture: Tritt am Capture Pin
die entsprechende Flanke auf, wird der aktuelle Zählerstand vom Timer in
einem Register gesichert und (wahlweise) ein Interrupt ausgelöst.
Ganz einfach - so wie praktisch alle Timeroperationen. Da kann ja auch
nicht viel dahinterstecken. So ein Stück gereinigter Sand (Silizium) hat
ja schliesslich die Intelligenz nicht gepachtet.
Ah ok aus dem TCNT1.
Das mit der steigenden/Fallenden Flanke ICES1 0/1, habe ich gefunden,
deshalb auch oben geschrieben.
Habe noch gefunden das er in die beiden Register muss:
TCCR1B = (1<<ICIE1);
TIMSK1 = (1<<ICIE1);
Karl Heinz Buchegger schrieb:> Einen Interrupt an das Capture Ereignis binden, damit man sich den Wert> auch zeitnah abholt.
Den Interupt immer setzten wenn eine Flanke am ICP ist und dann damit
den Wert aus dem ICR1 verarbeiten, bzw in ein von mit definiertes wort
(2byte)
schieben? die bearbeitung dann am besten außerhalb des Interrupts
machen.
wenigstens etwas richtiger?
Kai W. schrieb:> Ah ok aus dem TCNT1.>> Das mit der steigenden/Fallenden Flanke ICES1 0/1, habe ich gefunden,> deshalb auch oben geschrieben.>> Habe noch gefunden das er in die beiden Register muss:>>> TCCR1B = (1<<ICIE1);>> TIMSK1 = (1<<ICIE1);
Äh. nein.
Du musst schon im Datenblatt GENAU lesen!
Bei der Registerbeschrreibung im
TCCR1B (Seite 132) (Timer/Counter Control Register B)
Das Bit heißt ICES1
ICES1 = Input Capture Edge Select vom timer 1
TIMSK1 (Seite 135) (Timer/Counter Interrupt Mask Register)
Das Bit heißt ICIE1
ICIE1 = Input Capture Interrupt Enable vom timer 1
Die Kürzel haben eine (halbwegs) memnonische Bedeutung, damit man sie
sich merken kann.
>> Einen Interrupt an das Capture Ereignis binden, damit man sich den Wert>> auch zeitnah abholt.>> Den Interupt immer setzten wenn eine Flanke am ICP ist und dann damit> den Wert aus dem ICR1 verarbeiten, bzw in ein von mit definiertes wort> (2byte)> schieben? die bearbeitung dann am besten außerhalb des Interrupts> machen.
Na ja. Die 'Bearbeitung' besteht im ersten Schritt in den meisten Fällen
in der Berechnung der Differnz zum vorhergehenden Input Capture. Das
geht noch locker in der ISR. Alles weiterführende, wie zb
Frequenzberechnung, die Behandlung mehrerer Overflows, die während des
Capture aufgetreten sind kann in der ISR sinnvoll sein, kann aber auch
ausserhalb sinnvoll sein.
Wie immer gilt: Dinge die in der ISR unbedingt gemacht werden müssen um
die logische Konsistenz der Daten sicherzustellen in die ISR, alles
weitere (was Zeit hat) ausserhalb.
Die grobe Richtlinie (für alle ISR) lautet: ISR so kurz wie möglich und
so lang wie notwendig.