Forum: Mikrocontroller und Digitale Elektronik STM32 Phasenverschobene Sinuswellen


von Sebastian T. (sebastian_tsch)


Lesenswert?

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

von Günter Lenz (Gast)


Lesenswert?

Ein Timer und eine dreispaltige Tabelle müßte auch gehen.

von Lurchi (Gast)


Lesenswert?

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.

von Sebastian T. (sebastian_tsch)


Lesenswert?

Stimmt, danke, dann mache ich drei 120° verschobene look up tables.

von Andreas S. (igel1)


Lesenswert?

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

von S. R. (svenska)


Lesenswert?

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.

von Sebastian T. (sebastian_tsch)


Lesenswert?

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
von Sebastian T. (sebastian_tsch)


Lesenswert?

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.

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

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.

von Sebastian T. (sebastian_tsch)


Lesenswert?

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
von Georg (Gast)


Lesenswert?

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

von Sebastian T. (sebastian_tsch)


Lesenswert?

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.

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

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.

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


Lesenswert?

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.

von Lurchi (Gast)


Lesenswert?

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.

von Alexander (Gast)


Lesenswert?

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?

von 0815 (Gast)


Lesenswert?

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