Forum: Mikrocontroller und Digitale Elektronik Sinuswerte für PWM berechnen


von Viktor N. (tondela)


Lesenswert?

Guten Tag,
ich möchte eine sinusfunktion über PWM generieren. das Grundprinzip 
kenne ich schon(sinus Tabelle, 2 timer ISR...)
erstmal möchte ich verstehen wie man die Sinuswerte berechnet.

die sinusfunktion hat eine Frequenz von 50 HZ und möchte 20 stützstelle 
berechnen.
die Formel habe ich in Foren gefunden:128+127*sin((double)i/256*2*pi);
aber ich denke das gilt nur für 8-Bit Timer und 256 schritte. soll ich 
einfach die Forlmel anpassen? (32768+32767*sin(i/20*2*pi))
ich wollte eigentlich mit sin(wt)= sin(2pif*(t+dt)) die sinuswerte 
berechnen, wobei dt= 1 ms ist. richtig?
ich benutzte ein 16-Bit Timer
Danke für eure Hilfe
Viktor

von Matthias L. (Gast)


Lesenswert?

>soll ich einfach die Forlmel anpassen?


Ich würde einfach nachdenken:

Sinuswert = Amplitudenspitzenwert mal SIN ( Winkel )

Dein Amplitudenspitzenwert ist für 16bit signed also 32767.
Der Winkel läuft von [0;360) Grad. Du willst 20 Stützstellen, also 
teilst Du das durch 20:

Winkel = n mal 20 durch 360. Mit n=[0;19].

Jetzt hast Du deine Tabelle.

Hinweis:
Aufgrund von Symmetrien würde es reichen, die Sinuskurve zwischen 0 und 
90 Grad als Tabelle abzulegen.

von Viktor N. (tondela)


Lesenswert?

Vielen Dank für die Antwort.
ich hätte noch ein paar Frage
warum in der folgenden Formel(wert[i]=128+127*sin((double)i/256*2*pi);)
 der berechnete Sinuswert noch mit 128 addiert wird? dabei möchte man 
scheinbar das MSB komplementiere.
wenn ich eine zweite sinusspannung um 180° versetzt erstellen möchte, 
reicht es wenn ich einfach in meine Berechnung  180 zu dem Winkel 
addiert oder geht es nicht so einfach?

ich steige erst jetzt in die Microkontrollerrogramierung und muss noch 
viel lernen.
Danke

von Matthias L. (Gast)


Lesenswert?

>der berechnete Sinuswert noch mit 128 addiert wird?

Das kann man nur sicher herausfinden, wenn man den Kontxt beachtet, wo 
du diese Formel abgeschrieben hast. Denkbar wäre aber das 
Zweierkomplement.



>wenn ich eine zweite sinusspannung um 180° versetzt erstellen möchte,
>reicht es wenn ich einfach in meine Berechnung  180 zu dem Winkel
>addiert oder geht es nicht so einfach?


Ja. Also quasi immer 10Schritte vor deinem anden sein...

von Electronics'nStuff (Gast)


Lesenswert?

Matthias Lipinsky schrieb:
> Aufgrund von Symmetrien würde es reichen, die Sinuskurve zwischen 0 und
> 90 Grad als Tabelle abzulegen.

Reicht, aber falls du nachher noch was mit dem Signal machen willst ist 
es oft sinnvoll alle Werte (also für 360°) aufzulisten.

von Reinhard Kern (Gast)


Lesenswert?

viktor N. schrieb:
> der berechnete Sinuswert noch mit 128 addiert wird?

weil der Sinus +-1 sein kann, das würde eine Periodenlänge von -127 ... 
+127 erzeugen, die wird damit verschoben zu 0 .. 255.

viktor N. schrieb:
> wenn ich eine zweite sinusspannung um 180° versetzt erstellen möchte,
> reicht es wenn ich einfach in meine Berechnung  180 zu dem Winkel
> addiert oder geht es nicht so einfach?

Es geht noch einfacher, nimm einfach den negativen Wert, bzw. bei dieser 
Formel 255 - Wert.

Gruss Reinhard

von Viktor N. (tondela)


Lesenswert?

Vielen Dank an alle
Mit Freundlichen Grüßen
Viktor

von Viktor N. (tondela)


Lesenswert?

Matthias Lipinsky schrieb im Beitrag #3002939
>
> Sinuswert = Amplitudenspitzenwert mal SIN ( Winkel )
>
> Dein Amplitudenspitzenwert ist für 16bit signed also 32767.
> Der Winkel läuft von [0;360) Grad. Du willst 20 Stützstellen, also
> teilst Du das durch 20:
>
> Winkel = n mal 20 durch 360. Mit n=[0;19].
>
eher n*360 durch 20 oder?
>

von Karl H. (kbuchegg)


Lesenswert?

viktor N. schrieb:
> Matthias Lipinsky schrieb im Beitrag #3002939
>>
>> Sinuswert = Amplitudenspitzenwert mal SIN ( Winkel )
>>
>> Dein Amplitudenspitzenwert ist für 16bit signed also 32767.
>> Der Winkel läuft von [0;360) Grad. Du willst 20 Stützstellen, also
>> teilst Du das durch 20:
>>
>> Winkel = n mal 20 durch 360. Mit n=[0;19].
>>
> eher n*360 durch 20 oder?

korrekt.

Mir ist echt nicht klar, wonach du fragst. Du scheinst alles zu 
verstehen!

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Hier ist übrigens ein netter online Rechner:
http://www.daycounter.com/Calculators/Sine-Generator-Calculator.phtml
Liefert Copy&Paste CSV :-P

von chris (Gast)


Lesenswert?

>Sinusberechnung
Im Code für dieses Projekt findest Du zwei Beispiele:

Beitrag "Arm Synthesizer mit LPC1114"

Im ersten Programm, dem Waveformgenerator, wird der Sinus über eine 
Sinus/4 Tabelle erzeugt.
Im zweiten Programm, dem Glockentongenerator, findet sich ein 
Python-Script zur Berechung einer Sinustabelle mit einer ganzen Periode. 
Das Python Script erzeugt eine C-Datei, die in Programme eingebunden 
werden kann.

von Viktor N. (tondela)


Lesenswert?

Nochmal vielen Dank für die Beiträge
nun eine zweite Frage über die PWM-Frequenz und die Frequenz des 
Abtasttimer
(für die PWM Erzeugung benutze ich 2 Timer)
meine Tabelle enthält 20 Werte, ich lade der PWM generator jede 1ms
meine PWM-Frequenz beträgt 10KHZ und scheint mir zu groß zu sein. wie 
hängen die beide Frequenze zusammen? gibst dafür einen Faustregel?

ich kann mein Programm leider nicht testen, da die bestellte Hardware 
noch nicht da sind

von Christian B. (luckyfu)


Lesenswert?

Einen Timer nimmst du und lädst die Werte aus deiner Tabelle als 
Umschaltwert für die PWM ein. Damit bestimmst du das Tastverhältnis, der 
Vorteiler dieses Timer bestimmt deine PWM Frequenz in Verbindung mit 
deiner Taktquelle.
Der 2. Timer läuft autark und generiert in passenden Abständen 
Interrupts welche die Werte für den ersten Timer überschreiben. der 
bestimmt dann die "Sinusfrequenz".
Die Frequenzen der beiden sind nur in sofern voneinander abhängig, daß 
der PWM Timer nat. viel schneller sein muss als der Drehfeldzeiger.

von STK500-Besitzer (Gast)


Lesenswert?

viktor N. schrieb:
> gibst dafür einen Faustregel?
Nein, da hilft nur die Mathematik :-)

Frequenz = Schrittweite / Tabellenlänge

Die Tabellenberechung ist mit google zu finden:

Digitale Sinusfunktion

von Karl H. (kbuchegg)


Lesenswert?

> meine PWM-Frequenz beträgt 10KHZ und scheint mir zu groß zu sein.

Wieso scheint dir die zu groß zu sein?

> wie hängen die beide Frequenze zusammen?

gar nicht.

ok, ein bischen schon. Der Abtasttimer muss der PWM natürlich auch eine 
Chance geben, die Vorgabe mithilfe der PWM auch zu realisieren. Von 
daher darf das nicht zu schnell sein, sonst gibt der Abtasttimer (über 
den Umweg der PWM) einen Spannungswert vor, der am Ausgang nie 
realisiert wird. So gesehen kann die PWM gar nicht schnell genug sein. 
Aber scheinbar hast du dieses Problem ja nicht, wenn du das Gefühl hast 
deine PWM sei zu schnell.

von Viktor N. (tondela)


Lesenswert?

Danke für die Antwort
die Sinustabelle weisst ich schon wie man die berrechnet oder mit 
C-program erstellt.
ich werde alles besser verstehen wenn ich die sinusspannung an dem Oszi 
visualisiere und die PWM frequenz variire.
Gruss
Viktor

von Reinhard Kern (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> sonst gibt der Abtasttimer (über
> den Umweg der PWM) einen Spannungswert vor, der am Ausgang nie
> realisiert wird.

Na ja, dann fehlt halt ein Wert bzw. der Sinus weist eine Treppenstufe 
auf. Das ist sowieso unvermeidbar, die Frage ist bloss wie gross die 
Stufe im konkreten Fall ist und welche Anforderungen an den Sinus 
gestellt werden. Für einen Motor reicht es, wenn eine gewisse 
Sinusähnlichkeit vorliegt, ein HIFI-Fan wäre damit nicht zufrieden.

Gruss Reinhard

von Doc Morris (Gast)


Lesenswert?

Reinhard Kern schrieb:
> Für einen Motor reicht es, wenn eine gewisse
>
> Sinusähnlichkeit vorliegt

nun ja, auch der Motor sieht diese Oberwellen und sie erzeugen nicht 
geringe Verlutste- gerade, weil der Motor sieht fast nicht mitmacht. 
Dafür hast Du mehr EMI. Auch Motorspannungen sollten oberwellenarm sein.

von MaWin (Gast)


Lesenswert?

> erstmal möchte ich verstehen wie man die Sinuswerte berechnet

http://www.tinaja.com/magsn01.shtml

von Viktor N. (tondela)


Lesenswert?

Guten Tag an alle
ich habe endlich meine PWM realisiert und am Oszi visualisiert. alles 
ist nicht wie ich gedacht habe und ich möchte verstehen wo der Fehler 
liegt.
der erste Timer(PWM) zählt von 0 bis 100(periode).

die kleinste Sinuswerte die ich in dem 2.timer übergebe ist 1604. könnte 
das das Problem sein? denn die max Wert des Zählers(1. timer) müsste 
gleich  die größte Sinuswert(65356) in der Sinustabelle sein. stimmt?

oder muss bei der übergabe an der PWM Generator die Sinuswerte im 
Bereich(0...100) skalieren) 100->65536 0->0

villeicht ist das schwachsinn was ich geschriebe habe?
vielen Dank für euere Beiträge

PS: Beiträge über DDS habe ich gelesen, gelesen und gelesen...

von Karl H. (kbuchegg)


Lesenswert?

Wie immer gilt:
Labere nicht um deinen Code rum, sondern zeige ihn!

Wenn der Fehler dort stecken würde, wo du ihn vermutest, würdest du ihn 
höchst wahrscheinlich selber sehen.

von Viktor N. (tondela)


Angehängte Dateien:

Lesenswert?

Hallo,
im Anhang steht der Wichstigste Teil meiner Code. die Initialisierung 
habe ich weggelassen. am Oszilloskop bekomme ich ein invertierte PWM mit 
50HZ und der Tastverhältnis bleibt konstant.
ich habe die Spannung direkt an Ports des STM32 VL gemessen, und nicht 
über ein RC-Glied.
ich verstehe leider mein ergebniss nicht. ich habe ein 10khz pwm mit 
variabel duty cycle erwartet.
Viele Grüße
Viktor

von Matthias L. (Gast)


Lesenswert?

Was ist xps?

von Karl H. (kbuchegg)


Lesenswert?

> am Oszilloskop bekomme ich ein invertierte PWM mit
> 50HZ und der Tastverhältnis bleibt konstant.

> ich habe ein 10khz pwm .... erwartet.


Vielleicht solltest du dich erst mal darum kümmern.
Das scheint mir die erste Baustelle zu sein ... völlig losgelöst von 
irgendwelchen Sinus-Werten.

Wenn du eine 10kHz PWM erwartest, aber nur eine 50Hz PWM kriegst, dann 
stimmt offenbar mit den Timer Einstellungen etwas nicht.


PS:
Häng doch einfach dein C-File hier an.
Dann braucht keiner Zusatzsoftware, die Forensoftware kümmert sich um
ein Syntax-Highlighting und wir können deinen Code in seiner Gesamtheit
studieren.

von Viktor N. (tondela)


Angehängte Dateien:

Lesenswert?

Hallo,
Danke für die Antwort. ich habe es geschaft, 10KHZ Signal mit 10% 
Tastverhältnis mit der obigen Timerkonfiguration zu kriegen(Ohne die 
Sinuswerte).
im Anhang meine C-Datei.
Gruss

von Christian B. (luckyfu)


Lesenswert?

aber am besten inclusive der Initialisierung, denn wenn mit dem Timing 
etwas nicht stimmt (apropos, wie ist denn die div8 Fuse gesetzt wenns 
ein atmel ist? da bin ich auch schon reingefallen) klärt sich das 
oftmals in der Initialisierung. Das nennen der Zielhardware währe auch 
von vorteil (oder hab ich das nur übersehen)

von Karl H. (kbuchegg)


Lesenswert?

viktor N. schrieb:
> Hallo,
> Danke für die Antwort. ich habe es geschaft, 10KHZ Signal mit 10%
> Tastverhältnis mit der obigen Timerkonfiguration zu kriegen(Ohne die
> Sinuswerte).

Hmm.
Wieder - wenn ich den Sinus einfach mal ignoriere.

Wie kommen die 10% zustande.
Ich sehe in deinem Code nichts, was diese 10% erklären könnte.

Hast du denn schon mal versucht einfach nur mit dem Timer 2 eine PWM zu 
erzeugen (und sonst ist nichts in deinem Programm; kein Timer 3; kein 
Interrupt; keine INterrupt Service Routine) und dann gezielt die PWM auf 
einen Wert einzustellen?

Also einfach nur
1
....
2
3
int main()
4
{
5
  alles initialisiersen
6
7
  Timer einstellen
8
9
  PWM Wert auf 40% setzen
10
11
  while( 1 )
12
  {
13
  }
14
}

und nachgesehen, ob du dann auch wirklich 40% kriegst? Und wenn du 
anstelle der 40% auf 80% gehst, siehst du dann auch die 80%?
Irgendwie werde ich das Gefühl nicht los, du hast das noch gar nicht 
probiert um zu sehen, wie das mit der PWM eigentlich auf deinem STM 
funktioniert. Dazu kann ich nur sagen: Solceh Dinge sollte man IMHO 
immer erst mal einzeln testen. Die Dinge werden nicht einfacher, wenn 
man 25 ungetestete Module versucht zusammenzuschalten, mit denen man 
keine Erfahrung gesammelt hat. Das führt im Normalfall einfach nur zu 
einem Programm welches nicht funktioniert, und keiner hat auch nur den 
Hauch einer Ahnung, wo das Problem steckt, weil alles ungetestet ist und 
der Programmierer mit keinem der 25 Module auch nur die geringste 
Erfahrung hat.

von Viktor N. (tondela)


Angehängte Dateien:

Lesenswert?

ich habe zwar keine Erfahrung aber ich bemühe mich seit ein paar Tagen 
mit dem stm 32 zu Programieren. ich lerne von Anfang an(Datenblätter, 
Grundprogramme)
die angehängte code generiert genau ein 10KHZ Signal mit 40% Duty Cycle
leider habe ich kein USB sctik dabei um das Bild vom Oszi hier 
anzuhängen.

die Code habe ich einfach erweitern um meine PWM Signal zu generieren.

Gruß
Viktor

von Karl H. (kbuchegg)


Lesenswert?

Gut.
Und die 40% enstehen wodurch?

Sind die deswegen
       TIM_OC_InitStructure.TIM_Pulse = 40;

gesetzt?

Kannst du die Pulsbreite auch ohne diese Struktur setzen?
In deinem ursprünglichen Code machst du später ein
  TIM2->CCR2 = ...


verändert das deine PWM, wenn du mal nach dieser Initialisierung ein

  TIM2->CCR2 = 60;

machst. Ergibt das eine 60% PWM? Oder was musst du tun, damit du in 
deinem letzten Code die Pulsbreite auf 60% setzen kannst OHNE dass du 
dazu die diese Init Structure benutzt.
Das ist doch der entscheidende Punkt. Denn genau darauf läuft es doch 
hinaus. Du kannst für dein endgültiges Projekt nicht mehr diesen Weg mit 
der Initialisierung gehen. Also musst du bei deinen Vortests das auch so 
raustesten: wie kann ich die PWM auf einen Wert setzen, ohne dass ich ds 
mit der Init Funktionalität mache. Vielleicht gibts ja auch eine 
vorgefertige Funktion, die genau das macht. Der du diese Init-Struktur 
gibst, samt gewünschtem PWM Wert und die macht die Berechnungen für dich 
und setzt den Wert in die Hardware. Hast du das schon mal kontrolliert?

von Viktor N. (tondela)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Gut.
> Und die 40% enstehen wodurch?
>
> Sind die deswegen
>        TIM_OC_InitStructure.TIM_Pulse = 40;
>
> gesetz?
genau. wenn ich TIM_OC_InitStructure.TIM_Pulse = 60; schreibe, ändert 
sich auch die Pulsbreite um 60%
>
> Kannst du die Pulsbreite auch ohne diese Struktur setzen?
> In deinem ursprünglichen Code machst du später ein
>   TIM2->CCR2 = ...
Ja. das habe ich auch schon probiert un es funktioniert.
>
>
> verändert das deine PWM, wenn du mal nach dieser Initialisierung ein
>
>   TIM2->CCR2 = 60;
 dann habe ich 60% Pulsbreite. das sehe ich genau am Oszilloskop.
in der ISR wollte ich dann anhang der Sinuswerte die Pulsbreite 
variiren. aber irgendwie klappt es nicht
Danke für die Hilfe
Gruß

von Karl H. (kbuchegg)


Lesenswert?

viktor N. schrieb:

>>   TIM2->CCR2 = ...
> Ja. das habe ich auch schon probiert un es funktioniert.

Sehr gut!

> in der ISR wollte ich dann anhang der Sinuswerte die Pulsbreite
> variiren. aber irgendwie klappt es nicht

Na ja. Logisch.
Wenn da der Zahlenwert die Prozentangabe macht, dann wirst du da nicht 
die Zahl 32767 zuweisen können. Denn mehr als 100% geht nun mal nicht. 
32 tausend 7 hundert 67 Prozent PWM ist nicht möglich.


Nächster systematischer Schritt.
Der andere Timer.
Läuft der und wird die Interrupt Funktion aufgerufen?

Was ist wenn du mal das hier in der Interrupt Funktion machst
1
static int PWM_Percent;
2
3
void TIM3_IRQHandler(void)
4
{
5
  TIM2->CCR2 = PWM_Percent;
6
7
  PWM_Percent++;
8
  if( PWM_Percent > 100 )
9
    PWM_Percent = 0;
10
11
  TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
12
}

Siehst du am Oszi, wie sich die PWM von 0 bis 100% durchverändert und 
wenn ja, wie lange dauert das, bis die PWM wieder auf 0 zurückspringt? 
(ungefähr. Wenn deine 50 ISR Aufrufe / Sekunde noch gültig sind, dann 
sollte das 2 Sekunden dauern)

von Viktor N. (tondela)


Lesenswert?

Hallo Karl
erstmal Vielen Dank für deine Hilfe
ich habe deine Code in der ISR eingegeben: die PWM wächst kontunerlich 
und  springt auf null wieder. das dauert etwa 2 sekunde und wiederholt 
sich.
das sieht schon gut aus. jetzt soll ich meine Sinuswerte anpassen. wie 
könnte ich vorgehen? ich ändere ZB die Sinus werte auf 10Bit und gebe 
als maximalwert in dem Zälregister des ersten Timers 1024 statt 100?
Gruß

von Karl H. (kbuchegg)


Lesenswert?

viktor N. schrieb:

> das sieht schon gut aus. jetzt soll ich meine Sinuswerte anpassen. wie
> könnte ich vorgehen?

a) Du könntest deine Tabelle so verändern, dass sich die Amplitude des
   Sinus nicht von 0 bis 65536 erstreckt, sondern von 0 bis 100
b) Du könntest eine entsrechende Umrechnung in die ISR machen
c) Du könntest deine PWM verändern, so dass du anstelle von Werten von
   0 bis 100, dann eben Werte von 0 bis 65536 reingeben kannst.
   Was dann allerdings die PWM Frequenz wieder senken wird.
d) Du könntest einen Mittelweg aus a) und c) gehen


> ich ändere ZB die Sinus werte auf 10Bit und gebe
> als maximalwert in dem Zälregister des ersten Timers 1024 statt 100?

Das wäre der letzte Punkt d). Also: machen!
Aber Achtung: Wenn du die PWM Frequenz bei 10kHz halten willst, dann 
musst du den PWM-Timer im Gegenzug entsprechend schneller zählen lassen.

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
Noch kein Account? Hier anmelden.