Hallo, ich verzweifle gerade.
Möchte mit dem ATmega88 einen Sinus mit 500Hz erzeugen. Das klappt
prinzipiell auch ganz gut. (siehe Code)
Ich erzeuge den Sinus mit einer PWM, deren Werte ich in einer Tabelle
abgelegt habe.
Das Signal hat 500Hz, besteht aus 128 Bit/Periode und die PWM hat eine
Frequenz von 125kHz (64kHz sind nötig! (500*128)
Mein Prozessor läuft mit 8MHz, Prescaler = 0, 8-Bit Timer(Timer 0): Sind
8MHz / 256 = 31,25kHz. Top-Wert geändert (WGM-Mode:5) auf 64: heißt 8MHz
/ 64 = 125kHz.
Ich arbeite im PhaseCorrectMode!
An OC0B liegt mein PWM-Siganl, da mein OCR0A Register belegt ist und die
PWM durch OCR0B geändert wird.
Das Signal durch einen Tiefpass und fertig ist der Sinus.
Jetzt brauche ich aber den Sinus einmal zusätzlich invertiert - und das
klappt nicht mit meiner Konfiguration. (OCR0A für OC0A ist schon
belegt.)
Da habe ich mir gedacht, ich erzeuge die PWM manuell und schalte meinen
OC0B und OC0A korrespondierenden Pin manuell.
Der Timer macht das ja ,indem (durch die COM0A / COM0B) bei einem
Compare mit OCR0B) der PWM Ausgang (OC0B) geändert wird.
Nun habe ich die PWM abgeschaltet (COM0B auf 0 --> Ausgang als
I/O-Port).
Dann habe ich in der ISR bei einem OutputCompareInterupt0B meine(n)
Ausgang(e) wie zuvor geändert, nur manuell.
Problem:
Jetzt habe ich keine stabile Ausgangsfrequenz mehr. Die Flanke springt
immer, so, als kommt der Interrupt nicht mehr Regelmäßig. Woran liegts?
Habt Ihr da den Durchblick?
Hc Zimmerer schrieb:
>> TCCR0A = (1<<WGM00);// | (1<<COM0B1);//--> Manuell, siehe ISR>> Nichts mit Manuell. Zitat Datenblatt:If one or both of the COM0B1:0> bits are set, the OC0B output overrides the normal port functionality
Genau!
COM0B1 ist auskommentiert somit ist der Port für normale I/O-Funktion
konfiguriert und ich kann meine Ausgänge manuell verwalten!
Resultat:
Weder die Grundfrequenz ist stabil (125kHz) noch die Umschaltzeiten am
Port D5
Kompletter Code ist im 1. Post...
Wie schaltet ihtr den Port bei manueller PWM?
Bernd A. schrieb:
> Resultat:> Weder die Grundfrequenz ist stabil (125kHz) noch die Umschaltzeiten am> Port D5
Vielleicht sollten wir mal darüber reden, was du unter 'nicht stabil'
verstehst. Wie groß sind die Schwankungen?
Wenn der Timer die PWM erzeugt, kann er das taktgenau machen.
Wenn du aber auf ISR angewiesen bist, hast du immer gewisse
Latenzzeiten, bis der aktuelle Befehl beendet ist und der µC mit der ISR
abarbeitung anfängt. Dann kommt bei dir natürlich noch dazu, dass eine
ISR evetuell ein wenig warten muss, weil gerade die andere ISR drann
ist.
Mit einem geringen Jitter würde ich daher rechnen.
Daher die Frage: Über welche Fluktuationen in deinen Messwerten reden
wir.
Also ich trigger auf positive Flanke. Die negative hat ein Delta von
früheste fallende bis späteste fallende von ca. 6µs
Das Delta von steigender Flanke bis früheste fallende Flanke ist ca.
5,4µs
Karl heinz Buchegger schrieb:
> Dann kommt bei dir natürlich noch dazu, dass eine> ISR evetuell ein wenig warten muss, weil gerade die andere ISR drann> ist.
Habe mal den Timer 2 ausgeschaltet und siehe da, der Takt meiner PWM ist
stabil. Meine Frage: In meinem Timer2 wird nur eine globale Variable
hochgezählt:
6µs sind bei 8Mhz 48 Prozessortakte (wenn ich mich nicht verrechnet
habe). Das könnte in Summe schon hinkommen. Pro ISR ein paar Push/Pop.
Variable in Register holen, inkrement und zurück, der ret, dann ein
Befehl im Hauptprogramm ehe die andere ISR loslegen kann. Die pusht auch
erst mal ein paar Register ...
So viel sind 48 Takte dann auch wieder nicht.
Wie kann ich jetzt das Problem lösen? (Lösungsansätze)
Den Timer 2 brauche ich ja um der PWM einen neuen Wert zu geben (128
neue Werte pro Periode - eine Periode 500Hz) um meinen Sinus zu
erzeugen. Ich habe 32 Werte pro viertel Sinus)
Inkrement klappert also die 128 Werte durch...
MWS schrieb:
> Schreib' einfach mal ein SEI() an den Anfang Deiner Timer2 ISR.
Das ist sinnlos.
Während eines ISR sind Interrupts sowieso gesperrt.
> Den Timer 2 brauche ich ja um der PWM einen neuen Wert zu> geben (128 neue Werte pro Periode - eine Periode 500Hz)> um meinen Sinus zu erzeugen. Ich habe 32 Werte pro viertel Sinus)
Wie wärs, wenn du den Timer 2 den Interrupt nicht auslösen lösst,
sondern den Overflow in der Hauptschleife pollst?:
Der Timer kann ruhig das Overflow Flag setzen, darf aber keine ISR
auslösen. In der Hauptschleife fragst du das Overflow Flag ab und
erhöhst dort zu gegebener Zeit das j und setzt das Overflow Flag wieder
zurück.
> Das ist sinnlos. Während eines ISR sind Interrupts sowieso gesperrt.
Ich hab' SEI() und nicht CLI() geschrieben, also das Aufheben der
Sperre. Timer2 sorgt für den Jitter, wenn man explizit dort weitere
Interrupts erlaubt, dann kommt der Compare Int schneller dran.
Wobei mir ein Polling in der Mainloop auch als besser erscheint.
Karl heinz Buchegger schrieb:
> Wie wärs, wenn du den Timer 2 den Interrupt nicht auslösen lösst,> sondern den Overflow in der Hauptschleife pollst?:> Der Timer kann ruhig das Overflow Flag setzen, darf aber keine ISR> auslösen. In der Hauptschleife fragst du das Overflow Flag ab und> erhöhst dort zu gegebener Zeit das j und setzt das Overflow Flag wieder> zurück.
Wie mache ich das? Das Flag wird gesetzt wenn ein Overflow passiert und
zurückgesetzt wenn die ISR verlassen wird. Umkehrschluss: Wenn das TOIE
- Flag nicht gesetzt ist, wird das TOV trotzdem gesetzt?
Muss mal schnell nachlesen...
zusatz: wenn es trotzdem gesetzt wird (sofort beim ersten Überlauf), und
die Interrupts aus sind, heißt das, das das Flag immer gesetzt bleibt?
Bis der Controller ausgeschaltet wird bzw ich es manuell zurücksetze?
Ja, ich geh der Sache mal nach...
> Wie mache ich das? Das Flag wird gesetzt wenn ein Overflow passiert und> zurückgesetzt wenn die ISR verlassen wird.
Wenn die entsprechende ISR nicht erlaubt ist, dann wird das Flag beim
Eintreten des Ereignisses gesetzt und bleibt es auch bis Du es löscht.
Gelöscht wird durch Schreiben einer 1 in's Flagbit.
@ Bernd A. (Gast)
>Wie kann ich jetzt das Problem lösen? (Lösungsansätze)>Den Timer 2 brauche ich ja um der PWM einen neuen Wert zu geben (128>neue Werte pro Periode - eine Periode 500Hz) um meinen Sinus zu>erzeugen. Ich habe 32 Werte pro viertel Sinus)>Inkrement klappert also die 128 Werte durch...
Dann pack einfach deinen Variabelenzähler in den Timer 0!
MFG
Falk
MWS schrieb:
>> Das ist sinnlos. Während eines ISR sind Interrupts sowieso gesperrt.>> Ich hab' SEI() und nicht CLI() geschrieben
Ah. Mein Fehler.
Das war der 'cli und sei in ISR'-Reflex.
Falk Brunner schrieb:
> Dann pack einfach deinen Variabelenzähler in den Timer 0!
Was soll ich denn damit?
Karl heinz Buchegger schrieb:
> Wie wärs, wenn du den Timer 2 den Interrupt nicht auslösen lösst,> sondern den Overflow in der Hauptschleife pollst?:
(Ich brauche nicht das Overflow- sondern das Output Compare-Flag)
Kann ich das so machen?
Bernd A. schrieb:
> (Ich brauche nicht das Overflow- sondern das Output Compare-Flag)
Mein Fehler.
War irgendwie auf OVerflow fixiert und hab nicht mehr hochgescrollt um
das zu kontrollieren ...
> Kann ich das so machen?> [c]> if (TIFR2 && OCF2A) //<-- !!
Nope. Wee fragt man denn ein Bit ab? Funktioniert wie alle anderen
Abfragen auch:
if (TIFR2 & (1<<OCF2A) )
> {> ++j;> TIFR2 |= (1<<OCF2A);
Diese Art von Flag wird gelöscht, indem man einfach zuweist.
TIFR2 = (1<<OCF2A);
Wann immer im Handbuch steht, dass das Flag zurückgesetzt wird, indem
man ein 1 Bit ins Register schreibt, ist genau das gemeint.
Karl heinz Buchegger schrieb:
> Nope. Wee fragt man denn ein Bit ab? Funktioniert wie alle anderen> Abfragen auch:>> if (TIFR2 & (1<<OCF2A) )
Bernd A. schrieb:
> Ich habe gerade einen Overflow in meinem Hirn.
Da sind schon mal ein paar Grundlagen zuviel... - oh man
@ Bernd A. (Gast)
>> Dann pack einfach deinen Variabelenzähler in den Timer 0!>Was soll ich denn damit?
Die Variable hochzählen? Du willst konstant mit 500 Hz eine PWM
ausgeben, dazu brauchst du nur einen Timer. Der macht die PWM und
gleichzeiig deinen Timerinterrupt. Der kann parallel auch eine Variabel
hochzählen, welche für andere Programmteile verwendet werden kann.
MFG
Falk
Falk Brunner schrieb:
>>> Dann pack einfach deinen Variabelenzähler in den Timer 0!>>>Was soll ich denn damit?>> Die Variable hochzählen? Du willst konstant mit 500 Hz eine PWM> ausgeben, dazu brauchst du nur einen Timer. Der macht die PWM und> gleichzeiig deinen Timerinterrupt. Der kann parallel auch eine Variabel> hochzählen, welche für andere Programmteile verwendet werden kann.
Das ist nur die halbe Wahrheit.
Meine 500Hz sind ein Sinus mit 128 Bit/Periode macht 15,625µs pro Bit.
Mein Timer 0 läuft mit 8µs.
Sind 488 Hz. Meine Frequenz soll später über ein Poti eingestellt werden
können zwischen 200Hz und 800Hz.
==========
Zurück zum eigentlichen Problem:
Ich brauche ja nur(!) ein invertiertes Signal am zweiten PWM Ausgang.
Kann ich nicht die HW-PWM machen (die läuft einwandfrei) und den PIN
abfragen und invertiert am anderen Pin ausgeben?
@ Bernd A. (Gast)
>Das ist nur die halbe Wahrheit.
Und warum rückst du nicht mit der ganzen raus? Siehe Netiquette!
>Meine 500Hz sind ein Sinus mit 128 Bit/Periode macht 15,625µs pro Bit.
Bit? Eher Byte, oder?
>Mein Timer 0 läuft mit 8µs.>Sind 488 Hz.
Bei mir sind das eher 125 kHz.
> Meine Frequenz soll später über ein Poti eingestellt werden>können zwischen 200Hz und 800Hz.
Ja und? Das kann man erstens über einen Ansatz mit konstanter Abtastrate
lösen oder die Abtastrate der Ausgangsfrequenz anpassen.
Und da man weiss, welche Frequenz man ausgeben will, kann man das auch
mit dem Hochzählen in den Griff bekommen.
Wozu brauchst du die variable j eigentlich?
>Kann ich nicht die HW-PWM machen (die läuft einwandfrei) und den PIN>abfragen und invertiert am anderen Pin ausgeben?
Das geht nur über Software. Man kann aber ZWEI PWMs parallel (synchron)
laufen lassen, an einem Timer (wenn dieser zwei oder mehr OCRx hat).
MFG
Falk
Hmm.
SChön langsam überleg ich mir ob die einfachste Variante nicht darin
bestünde am µC Pin einfach einmal normal rauszugehen und einmal über
einen Inverter (zb Schalttransistor - NPN).
Wenn ich dich richtig verstehe, willst du ja eigentlich nur zusätzlich
zum normalen Signal ein um 180° phasenverschobenes Signal haben.
Tja, Falk,
du hast es wohl nicht ganz verstanden!
Falk Brunner schrieb:
>>Das ist nur die halbe Wahrheit.>> Und warum rückst du nicht mit der ganzen raus? Siehe Netiquette!
Diese Variante kam erst später hinzu.
Falk Brunner schrieb:
>>Meine 500Hz sind ein Sinus mit 128 Bit/Periode macht 15,625µs pro Bit.>> Bit? Eher Byte, oder?
Nein Bit, wer rechnen kann ist klar im Vorteil: 500Hz = 2ms geteilt
durch 128 Bit sind 15,625 µs pro Bit!
Falk Brunner schrieb:
>>Mein Timer 0 läuft mit 8µs.>>Sind 488 Hz.>> Bei mir sind das eher 125 kHz.
Siehst du, Sache nicht verstanden. Vielleicht habe ich auch zuviel von
dir erwartet. Wenn du nun rückwärts rechnest und mit deiner
hochzählvariablen in Timer0 zu arbeiten heißt das 2x8µs = 16µs (nächster
Wert zu 15,625µs) mal 128 Bit (2,048ms) sind: 488,28125 Hz um es genau
zu nehmen!
Höchzählen mit 1 (1x8µs): 976 Hz
Hochzählen mit 3 (3x8µs): 325 Hz
Falk Brunner schrieb:
>> Meine Frequenz soll später über ein Poti eingestellt werden>>können zwischen 200Hz und 800Hz.> [...]> Und da man weiss, welche Frequenz man ausgeben will, kann man das auch> mit dem Hochzählen in den Griff bekommen.
siehe oben
Falk Brunner schrieb:
> Wozu brauchst du die variable j eigentlich?
Damit zähle ich das Bit in der Periode hoch (128 Bit = 1 Periode)
--> zählen kann ich auch
Falk Brunner schrieb:
> Man kann aber ZWEI PWMs parallel (synchron)> laufen lassen, an einem Timer (wenn dieser zwei oder mehr OCRx hat).
Timer 0 ist meine primäre PWM, Timer 2 ist für die Periode, Timer 1 wird
später noch benötigt.
Karl heinz Buchegger schrieb:
> Hmm.> SChön langsam überleg ich mir ob die einfachste Variante nicht darin> bestünde am µC Pin einfach einmal normal rauszugehen und einmal über> einen Inverter (zb Schalttransistor - NPN).>> Wenn ich dich richtig verstehe, willst du ja eigentlich nur zusätzlich> zum normalen Signal ein um 180° phasenverschobenes Signal haben.
Das ist auch ein guter Ansatz, da bin ich ja noch gar nicht drauf
gekommen. Das kommt davon, wenn der Horizont immer so eingeschränkt ist.
Gut dass man mit Leuten von außen drüber spricht. Vielen Dank, ich
glaube das ist die vernünftigste Lösung. Externe Beschaltung ist ja auch
nötig und der eine Transistor macht auch nichts mehr...
Guter Hinweis...
@ Bernd A. (Gast)
>Tja, Falk,>du hast es wohl nicht ganz verstanden!
Wir werden sehen . . .
>>>Meine 500Hz sind ein Sinus mit 128 Bit/Periode macht 15,625µs pro Bit.>>> Bit? Eher Byte, oder?>Nein Bit, wer rechnen kann ist klar im Vorteil: 500Hz = 2ms geteilt>durch 128 Bit sind 15,625 µs pro Bit!
Du gibst aber pro PWM-Zyklus einen 5-Bit Wert aus, denn deine PWM kann
ja wahrscheinlich Werte zwischen 0..255 annehmen. Macht 1
BYTE/PWM-Zyklus.
>Siehst du, Sache nicht verstanden. Vielleicht habe ich auch zuviel von>dir erwartet.
Du bist ja ein ganz Schlauer. Wie alt bist du? 12 1/2?
> Wenn du nun rückwärts rechnest und mit deiner>hochzählvariablen in Timer0 zu arbeiten heißt das 2x8µs = 16µs (nächster>Wert zu 15,625µs) mal 128 Bit (2,048ms) sind: 488,28125 Hz um es genau>zu nehmen!
Das sind keine 128 Bit, sondern 128 Abtastpunkte a 1 Byte.
>Höchzählen mit 1 (1x8µs): 976 Hz>Hochzählen mit 3 (3x8µs): 325 Hz>>> Meine Frequenz soll später über ein Poti eingestellt werden>>>können zwischen 200Hz und 800Hz.>> [...]>> Und da man weiss, welche Frequenz man ausgeben will, kann man das auch>> mit dem Hochzählen in den Griff bekommen.>siehe oben
Zitieren will auch gelernt sein.
"Das kann man erstens über einen Ansatz mit konstanter Abtastrate
lösen oder die Abtastrate der Ausgangsfrequenz anpassen."
Wenn man 800 Hz Sinus mit 128 Abtastwerte/Periode erzeugen will, braucht
man logischerweise 102,4 kHz PWM-Frequenz. Will man 5 Bit Auflösung
macht das 3,2768 MHz.
Aber für einen reinen Sinus ist das alles sowieso Overkill. Mit DDS
geht das bedeutend einfacher.
>Falk Brunner schrieb:>> Wozu brauchst du die variable j eigentlich?>Damit zähle ich das Bit in der Periode hoch (128 Bit = 1 Periode)>--> zählen kann ich auch
Was ja auch vollkommen unabhängig von der PWM-Erzeugung ist und man
dafür unbedingt einen zweiten Timer braucht . . .
Na dann mach mal.
MfG
Falk
So langsam gefällt mir die Konversation mit dir.
Falk Brunner schrieb:
> Du gibst aber pro PWM-Zyklus einen 5-Bit Wert aus, denn deine PWM kann> ja wahrscheinlich Werte zwischen 0..255 annehmen. Macht 1> BYTE/PWM-Zyklus.
NÖ
Meine PWM nimmt 64 Werte an (6 Bit: 0...63)
Aber ich habe mich unglücklich ausgedrückt:
Ich schrieb:
>Meine 500Hz sind ein Sinus mit 128 Bit/Periode macht 15,625µs pro Bit.
Richtig: Meine 500Hz sind ein Sinus, der aus 128 Schritten besteht
(500Hz = 2ms --> 2ms/128 Schritte = 15,625 µs pro Schritt). Nach einem
Schritt wird die PWM mit einem neuen Wert geladen.
Falk Brunner schrieb:
>>Siehst du, Sache nicht verstanden. Vielleicht habe ich auch zuviel von>>dir erwartet.>> Du bist ja ein ganz Schlauer. Wie alt bist du? 12 1/2?
Siehst du, Sache doch nicht verstanden. Vielleicht unterstellst du den
Fragestellern einfach zuviel! Du denkst für den Fragesteller mit und
schießt am Ziel vorbei.
Falk Brunner schrieb:
> Das sind keine 128 Bit, sondern 128 Abtastpunkte a 1 Byte.
Hier hast du Recht! Schritte = Abtastpunkte
ABER: 128 Abtastpunkte á 64 Bit
Falk Brunner schrieb:
>>> Wozu brauchst du die variable j eigentlich?>>>Damit zähle ich das Bit in der Periode hoch (128 Bit = 1 Periode)>>--> zählen kann ich auch>> Was ja auch vollkommen unabhängig von der PWM-Erzeugung ist und man> dafür unbedingt einen zweiten Timer braucht . . .
Wieder richtig! Die PWM-Frequenz läuft unabhängig von meiner zu
erzeugenden Frequenz! Immer stabil mit 125 kHz! Und ca. zwei PWM-Zyklen
pro Abtastpunkt. (500*128*2=128.000 - Meine PWM: 125kHz)
Der zweite Timer erzeugt die Frequenz des zu erzeugenden Signals!
Wenn es dich wirklich interessiert (davon gehe ich nicht aus) schau doch
mal in den Code.
Außerdem möchte ich auch keine Grundsatzdiskussion, wie du die Sache
angegangen wärst, sondern eine Lösung für mein geschildertes Problem!
Und wenn du helfen willst orientiere dich bitte an der Frage und
unterstelle niemanden Dummheit (Das gilt übrigens ganz allgemein und
nicht dieses Thread).
Falls du dem Fragesteller was unterstellst, dann kläre es mit ihm ab
oder frag ihn. Getreu dem Motto: Kann es vielleicht sein, dass du die
PWM nicht verstehst? o.ä.
Aber nicht: Du hast ja keine Ahnung von PWM! Nimm einfach den Timer mit
den Einstellungen und meiner Methode, dann gehts schon...
Also mein Motto, getreu den alten Funkern: Denken, drücken, sprechen!
soll heißen erst denken, das Probelm verstehen (aus der Sicht des
Fragestellers), dann Antwort formulieren und schließlich ins Forum
schreiben.
@ Bernd A. (Gast)
>Meine PWM nimmt 64 Werte an (6 Bit: 0...63)
In deinem Quelltext geht es bis 31, also 5 Bit.
Aber da ich mal wieder (unzulässigerweise) mitdenke, und du ja noch eine
invertierten Ausgang haben willst, sind es wahrscheinlich 32 Stufen pro
Polarität, also 64 Stufen von Spitze zu Spitze, erzeugt duch eine
H-Brücke.
>Aber ich habe mich unglücklich ausgedrückt:
In der Tat.
>Siehst du, Sache doch nicht verstanden. Vielleicht unterstellst du den>Fragestellern einfach zuviel!
Glaub ich nicht.
> Du denkst für den Fragesteller mit
Berufs- und Forumskrankheit ;-)
>> Das sind keine 128 Bit, sondern 128 Abtastpunkte a 1 Byte.>Hier hast du Recht! Schritte = Abtastpunkte>ABER: 128 Abtastpunkte á 64 Bit
Nöö. Du solltest dich a) mal mit Zahlensystemen und b) mit
Ausdrucksweise in der Welt der Programmierung/Elektronik befassen. Denn
deine Wortwahl ist falsch und irreführend.
Wenn deine Zahlen von 0..63 laufen sind das 6 Bit ;-)
Anzahl der verschiedenen Zahlen = 2 hoch Anzahl der Bits (im
Binärsystem)
>> Was ja auch vollkommen unabhängig von der PWM-Erzeugung ist und man>> dafür unbedingt einen zweiten Timer braucht . . .>Wieder richtig! Die PWM-Frequenz läuft unabhängig von meiner zu>erzeugenden Frequenz!
Ja und? Damit ist das Problem doch noch einfacher.
> Immer stabil mit 125 kHz! Und ca. zwei PWM-Zyklen>pro Abtastpunkt. (500*128*2=128.000 - Meine PWM: 125kHz)>Der zweite Timer erzeugt die Frequenz des zu erzeugenden Signals!
Was aber nicht sonderlich gut ist, denn damit kann man sich schöne
Artefakte ins Signal holen, wenn es da zu dummen Frequenzverhältnissen
kommt. Stichwort Schwebung etc.
Und ist auch sonst nicht sonderlich sinnvoll. Ein CD-Player hat auch nur
einen 44.1 kHz Takt (Jaja, ist ein alter CD-Player ;-), und mit dem
werden sämtliche Berechnungen/Datenausgaben gemacht.
>Außerdem möchte ich auch keine Grundsatzdiskussion, wie du die Sache>angegangen wärst, sondern eine Lösung für mein geschildertes Problem!
;-)
Jaja, klassicher Fall von Netiquette, oder vielmehr ein Mangel
derer.
Zitat
"Besonders für Anfänger gilt: Gerade am Anfang ist es immer gut zu
sagen, was man erreichen will und nicht so sehr Annahmen darüber zu
treffen, wie man es erreichen könnte und dann das Wie zu hinterfragen.
Oft ist der Denkfehler nämlich schon im Ansatz und man kann besser
helfen, wenn man das Ziel des Fragenden kennt."
>Und wenn du helfen willst orientiere dich bitte an der Frage und>unterstelle niemanden Dummheit
Deine Aussagen sprechen ihre eigene Sprache. Und als Supercrack kommst
du dabei nicht weg . . .
> (Das gilt übrigens ganz allgemein und nicht dieses Thread).>Also mein Motto, getreu den alten Funkern: Denken, drücken, sprechen!
Geh mal davon aus, dass du mich nicht über solche Dinge belehren musst.
MfG
Falk
Falk Brunner schrieb:
>>Meine PWM nimmt 64 Werte an (6 Bit: 0...63)>> In deinem Quelltext geht es bis 31, also 5 Bit.>> Aber da ich mal wieder (unzulässigerweise) mitdenke, und du ja noch eine> invertierten Ausgang haben willst, sind es wahrscheinlich 32 Stufen pro> Polarität, also 64 Stufen von Spitze zu Spitze, erzeugt duch eine> H-Brücke.
Guten Morgen!
Hast du meinen Quelltext wirklich gelesen?
1
voidpwm_init(void)//timer 0 init
2
{/* PWM-Output: OC0B */
3
/* OC0B -> ATmega88 PD5 */
4
5
TCCR0A=(1<<WGM00)|(1<<COM0B1);
6
TCCR0B=(1<<CS00)|(1<<WGM02);
7
8
OCR0A=64;// Top
9
// 1 Zyklus (0x00 - 0x3F) = 8MHz/64 = 125kHz
10
}
Wer lesen kann ist klar im Vorteil! Steht hier irgendetwas von 32??? Ich
denke nicht!
Falk Brunner schrieb:
>>Siehst du, Sache doch nicht verstanden. Vielleicht unterstellst du den>>Fragestellern einfach zuviel!>> Glaub ich nicht.
Glaub ich immer noch.
>> Du denkst für den Fragesteller mit>> Berufs- und Forumskrankheit ;-)
Solltest du vielleicht lassen. Es sit nicht immer wie es scheint.
Falk Brunner schrieb:
> Jaja, klassicher Fall von Netiquette, oder vielmehr ein Mangel> derer.>> Zitat>> "Besonders für Anfänger gilt: Gerade am Anfang ist es immer gut zu> sagen, was man erreichen will
Habe ich gemacht: eine invertierte PWM, um einen invertierten Sinus zu
erzeugen
>und nicht so sehr Annahmen darüber zu> treffen, wie man es erreichen könnte und dann das Wie zu hinterfragen.
Die Annahmen triffst du! Und liegst ganz oft kräftig daneben.
> Oft ist der Denkfehler nämlich schon im Ansatz und man kann besser> helfen, wenn man das Ziel des Fragenden kennt."
Genau, du sollst erst richtig und alles lesen, dann das wichtigste: es
VERSTEHEN und nicht glauben es zu wissen was der Fragende möchte.
Wenn dir das zuviel ist (das lesen), dann halt dich halt zurück.
Falk Brunner schrieb:
> Und als Supercrack kommst> du dabei nicht weg . . .
1. Möchte ich das gar nicht und 2. bin ich kein Supercrack, denn dann
würde ich nicht fragen.
Falk Brunner schrieb:
> Geh mal davon aus, dass du mich nicht über solche Dinge belehren musst.
Vielleicht nimmst du das Denken nicht allzu ernst. Geh davon aus, dass
der Fragende sich schon ein Weilchen damit beschäftigt hat und nicht
erst seit zwei Minuten am Thema hängt. Wenn dir das Klar ist, kannst du
ganz anders argumentieren und auch hoffentlich helfen dem Fragenden das
Problem zu lösen.
Um eueren Hick-Hack zu stören :
a) Mit Interrupts das Pin setzen geht es nicht, weil Du nicht
garantieren kannst, dass das Interrupt sofort ausgeführt wird, bzw. dass
die Zeit zwischen Compare Match und Abarbeiten der Interrupt immer
konstant ist. Du bekommst in jeden Fall einen Jitter.
Außerdem können die Interrupts bei sehr hohen oder sehr kleinen
PWM-Werten sehr schnell hintereinander kommen, weil die Flanken sehr
nahe sind. Da bleibt möglicherweise nicht mehr genug Rechenzeit.
b) Nach meiner Rechnung sollte die Periode der PWM 63.5 KHz sein. Du
setzt TOP auf 64, aber der Zähler zählt doch auf und ab, also 1-64 und
dann 63 - bis 0. Ergibt einen Zählperiode von 126.
c) Timer 1 kann das alles was Du möchtest. Er hat ein getrenntes TOP
Register (ICR1) und du kannst OCR1A und OCR1B verwenden.
Klaus Falser schrieb:
> Timer 1 kann das alles was Du möchtest. Er hat ein getrenntes TOP> Register (ICR1) und du kannst OCR1A und OCR1B verwenden.
Danke Klaus, du hast das Problem erkannt. Vielen Dank für den Hinweis,
werde mir den Timer 1 genauer betrachten. Timer 1 brauchte ich
eigentlich als 16-Bit-Timer für eine andere Geschichte, muss aber mal
schauen wenn es mit der PWM klappt, ob ich dann mit Timer 2 zurecht
komme.
Auf den Timer 2 kann man auch verzichten, den verwendest Du ja, um der
PWM den PWM Wert unter der Nase zu verdrehen.
Der Zähler der PWM kann aber auch ein Interrupt auslösen, wenn der
BOTTOM Wert erreicht ist, in deinem Fall alle 16 us. In diesem Interrupt
lädst Du den neue OCRx Wert, der dann bei BOTTOM übernommen wird. Das
ist der schnellste PWM update, der Sinn macht; jede PWM Periode bekommt
dann einen neuen Wert.
In der ISR hast Du 2 Möglichkeiten :
- Entweder Du bereitest ein Feld vor (volle Periode oder 1/4 Periode mit
Spiegeln) mit der genauen Länge im 16 us Raster und die Werte werden nur
mehr ausgelesen,
- oder Du bereitest eine allgemeine Sinus-Tabelle vor, addierst die
Phase auf, bestimmst daraus den Index für die Sinustabelle und die Werte
werden interpoliert (oder auch nicht).
>in deinem Fall alle 16 us>- oder Du bereitest eine allgemeine Sinus-Tabelle vor, addierst die>Phase auf, bestimmst daraus den Index für die Sinustabelle und die Werte>werden interpoliert (oder auch nicht).
Die Frage ist nur, ob das alles in die 16µs reinpasst.