Hallo,
schreibe gerade ein Programm für den frequenzgeführten Betrieb einer
Drehfeldmaschine mit Grundfrequenztaktung. Die Frequenz stelle ich über
die Periodendauer PER des Counters ein.
Das Problem: Wenn ein Ausgang der PWM über mehrere Perioden auf High
bleiben soll, geht er am Ende (Anfang?) einer Periode kurz (einen
PWM-Takt?) auf Low. Das, obwohl z.B. TCC0.CCABUF = TCC0.PERBUF gesetzt
ist und laut Manual hier PIN0 an PORTC über mehrere Perioden
kontinuierlich auf High bleiben sollte. Das Ganze passiert im statischen
Betrieb, ohne TCC0.PER zu ändern.
Seltsam ist auch, dass je nach Wert von TCC0.PER das Problem manchmal
nicht auftritt...?
Wenn ich den Wert für CCABUF unsinniger Weise höher als PERBUF setze,
habe ich ein durchgängiges High am Pin.
Könnte mir jemand mit seinem Fachwissen weiter helfen, bzw. eine
elegantere Lösung für die GFT nennen.
Hier ein Auszug au dem Code:
Also ich würd mit den Atmel Lib-Funktionen arbeiten. Was du alles im
Timer 0 Interrupt machst schreit nach Problemen. Mit welcher PWM
Frequenz arbeitest du und mit welcher Auflösung?
SG
Was die Lib-Funktionen sind, weiß ich nicht mal. Vieleicht kannst Du mir
erklären, warum ich diese benutzen sollte. Bin halbwegs Anfänger.
Den TCC0_OVF_vect nutze ich, um zu gewährleisten, dass die
Compare-Register in der nächsten Periode den "richtigen" Wert haben.
Übrigens mache ich noch eine ganze menge mehr in dieser ISR. Warum
schreit das nach Problemen?
Die PWM-Frequenz ist wie erwähnt variabel und bestimmt die Frequenz der
"Blocktaktung". fBlock = fPWM/6. PER wird über eine Variable gefüttert.
Die Frequenz variiert zwischen 2,1Hz und 65,94Hz bei DIV=256,
ausgeschaltetem HiRes, ClkCPU=32MHz, ClkPer=ClkCpu, PER=63130 bis 1895.
Und zwischen 66Hz und 600Hz bei DIV=256, HiRes an (4x), ClkCPU=32MHz,
ClkPer=ClkCpu, ClkPer4=4*ClkCpu, PER=7575 bis 832.
CCA bis CCC sollen immer den aktuellen Wert von PER haben oder Null
sein. Je nach Sektor halt.
Am liebsten wäre mir eine 32bit-PWM gewesen. Die scheint aber nicht
möglich mit dem Xmega256A3U. Eine bessere Lösung für die Blocktaktung
ist mir bisher nicht eingefallen... Vieleicht hast Du einen
konstruktiven Vorschlag
qzeta5 schrieb:> Das Problem: Wenn ein Ausgang der PWM über mehrere Perioden auf High> bleiben soll, geht er am Ende (Anfang?) einer Periode kurz (einen> PWM-Takt?) auf Low. Das, obwohl z.B. TCC0.CCABUF = TCC0.PERBUF gesetzt> ist und laut Manual hier PIN0 an PORTC über mehrere Perioden> kontinuierlich auf High bleiben sollte. Das Ganze passiert im statischen> Betrieb, ohne TCC0.PER zu ändern.> Seltsam ist auch, dass je nach Wert von TCC0.PER das Problem manchmal> nicht auftritt...?>> Wenn ich den Wert für CCABUF unsinniger Weise höher als PERBUF setze,> habe ich ein durchgängiges High am Pin.
Das ist völlig richtig und normal so. Die PWM wird, wenn sie nicht
invertiert ist, beim Übergang von Timer-Top -> 0000 gesetzt und beim
Compare-Match gelöscht. Im invertierten Modus wird sie beim
Compare-Match gesetzt und bei Timer-Top -> 0000 gelöscht. Daher erhältst
du immer einen Spike in der Breite eines ungeteilten Timer-Taktzyklusses
(CLKPer). Um dies zu verhindern, setzt Du PER genau 1 höher als Deinen
maximalen Compare-Wert und schon ist alles in Butter.
qzeta5 schrieb:> Am liebsten wäre mir eine 32bit-PWM gewesen. Die scheint aber nicht> möglich mit dem Xmega256A3U.
Auszug aus dem AU-Manual:
Atmel AVR XMEGA devices have a set of flexible, 16-bit timer/counters
(TC). Their capabilities include accurate program
execution timing, frequency and waveform generation, and input capture
with time and frequency measurement of digital
signals. Two timer/counters can be cascaded to create a 32-bit
timer/counter with optional 32-bit capture.
Danke für die hilfreiche Antwort Knut :)
Schon komisch, dass dieses Verhalten nicht aus der zugehörigen "Figure
14-15" im Manual des Xmega AU hervorgeht. Eher im Gegenteil.
Der Spike ist bei mir übrigens tatsächlich (CLKPer/DIV)^-1 breit, also
ca. 8us.
Deine Lösung funktioniert (fast) tatsächlich! Nur dass ich den
Compare-Wert um 1 höher setzen muss als PER.
Mit HiRes muss ich übrigens CCx=PER+4 rechnen...
So ganz verstanden habe ich das immer noch nicht. Da im Manual für
Single-slope PWM CCx=TOP zu einem verbleibenden High führen soll.
Das Vorgehen jetzt bedeutet ja, dass ich keinen Compare-Match habe und
somit der CCx-Wert "beliebig" größer als der PER-Wert sein könnte. Habe
da ein wenig Bedenken wegen unberechenbaren Verhaltens des Programms.
Ja, das habe ich tatsächlich auch gelesen. Das soll wohl mit dem
Event-System funktionieren. Wie das aber progrsmmiert werden soll, ist
mir ein Rätsel. Das Event-System habe ich bisher aus Unwissenheit und
Scheu nicht angefasst. :) Ansonsten steht aber nicht mehr dazu im
Manual.
Zudem frage ich mich, wie eine 32-Bit PWM an drei Pins damit realisiert
werden kann. Ich kann ja z.B. TCC0 und TCC1 zusammenschalten. Sagen wir
der TCC0 würde beim OVF von TCC1 starten. Das hieße doch, dass ich für
PORTC PIN0 bis PIN2 trotzdem nur Compare-Werte von 0 bis 65536 nutzen
könnte, somit nur die Frequenz aber nicht die Auflösung eines echten
32-Bit Counters hätte.(?) Oder verstehe ich das falsch...?
Habe jetzt den Code aus der "void speedNeu32(void)" in die "ISR
(TCC0_OVF_vect)" verlegt. Das Vorgehen CCx=PER+1 bzw. CCx=PER+4 (HiRes)
funktioniert soweit.
Das Beschleunigen, Verzögern und der statische Betrieb geben mir ein
scheinbar einwandfreies Signal aus.
Einziger Knackpunkt ist der Wechsel zwischen HiRes an/aus beim
Beschleunigen bzw. Verzögern.
Gibt es eine Möglichkeit HiRes exakt zum Beginn einer neuen Periode zu
aktivieren? So wie ich das jetzt mache geschieht das
Aktivieren/Deaktivieren von HiRes "irgendwo" zwischendurch.
Dachte hier die ISR des freien TCC0.CCD-Registers zu nutzen, um einige
Takte vor TOP HiRes ein/auszuschalten, damit HiRes genau zum Beginn der
nächsten Periode eingeschaltet wird. Mein analoges Oszi eignet sich hier
leider nicht für die Untersuchung´des Wechsels. Zudem scheint mir dieser
Ansatz immer noch zu unberechenbar.
Oh je ;) Danke. Habs am liebsten idiotensicher erklärt. Die
Getting-Started-Blättchen von Atmel verwirren mich manchmal noch mehr,
als dass sie mir weiterhelfen :) Naja, irgendwann muss ich auch da
durch...
Weißt Du, ob meine Vermutung mit der 16bit-Auflösung beim
zusammengesetzten 32bit-Counter riichtig ist? Oder hat jemand eine echte
32bit-PWM mit dem Zusammenschalten zweier Timer produziert? Mein
HiRes-Problem habe ich bisher auch nicht lösen können...
qzeta5 schrieb:> Deine Lösung funktioniert (fast) tatsächlich! Nur dass ich den> Compare-Wert um 1 höher setzen muss als PER.
Meinte ich doch... verdammt ;-)