Datum:
Hi, ich sitze gerade an einem Projekt bei dem ich einen Schrittmotortreiber mittels PWM ansteuern möchte. Dazu habe ich verschiedene Modi des Timer 1 eines AT90USB162 ausprobiert. Bisher ist es mir allerdings nur gelungen den Modus 15 (fast PWM) zum Laufen zu bekommen. Nach dem ich das Datenblatt nochmal genau gelesen habe, erscheint mit der Modus 11 für meine Zwecke sinnvoller. Folgende Einstellungen habe ich vorgenommen
/** * setup TOP value */ ldi r16,0x01 sts OCR1AH,r16 ldi r16,0x00 /** * WGM-mode 11, phase correct PWM * set PIN C6 on upcounting, clear on downcounting * * TCCR1A = COM1A1 | COM1A0 | COM1B1 | COM1B0 | COM1C1 | COM1C0 | WGM11 | WGM10 * 0x83 = 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 */ ldi r16,((1 << COM1A1) | (1 << WGM11) | (1 << WGM10)) sts /** * enable interrupt on compare match A * * TIMSK1 = - | - | ICIE1 | - | OCIE1C | OCIE1B | OCIE1A | TOIE1 * 0x03 = 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 */ ldi r16,((1 << OCIE1A) | (1 << TOIE1)) sts TIMSK1,r16,r16 /** * OC1A as output (PIN C6, output) * * DDRC = DDC7 | DDC6 | DDC5 | DDC4 | DDC3 | DDC2 | DDC1 | DDC0 * 0x?? = - | 1 | - | - | - | - | - | - */ in r16,DDRC ori r16,(1 << DDC6) out DDRC,r16 /** * WGM-mode 11, phase correct PWM * start PWM right now * * TCCR1B = ICNC1 | ICES1 | - | WGM13 | WGM12 | CS12 | CS11 | CS10 * 0x11 = 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 */ ldi r16,((1 << WGM13) | (1 << CS10)) sts TCCR1B,r16 |
Wenn ich das richtig verstanden habe, dann sollte der Timer1 von 0x0000 (BOTTOM) bis zu dem von OCR1A gegebenen Wert zählen. Dabei sollte PIN C6 HIGH sein. Wird OCR1A (TOP) erreicht, dann sollte PIN C6 LOW werden und der Timer sollte rückwärts auf 0x0000 zählen. Bei erreichen des TOP-Wertes kann der Compare Match A Interrupt ausgelöst werden. Bei erreichen des BOTTOM-Wertes kann der Timer1 Overflow ausgelöst werden. Beide Interrupts bräuchte ich für mein Programm. Ich habe ein Oszi an den Pin angeschlossen und festgestellt, dass der PIN C6 lediglich HIGH-Pegel hat. Ändere ich
/** * WGM-mode 11, phase correct PWM * set PIN C6 on upcounting, clear on downcounting * * TCCR1A = COM1A1 | COM1A0 | COM1B1 | COM1B0 | COM1C1 | COM1C0 | WGM11 | WGM10 * 0x83 = 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 */ ldi r16,((1 << COM1A1) | (1 << WGM11) | (1 << WGM10)) sts |
zu
/** * WGM-mode 11, phase correct PWM * toggle PIN C6 * * TCCR1A = COM1A1 | COM1A0 | COM1B1 | COM1B0 | COM1C1 | COM1C0 | WGM11 | WGM10 * 0x43 = 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 */ ldi r16,((1 << COM1A0) | (1 << WGM11) | (1 << WGM10)) sts |
dann funktioniert die PWM. Allerdings nicht mit der angedachten Frequenz, aber immerhin mit einem Tastverhältnis von 1:1. Habe ich da etwas falsch verstanden? Wie sollte der WGM Modus 11 denn sonst funktionieren? Hat jemand schonmal diesen Modus genutzt?
Datum:
Hi OCR1A ist dein Top-Register (Wert, bis zu dem der Timer zählt). Damit bleiben für PWM nur die Kanäle B und C. MfG Spess
Datum:
Wozu gibt es dann die Optionen aus Tabelle 15-3 auf Seite 130 des Handbuchs? "Clear OCnA/OCnB/OCnC on compare match up-counting. Set OCnA/OCnB/OCnC on compare match when downcounting" bzw. invers, also setzen bei compare match beim hochzählen (sprich BOTTOM matched -> Timer Overflow Interrupt wird ausgelöst -> Pin wird gesetzt) und rücksetzen bei compare match (sprich TOP matched -> Compare Match A Interrupt wird ausgelöst -> Pin wird zurückgesetzt) beim runterzählen. Hast du das mal ausprobiert? Ich habe beide Interrupt, also Timer Overflow und Compare Match A aktiviert. Habe Breakpoints in beiden Interruptroutinen gesetzt und weiß daher, dass Timer Overflow direkt beim starten ausgelöst wird, was ja Sinn macht, da TCNT1 am Anfang 0 enthält und somit BOTTOM matched. Leider scheint das Debugging beim AVR Studio 5 noch nicht richtig ausgereift zu sein. Setze ich in beiden InterruptHandlern einen Breakpoint, dann wird immer nur einer angesprungen. Lösche einen beliebigen, wird der noch vorhandene angesprungen ... Also nochmal für mich zum richtigen Verständnis: Phase-correct PWM im Modus 11 bedeutet laut Datenblatt, dass der Timer von 0x0000 bis zum Wert in OCR1A hochzählt. Der Wert in OCR1A muss mindestens 0x0003 betragen. Hat er den Wert erreicht, dann wird der Compare Match A Interrupt ausgelöst und der Timer zählt rückwärts bis 0x0000. Dort angekommen wird der Timer Overflow Interrupt ausgelöst und das Spiel beginnt von vorne. Über COM1A1 und COM1A0 kann ich wählen ob der PIN C6 bei jedem Match toggeln soll, oder ob er beim hochählen gesetzt und beim runterzählen rückgesetzt werden soll bzw. eine dazu inverse Einstellung. Soweit OK oder Einwände? Falls dies nicht richtig ist, dann wäre es nett wenn mich jemand erleuchten könnte. Ich würde gerne beim Höchzählen setzen und beim runterzählen rücksetzen. Wenn das wirklich so nicht funktionieren sollte, dann werde ich versuchen mit der normalen Port operation zu arbeiten und den PIN händisch in den entsprechenden Interruptroutinen setzen. Schonmal Danke im vorraus. Gruß Benny
Datum:
Benjamin K. schrieb: > Hi, > > ich sitze gerade an einem Projekt bei dem ich einen Schrittmotortreiber > mittels PWM ansteuern möchte. Wozu brauchst du da einen PWM Modus? CTC Modus mit Pin toggeln und die Sache ist gegessen. Alles was du willst ist eine variable Frequenz.
Datum:
Hi >Wozu gibt es dann die Optionen aus Tabelle 15-3 auf Seite 130 des >Handbuchs? Es gibt ja noch andere PWM-Modes, bei denen OCR0A nicht als Top fungiert. OCR0A kann nur eine Funktion übernehmen, entweder als Compare-Register oder als TOP-Register. Bei Mode 10 kannst du auch OCR0A als Compare-Register verwenden. >Leider scheint das Debugging beim AVR Studio 5 noch nicht richtig >ausgereift zu sein. Setze ich in beiden InterruptHandlern einen >Breakpoint, dann wird immer nur einer angesprungen. Lösche einen >beliebigen, wird der noch vorhandene angesprungen ... Ist bekannt. Der Simulator funktioniert bei PWM-Modes mit variablen Top nicht. Steht auch, wenn ich mich nicht irre, in den 'Known Issues' vom Simulator. >Über COM1A1 und COM1A0 kann ich wählen ob der PIN C6 bei jedem Match >toggeln soll, oder ob er beim hochählen gesetzt und beim runterzählen >rückgesetzt werden soll bzw. eine dazu inverse Einstellung. Beim togglen bekommst du im Mode 11 eine CTC und beim Rest entweder L oder H. Aber in keinem Fall eine PWM. MfG Spess
Datum:
Moin, ich nutze den Simulator nicht, sondern bin mit einem JTAG MK2 auf dem Controller via DebugWire unterwegs. Im übrigen, kann der Simulator anscheinend einen AT90USB162 nicht simulieren. Wieso OCR0A? Ich möchte Timer1 nutzen, wenn dann ist das OCR1A. OK ich blick es nicht. Das mit Mode 11 und CTC steht in Handbuch anders ... CTC ist da in Tabelle 15-4 auf Seite 131 entweder Mode 4 oder Mode 12. In letzterem ist ICR1 dann TOP. Klar dass ich dann OCR1A als Compare nutzen kann. Der Timer läuft dann von BOTTOM bis zum Wert in ICR1 und wenn er unterwegs OCR1A matched wird der Pin geschaltet. Anschließend beim runterzählen und erneutem matchen von OCR1A wird der Pin wieder geschaltet. Tastverhältnis ist dann nur 1:1 wenn die Werte in ICR1 und OCR1A geschickt gewählt werden ... Also meine Frage lautet: Wie funktioniert der Phase Correct PWM Mode? Wie kann dieser eingeschaltet werden und was macht OC1A dabei? Ich weiß dass es andere Modi gibt, die für meine Anwendung auch missbraucht werden können. Ich könnte mir auch eine Karte kaufen die bereits alles mit einem Schrittmotor macht was ich will ... Dann weiß ich aber immer noch nicht wieso der Phase Correct PWM Modus bei meinem AVR nicht funktioniert, bzw. wo mein Fehler liegt ...
Datum:
Hi >Ich weiß dass es andere Modi gibt, die für meine Anwendung auch >missbraucht werden können. Ich könnte mir auch eine Karte kaufen die >bereits alles mit einem Schrittmotor macht was ich will ... Wieso kommt jetzt ein Schrittmotor ins Spiel? MfG Spess
Datum:
spess53 schrieb: > Hi > >>Ich weiß dass es andere Modi gibt, die für meine Anwendung auch >>missbraucht werden können. Ich könnte mir auch eine Karte kaufen die >>bereits alles mit einem Schrittmotor macht was ich will ... > > Wieso kommt jetzt ein Schrittmotor ins Spiel? War es schon immer. :-) und genau darum ist mir unklar, was da ein PWM Modus überhaupt soll. Im speziellen bin ich der Meinung, dass der phase-correct Modus sowieso überbewertet wird. Sinn macht der IMHO nur dann, wenn bestimmte Phasenbeziehungen zwischen mehreren Timern eingehalten werden müssen. Ein Fall, den man eher selten hat. Eine PWM dazu zu benutzen um eine variable Frequenz mit einem PP von 1:1 zu erzugen ist meiner Meinung nach pervers. Dazu war PWM nie gedacht und man muss höllisch aufpassen, was denn nun genau passiert, wenn der Compare Wert identisch mit dem Top-Wert ist. > sts TIMSK1,r16,r16 Was macht der Assembler hiermit? und hiermit? > ldi r16,((1 << COM1A1) | (1 << WGM11) | (1 << WGM10)) > sts
Datum:
Sorry muss beim kopieren schiefgegangen sein. Ist mir garnicht aufgefallen ... Hier die korrigierte Version:
/** * setup TOP value */ ldi r16,0x01 sts OCR1AH,r16 ldi r16,0x00 /** * WGM-mode 11, phase correct PWM * set PIN C6 on upcounting, clear on downcounting * * TCCR1A = COM1A1 | COM1A0 | COM1B1 | COM1B0 | COM1C1 | COM1C0 | WGM11 | WGM10 * 0x83 = 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 */ ldi r16,((1 << COM1A1) | (1 << WGM11) | (1 << WGM10)) sts TCCR1A,r16 /** * enable interrupt on compare match A * enable timer overflow interrupt * * TIMSK1 = - | - | ICIE1 | - | OCIE1C | OCIE1B | OCIE1A | TOIE1 * 0x03 = 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 */ ldi r16,((1 << OCIE1A) | (1 << TOIE1)) sts TIMSK1,r16 /** * OC1A as output (PIN C6, output) * * DDRC = DDC7 | DDC6 | DDC5 | DDC4 | DDC3 | DDC2 | DDC1 | DDC0 * 0x?? = - | 1 | - | - | - | - | - | - */ in r16,DDRC ori r16,(1 << DDC6) out DDRC,r16 /** * WGM-mode 11, phase correct PWM * start PWM right now * * TCCR1B = ICNC1 | ICES1 | - | WGM13 | WGM12 | CS12 | CS11 | CS10 * 0x11 = 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 */ ldi r16,((1 << WGM13) | (1 << CS10)) sts TCCR1B,r16 |
bzw.
/** * WGM-mode 11, phase correct PWM * toggle PIN C6 * * TCCR1A = COM1A1 | COM1A0 | COM1B1 | COM1B0 | COM1C1 | COM1C0 | WGM11 | WGM10 * 0x43 = 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 */ ldi r16,((1 << COM1A0) | (1 << WGM11) | (1 << WGM10)) sts TCCR1A,r16 |
Was die Wahl des Modus angeht, war die Idee dass die Frequenz sehr einfach geändert werden kann, nämlich nur durch Ändern eines Registers OCR1A. Das Tastverhältnis bleibt automatisch erhalten und muss nicht weiter beachtet werden und die beiden Interrupts gestatten mir das drumherum einfach zu behandeln. Da der Treiber (Trinamic TMC262) über eine STEP/DIRECTION Schnittstelle verfügt scheint mir eine PWM durchaus geeignet. In den sehr einfachen Interruptroutinen will ich die Schritte bis zur Zielposition aktualisieren, bzw. prüfen, ob die Zielposition schon erreicht wurde bzw. ob ich noch beschleunigen oder bremsen muss (-> Frequenzänderung -> Änderung von OCR1A). Im Falle der Nutzung des CTC Modus ist die eine Interruptroutine dann etwas komplizierter und ich muss mir auch noch merken ob eine volle Schrittperiode durchgeführt wurde bevor ich zum Beispiel die Frequenz ändere.
Datum:
da hat sich noch ein Fehler eingeschlichen ...
/** * setup TOP value */ ldi r16,0x01 sts OCR1AH,r16 ldi r16,0x00 sts OCR1AL,r16 |
Datum:
Benjamin K. schrieb: > Was die Wahl des Modus angeht, war die Idee dass die Frequenz sehr > einfach geändert werden kann, nämlich nur durch Ändern eines Registers > OCR1A. Und? Ist beim CTC mit toggeln auch nicht anders. > Das Tastverhältnis bleibt automatisch erhalten und muss nicht > weiter beachtet werden auch das ist beim CTC nicht anders > und die beiden Interrupts gestatten mir das > drumherum einfach zu behandeln. und wieder: ist beim CTC nicht anders > Da der Treiber (Trinamic TMC262) über > eine STEP/DIRECTION Schnittstelle verfügt scheint mir eine PWM durchaus > geeignet. Wozu? eine PWM nimmst du, wenn die Pulse unterschiedliche Puls/Pausenverhältnisse haben müssen. Das ist bei dir nicht der Fall. > Im Falle der Nutzung des CTC Modus ist die eine Interruptroutine dann > etwas komplizierter bis 2 zählen ist kompliziert? Aber seis drum: Bei einer Frequenzänderung musst du 2 Register anpassen. Genausoviele wie zb im FastPWM Modus. Den Top-Wert und den Compare Match. Ausser in ganz seltenen Fällen, in denen zb 2 Timer eine bestimmte PWM Phasenbeziehung einhalten müssen oder es sonstige externe Symteriebeschränkungen gibt, braucht kein Mensch den phase correct Mode. Du bellst mit diesem Modus das falsche Pferd an.
Datum:
Dann habe ich jetzt mal eine Frage: Wenn der TOP-Wert bei Phase Correct PWM im Modus 11 durch OCR1A angegeben wird. Welches Register beinhaltet dann den Compare-Wert? Gruß Benny
Datum:
Hi >Wenn der TOP-Wert bei Phase Correct PWM im Modus 11 durch OCR1A >angegeben wird. Welches Register beinhaltet dann den Compare-Wert? OCR1B und/oder OCR1C. MfG Spess
Datum:
Kannst du mir sagen wo das im Handbuch steht? Ich habe es jetzt so gelöst, dass ich COM1A1 und COM1A0 auf 0:0 setze. Dadurch wird OC1A nicht von OCR1A beeinflusst. Ich setze den Pin jetzt einfach in den beiden Interruptroutinen. Nochmal Danke für die Hilfe.
Datum:
Hi >Kannst du mir sagen wo das im Handbuch steht? Wenn du drei OC-Register hast und davon mutiert eins zum Top-Register. Wie viel bleiben dann noch übrig? Steht vielleicht auch irgendwo. >Ich habe es jetzt so gelöst, dass ich COM1A1 und COM1A0 auf 0:0 setze. >Dadurch wird OC1A nicht von OCR1A beeinflusst. Ich setze den Pin jetzt >einfach in den beiden Interruptroutinen. Blödsinn. Ich hatte deinen ersten Satz leider überlesen sonst hätte ich dir auch gleich, wie Karl-Heinz, zu CTC geraten. Also Mode 4. Damit kannst du eine von OCR1A abhängige Frequenz erzeugen. Ganz ohne Interrupts und händisches Pin setzten. MfG Spess
Datum:
Das ist schon richtig. Es steht aber auch nirgends das der Pin dann nicht mehr geschaltet werden kann. Es wird ja auch der Compare Match A Interrupt ausgelöst ... Wie dem auch sei, zwei Befehle um einen Pin ein und auszuschalten und 1 16-Bit-Register zu beschreiben scheint mir bequemer und weniger Aufwand zu sein als ständig 2 16-Bit-Register zu setzen zu berechnen wie jetzt das Compare Register beschrieben werden muss, damit ein Tastverhältnis von 1:1 erhalten bleibt und dann noch einen Vergleich durchzuführen damit ich weiß ob ich jetzt gerade mitten im Schritt bin oder doch schon am Ende, aber das ist nur meine Meinung ;-) nochmal danke
Datum:
Hi > damit ein Tastverhältnis >von 1:1 erhalten bleibt und dann noch einen Vergleich durchzuführen CTC hat ein Tastverhältnis von 1:1. Darum brauchst du dich nicht kümmern. MfG Spess
Datum:
... und die 'Rechnerei' ist eine Multiplikation mit 2. Die müsstest du bei deiner phase correct PWM Lösung im übrigen genauso machen. Aber was solls. Des Menschen Wille ist sein Himmelreich.
Datum:
Ich muss nichts rechnen, da ich nur das OCR1A-Register als TOP setze. Ich habs hier gerade Laufen ... Ich war, wohl falsch, davon ausgegangen, dass man im Modus 11 einfach das OCR1A-Register als TOP setzen kann UND die Automatik des OC1A-Pin setzen nutzen kann. Auf diese Art würde man sich alle Rechnerei einfach sparen, weil der Pin beim zählen von 0x0000 zu TOP gesetzt und beim zählen von TOP zu 0x0000 rückgesetzt würde, oder falls benötigt umgekehrt. Aufwand in diesem Fall: 1x 16 Bit-Register OCR1A setzen 1x Compare Match A Interrupt Routine mit Schritt zählen 1x Overflow Routine mit Frequenz ändern Aufwand CTC-Modus: 1x 16 Bit-Register OCR1A setzen 1x Interrupt-Routine (Compare Match A) 1x Vergleich um entweder Frequenz zu ändern oder Schritt zu zählen 1x Register oder Variable um zu merken ob Schritt gezählt werden muss Aufwand in meiner jetzigen Lösung: 1x 16 Bit-Register OCR1A setzen 1x Compare Match A Interrupt Routine mit Pin setzen (sbi) + Schritt zählen 1x Overflow Interrupt Routine mit Pin rücksetzen (cbi) + Frequenz ändern Wenn ICR1 mit einbezogen wird, dann 1x 16 Bit-Register ICR1 setzen (nicht gepuffert!) 1x 16 Bit Division mit 2 (ok einfach, aber doch "Aufwand") 1x 16 Bit-Register OCR1A setzen für 1:1 1x Interrupt Routine (Compare Match A) 1x Vergleich um entweder Frequenz zu ändern oder Schritt zu zählen 1x Register oder Variable um zu merken ob Schritt gezählt werden muss Wirklich vielen Dank für die Hilfe. Vielleicht ist mir auch einfach nicht gelungen klar auszudrücken was ich eigentlich wissen wollte... Gruß Benny