Hi, Wie realisiere ich am besten 3 Phasenverschobene Sinuswellen mit einem STM32F4? Eine Sinuswelle ist mit einer Look-Up Table schnell erzeugt, aber wie kann ich es bewerkstelligen, dass die 3 Sinus Wellen zueinander 120° verschoben sind? Dafür bräuchte ich doch 3 Timer und die müssten irgendwie synchronisiert sein? Grüsse Sebastian
Eine Verschiebung in der Phase entspricht einem Verschiebung im Index in der Tabelle mit den Sinuswerten. Die Verschiebung addiert man halt vor dem Auslesen der Tabelle jeweils dazu. Wenn man es per Ausgabe per DMA machen will, muss man ggf. 2 Timer nutzen, wenn man nicht einen Timer als trigger für 2 DMAs nutzen kann. Bei der Ausgabe im Interrupt kann man die Tabelle natürlich auch mehrfach auslesen. Man muss im µC an sich nur 2 der 3 Sinussignale erzeugen (kommt also mit 2 DAC Ausgängen aus), der 3. Sinus lässt sich analog als -Wurzel 3 mal der summe der beiden anderen erzeugen.
Stimmt, danke, dann mache ich drei 120° verschobene look up tables.
Angenommen, Du hättest 3600 Werte in Deiner Sinus-Tabelle/Array. Nun nimmst Du 3 Zeiger und läßt sie jeweils in die Tabelle zeigen: - Zeiger 1 zeigt auf Array-Platz 0 - Zeiger 2 zeigt auf Array-Platz 1200 - Zeiger 3 zeigt auf Array-Platz 2400 Der Ablauf ist dann wie folgt: 1.) Hole Dir die 3 Werte auf die die 3 Zeiger zeigen aus Deiner Sinus-Tabelle und gib diese 3 Werte via D/A-Wandler aus 2.) Per Timer erhöhst Du die Zeiger dann jeweils um 1 und hüpfst dann wieder zu Schritt 1.) Selbstverständlich mußt Du ein wenig Hirnschmalz investieren, damit Deine Zeiger nach Position 3599 wieder bei 0 anfangen - aber das schaffst Du sicherlich. Viele Grüße Igel1
Bei einer Tabelle mit 256 Einträgen hat zum Zeitpunkt 0: - Sinus 1 die Phase 0° = Index 0 - Sinus 2 die Phase 120° = Index 86 - Sinus 3 die Phase 240° = Index 171 Da reicht auch eine Tabelle.
Lurchi schrieb: > Man muss im µC an sich nur 2 der 3 Sinussignale erzeugen (kommt also mit > 2 DAC Ausgängen aus), der 3. Sinus lässt sich analog als -Wurzel 3 mal > der summe der beiden anderen erzeugen. Das spart natürlich Speicher, danke. Ein bisschen was zum Hintergrund: Ich erhoffe mir mit einer Sinus Ansteuerung des DRV8313 BLDC Controllers einen ruhigeren lauf bei langsamen Geschwindigkeiten. Denkt ihr, mann kann einfach die EN Eingänge auf HIGH belassen und dann die IN Eingänge mit den drei Phasenverschobenen Sinuswellen füttern, also natürlich nicht D/A Wandlung vornehmen, sondern direkt durch die duty cycles? Datenblatt DRV8313: http://www.ti.com/lit/ds/symlink/drv8313.pdf Grüsse Sebastian
:
Bearbeitet durch User
Ich sehe nicht so recht, wie ich das Problem mit nur einem Timer lösen könnte. Um ein Sinus ähnliches PWM Signal zu erzeugen, muss ich ja den duty cycle anpassen, doch dies geht ja nicht so ohne weiteres bei 3 Parallel laufenden Sinus Wellen.
Schau Dir den HRTimer im F334 an. Ausserdem kannst Du 3 Timer im Master/Slave Betrieb nutzen. Timer A startet Timer B, Timer B startet Timer C. Alles Timer haben den gleichen ARR Wert und in das PWM Compare Register jeded Timers kommt der aktuelle PWM Wert aus der Sinustabelle.
Uwe B. schrieb: > Ausserdem kannst Du 3 Timer im Master/Slave Betrieb nutzen. Timer A > startet Timer B, Timer B startet Timer C. Alles Timer haben den gleichen > ARR Wert und in das PWM Compare Register jeded Timers kommt der aktuelle > PWM Wert aus der Sinustabelle. Kann ich das folgendermassen auf einem STM32F4 implementieren: Man nimmt z.B Timer2 und benützt 3 Subchannels für PWM Signale. Die jeweiligen duty cycles für die nächste Periode werden jeweils beim Aufruf von der IRQ für Timer2 festgelegt und dann werden auch gleich alle Timer wieder neu synchronisiert. Die Frequenz für den Sinus lege ich dann über den Prescaler oder evtl. ARR fest, wobei bei ARR die Abhängigkeit der Sinustabelle eine Rolle spielt.
:
Bearbeitet durch User
Sebastian T. schrieb: > Die > jeweiligen duty cycles für die nächste Periode werden jeweils beim > Aufruf von der IRQ für Timer2 festgelegt und dann werden auch gleich > alle Timer wieder neu synchronisiert Wieso so kompliziert? Du gibst im Interrupt für Timer 2 einfach alle 3 PWM-Werte neu aus, die du entsprechend (um 120 Grad) versetzt aus der selben Tabelle liest. Es werden weder weitere Timer gebraucht noch eine Synchronisation, die ergibt sich einfach aus dem Versatz in der Tabelle. Ich fürchte, nach dem bisherigen schwachen Verständnis ist auch nicht bekannt, dass man für einen Sinus nur eine Tabelle von 0..90 Grad braucht, also 12mal weniger Daten als von dir geplant. Georg
Georg schrieb: > Wieso so kompliziert? Du gibst im Interrupt für Timer 2 einfach alle 3 > PWM-Werte neu aus, die du entsprechend (um 120 Grad) versetzt aus der > selben Tabelle liest. Es werden weder weitere Timer gebraucht noch eine > Synchronisation, die ergibt sich einfach aus dem Versatz in der Tabelle. Und wie soll ich die ausgeben, wenn ich keinen D/A Wandler verwende? Mit D/A ist das klar, aber ohne muss ich ja 3 Timer benützen, sonst kann ich nicht unterschiedliche duty cycles haben.
Nochmals: Du verkettest Timer A, B und C. TIMa->ARR = TIMb->ARR = TIMc->ARR= ARR fuer benoetigte PWM Frequenz TIMa->CNT = 0, TIMb->CNT = ARR/3 TIMc->CNT = 2*ARR/3 TIMB ist Slave von TIMa, TIMc Slave von TIMb TIMa und TIMB senden Signal mit Timer Start, TIMa startest Du mit CEN. TIMa->CCRx = TIMb->CCR = TIMc->CCR = gewuenschter PWM Wert.
Man kann die drei PWM Signale auch mit einem einzigen Advanced Timer und den dazugehörigen CCRn Registern (und der DTI) erzeugen. Ein Pointer in eine 3 spaltige Tabelle mit U, V und W Werten reicht dazu - das Prinzip wird für kleine AVR in AppNote AVR447 beschrieben, die allerdings wirklich alle 3 Timer eines Mega88 belegt, weil es bei denen das Limit der komplementären Ausgänge gibt, jeder Timer hat nur 2. Diese Beschränkung gibts es beim Advanced Timer des STM32 nicht und es gibt ein DeadTime Unit, das einem ein paar Berechnungen abnimmt.
Für die Sinuswert reicht wirklich eine Tabelle, ggf. auch nur einer kleiner Teil der Periode, aber für eine Periode sollte der Platz i.A. reichen. Für das Einstellen der Frequenz kann man ähnlich wie beim DDS Generator vorgehen, also den Index nicht immer um 1 weiter zählen, sondern ggf. auch Zwischenwerte nutzen. So kann man die Sinus Frequenz unabhängig von der PWM Frequenz wählen ohne die Tabelle neu zu berechnen.
Sebastian T. schrieb: > Und wie soll ich die ausgeben, wenn ich keinen D/A Wandler verwende? Mit > D/A ist das klar, aber ohne muss ich ja 3 Timer benützen, sonst kann ich > nicht unterschiedliche duty cycles haben. Wofür braucht man den D/A Wandler in der ganzen PWM Generierung von Sine PWM?
Bei einem Arduino Mega hast Du Timer mit 3 Vergleichsregister für das PWM. Ansonsten kannst Du auch 3 Timer parallel laufen lasssen. Die bleiben schon synchron. Meine Sinustabelle ist 156 in der Länge (durch 3 teilbar).
1 | signed char si[156] = {0, |
2 | 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 54, 59, 63, 68, 72, 76, 80, 84, 88, 92, |
3 | 95, 98, 102, 105, 107, 110, 112, 115, 117, 119, 120, 122, 123, 124, 125, 126, 127, 127, 127, 127, |
4 | 127, 126, 125, 124, 123, 122, 120, 119, 117, 115, 112, 110, 107, 105, 102, 98, 95, 92, 88, 84, |
5 | 80, 76, 72, 68, 63, 59, 54, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0, -5, -10, |
6 | -15, -20, -25, -30, -35, -40, -45, -50, -54, -59, -64, -68, -72, -76, -80, -84, -88, -92, -95, -98, |
7 | -102, -105, -107, -110, -112, -115, -117, -119, -120, -122, -123, -124, -125, -126, -127, -127, -127, -127, -127, -126, |
8 | -125, -124, -123, -122, -120, -119, -117, -115, -112, -110, -107, -105, -102, -98, -95, -92, -88, -84, -80, -76, |
9 | -72, -68, -64, -59, -54, -50, -45, -40, -35, -30, -25, -20, -15, -10, -5 |
10 | };
|
Berechnung der 3 Stellen fuer den 120 Grad Versatz. "zaehl" wird laufend erhöht. Die Division durch 16 macht eine feinere Frequenzeinstellung möglich.
1 | arg0 = (zaehl / 16 + 0) % 156; |
2 | arg1 = (zaehl / 16 + 52) % 156; |
3 | arg2 = (zaehl / 16 + 104) % 156; |
Der Tabellenzugriff
1 | OCR5AL = X + Ampl * si[arg0] / 256 ; |
2 | OCR5BL = Y + Ampl * si[arg1] / 256 ; |
3 | OCR5CL = Z + Ampl * si[arg2] / 256 ; |
Dabei wird nach jedem pwm Zyklus ein Interrupt ausgelöst und dieser Vergleichswert geladen.
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.