Hallo zusammen,
ich habe einen Arduino und möchte mit diesem einen Sinus mittels PWM
erzeugen.
Dazu habe ich vor, die 360° des Sinus' mit einem Array von 360 Elementen
abzubilden. In jedem Element des Arrays soll ein Wert zwischen 0 und 255
enthalten sein (8 bit -> AVR), was dann später dem Tastverhältnis (PWM)
entsprechen soll.
In Excel habe ich dazu mit der Sinusfunktion einen Wertebereich von
1°-360° berechnet und daraus dann die Werte zwischen 0 und 255 erzeugt.
Allerdings scheint in meiner Wertetabelle etwas nicht stimmen...siehe
Graphen. Mir kommt der Sprung von 180° auf 181° seltsam vor.
Wisst ihr, wo das Problem liegen könnte?
Vielen Dank schon mal!
Grüße
Andreas
Vergiss die 360 Grad. Falls irgendwas, dann den Kreis durch 256 teilen,
das ergibt dann gerade einen Ringspeicher, der bei 8bit Ansteuerung
rundrum laeuft. Wobei man dann eh nur 90 Grad davon abspeichern wuerde,
die anderen Winkel ergeben sich durch Spiegelungen, Dh man benoetugt nur
64 Samples.
Dh du musst nur 0- pi/2 durch 64 samples abbilden. Als Sin & Cos.
Fuer einen BLDC die Clark & Park Transformation nicht vergessen.
Bei deiner berechnung fehlt der Negativ anteil. Dein AVR wird ebenfalls
perse keine Negativen spannungen ausgeben können. Du musst also darauf
achten ob du mit deiner Sinuserzeugung gerade in der negativen Sinus
halbwelle bist oder nicht.
Wenn du in der Negativen bist musst du dann vorkehrungen treffen dass
die Werte negativ werden.
Andreas Berglich schrieb:> Wisst ihr, wo das Problem liegen könnte?
Deine Wertetabelle lässt keine negativen Werte zu. Zeig doch mal wie du
sie berechnet hast.
rhf
Ok, Danke!
Das mit den 64 Werten klingt logisch.
Was ich nicht verstehe ist, warum ich den Kreis (360°) durch 256 teilen
soll. Letztlich hätte ich einfach ein Array mit 360 Elementen erzeugt.
Vielmehr würde mich interessieren, wie ich auf die Werte des
"Negativbereichs" komme.
Dass man mit 0 oder 1 keinen Negativbereich abbilden kann, ist mir klar.
Aber wie kann ich es in meiner Wertetabelle berechnen?
Danke!
Andreas Berglich schrieb:> Letztlich hätte ich einfach ein Array mit 360 Elementen erzeugt.
Du solltest binär denken. Das macht es dem binären Rechner
einfacher...
> Vielmehr würde mich interessieren, wie ich auf die Werte des> "Negativbereichs" komme.
Du ziehst von den Werten, die sprunghaft nach oben gehen, einfach 255
(oder eher 256) ab.
Und wenn du für die Minimalwerte und Maximalwerte deines Sinus nur 1
Byte über hast, dann musst du ihn auf den Bereich -128..127 skalieren.
Das pass als Zweierkomplement in ein Byte.
> warum ich den Kreis (360°) durch 256 teilen soll. Letztlich hätte ich einfach
ein Array mit 360 Elementen erzeugt.
Die Anzahl : 360 Werte sind zufaellig. Es koennten auch 400 sein. Fuer
Neugrad. Oder sinnvollerweise eine Zweierpotenz, zB 256. Allenfalls
gehen auch 128. Oder es sollten besser 512 sein.
Hallo zusammen,
so etwas habe ich auch schon gemacht. Du solltest Dein Array so bilden,
dass die Grundwelle ohne Tonausgabe bei der Hälfte der PWM-Frequenz
steht.
Sprich: Dein Sinus hat bei Beginn einen Wert von 127, im positiven
Maximum 254 und im negativen Maximum 0.
Es ist richtig, dass man prinzipiell nur 90° des Sinus abbilden muss und
sich den Rest durch rückwärts lesen und Verschiebung durch Addition
bilden kann. Das verkompliziert den Code für den Anfang allerdings.
Ich würde vorschlagen eine Sinustabelle mit 256 Werten zu nehmen, was
einem Byte-Array von 256 Werten entspricht. Ein Timer steuert die PWM
mit der maximalen Frequenz, um den Sinus durch Aliasing sauber hin zu
bekommen, der zweite Timer inkrementiert den Pointer, der auf das
aktuelle Arrayelement zeigt. Mit der Geschwindigkeit des 2. Timers
steuerst Du die Frequenz.
Auf jeden Fall benötigt man einen sehr guten Tiefpass mind. 3. oder
besser 5. Ordnung hinter dem PWM-Ausgang, um das Signal von Oberwellen
zu befreien. Ich empfehle dafür den AADE-Filterdesigner. Für große
Induktivitäten kann man Entstördrosseln verwenden.
Code kann ich im Moment nicht zeigen, aber ein Foto vom Scope.
Mehr Infos zum Thema: http://forum.db3om.de/ftopic24353.html
Viele Grüße!
Sven
Sven L. schrieb:> Es ist richtig, dass man prinzipiell nur 90° des Sinus abbilden muss und> sich den Rest durch rückwärts lesen und Verschiebung durch Addition> bilden kann. Das verkompliziert den Code für den Anfang allerdings.
Nicht, wenn man es schlau anstellt. Denn die Information, welcher Wert
aus dem Viertelsinus zu werten ist, steht in den obersten beiden Bits.
Dort habe ich das mal mit VHDL beschrieben:
http://www.lothar-miller.de/s9y/archives/37-DDFS-mit-BROM.html
Der Viertelsinus hat 64 Werte, und der Ausgabewert berechnet sich
ausgehend von einem "Vollsinus" mit 256 Punkten (=index) in C etwa so:
http://www.daycounter.com/Calculators/Sine-Generator-Calculator.phtml
Wertebereich und gewünschte Länge angeben, heraus kommt eine direkt für
C geeignete Copy&Paste Tabelle. Geschweifte Klammern um das Ganze und
der Tabelle einen Namen geben. Bei Bedarf noch PROGMEM oder andere
Spässchen hinzufügen. Nicht vergessen, das letzte Komma zu entfernen.
@Lothar Miller (lkmiller) (Moderator) Benutzerseite
>> Es ist richtig, dass man prinzipiell nur 90° des Sinus abbilden muss und>> sich den Rest durch rückwärts lesen und Verschiebung durch Addition>> bilden kann. Das verkompliziert den Code für den Anfang allerdings.
Eben.
>Nicht, wenn man es schlau anstellt. Denn die Information, welcher Wert>aus dem Viertelsinus zu werten ist, steht in den obersten beiden Bits.
Lohnt sich das auf einem kleinen Controller? Was hat man eher übrig,
Flash oder CPU-Leistung?
>if (index&0x40) result = viertelsinus[63-(index&0x3f)]; // rückwärts>else result = viertelsinus[ (index&0x3f)]; // vorwärts>if (index&0x40) result = -result; // negieren
Ein einfaches
OCR1A = sinus[index];
ist da deutlich einfacher und schneller. Die paar hunder Bytes Speicher
sind selten ein Problem.
Man kann auch am Anfang in der main() das Array mit sin(x) Werten füllen
(Math.h) sofern man genug Speicherplatz hat.
PWM Erzeugung dann (mit dem 8 Bit Timer): OCRx = 128 + sintable[n]
wobei in sintable die Werte von +127 bis -127 stehen (in welchen
Abstufungen musst du entscheiden, aber ein 256 Elemente Ringpuffer
bietet sich an, sintable[n++] rotiert dich immer durch den Puffer
durch).
Am PWM Pin kommt dann ein Sinus mit DC-Offset raus, den packst du mit
Koppelkondensator (hat Nullstelle bei DC) an einen Tiefpassfilter
(Rekonstruktionsfilter) mit geeignetem Amplitudengang und fertig ist
dein symmetrischer Sinus.
Matthias S. schrieb:> http://www.daycounter.com/Calculators/Sine-Generator-Calculator.phtml>> Wertebereich und gewünschte Länge angeben, heraus kommt eine direkt für> C geeignete Copy&Paste Tabelle.
Aber eine nicht so besonder schlau gerundete mit zufälligem Offset.
Das sollte man lieber MATLAB überlassen. Außerdem zeigt sich daß die
Umsetzung auf eine PWM auch noch zu einem Fehler führt, den man in der
Tabelle berücksichtigen sollte, um ihn zu minimieren.
Thomas U. schrieb:> Aber eine nicht so besonder schlau gerundete mit zufälligem Offset.> Das sollte man lieber MATLAB überlassen. Außerdem zeigt sich daß die> Umsetzung auf eine PWM auch noch zu einem Fehler führt, den man in der> Tabelle berücksichtigen sollte, um ihn zu minimieren.
Ich fürchte nur, nach fast einem Jahr hat das kaum noch Relevanz.
Der link ist noch aktuell und die dort angebotenen Werte sind sicher die
gleichen wie von vor einem Jahr. Und sie sind nicht sonderlich
intelligent gerundet, als das sie Beispiel für eine gute Wertegeneration
wären.
Ist aber nett, dass Du aufpasst.
Thomas U. schrieb:> Matthias S. schrieb:>> http://www.daycounter.com/Calculators/Sine-Generator-Calculator.phtml>>>> Wertebereich und gewünschte Länge angeben, heraus kommt eine direkt für>> C geeignete Copy&Paste Tabelle.>> Aber eine nicht so besonder schlau gerundete mit zufälligem Offset.> Das sollte man lieber MATLAB überlassen. Außerdem zeigt sich daß die> Umsetzung auf eine PWM auch noch zu einem Fehler führt, den man in der> Tabelle berücksichtigen sollte, um ihn zu minimieren.
Das ist ein Thema, das man doch besser im PWM-Modulator regeln sollte,
weil die dafür nötige Vorverzerrung auf dessen Verhalten und Auflösung,
sowie auch an das Folgesystem angepasst werden muss. In der Tabelle kann
man das nur einbringen, wenn die Drehzahl und das Fehlerspektrum
statisch sind und alles vorausberechnet werden kann - wenn der Modulator
also stur geradeaus arbeitet und Linearität annimmt.