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
>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.
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
>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...
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.
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
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? >
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!
Hier ist übrigens ein netter online Rechner: http://www.daycounter.com/Calculators/Sine-Generator-Calculator.phtml Liefert Copy&Paste CSV :-P
>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.
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
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.
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
> 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.
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
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
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.
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...
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.
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
> 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.
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
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)
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.
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
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?
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ß
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)
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ß
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.