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 |
2 | ----+-----+-----+-----+------+-------------------+----------- |
3 | 0 0 0 0 0 Normal 0xFFFF |
4 | 1 0 0 0 1 PWM, p c, 8-bit 0x00FF |
5 | 2 0 0 1 0 PWM, p c, 9-bit 0x01FF |
6 | 3 0 0 1 1 PWM, p c, 10-bit 0x03FF |
7 | 4 0 1 0 0 CTC OCR1A |
8 | 5 0 1 0 1 Fast PWM, 8-bit 0x00FF |
9 | 6 0 1 1 0 Fast PWM, 9-bit 0x01FF |
10 | 7 0 1 1 1 Fast PWM, 10-bit 0x03FF |
11 | 8 1 0 0 0 PWM, pf c ICR1 |
12 | 9 1 0 0 1 PWM, pf c OCR1A |
13 | 10 1 0 1 0 PWM, p c ICR1 |
14 | 11 1 0 1 1 PWM, p c OCR1A |
15 | 12 1 1 0 0 CTC ICR1 |
16 | 14 1 1 1 0 Fast PWM ICR1 |
17 | 15 1 1 1 1 Fast PWM OCR1A |
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 :-(
Schau mal ins Datenblatt, in welchem Register WGM12 und WGM13 liegen, danach sollte es gehen. ;-)
@ 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) |
2 | TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11); //Prescaler 8 |
3 | ICR1 = 20000; |
>zum kotzen und ich finde den fehler nicht, alles doppelt überprüft, nix >:-( Das nennt man eine Doppel-Blind Studie ;-)
aahhh die völlige blindheit..... kaum macht mans richtig schon gehts :-) DANKE, Jungs!
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.