Mehrphasige PWM-Signalerzeugung auf TMS320F28027

Es war einmal in einer fernen fernen Galaxie Ich habe einen kurzen Artikel über den speziellen Piccolo-Controller von Texas Instruments geschrieben, der zur Steuerung von Stromrichtern und elektrischen Antrieben entwickelt wurde. Diese Controller sind sehr leistungsfähige Entwicklungswerkzeuge für viele Aufgaben, und ich wollte etwas anderes darüber schreiben ... einfach und nützlich.


Vor kurzem war ich verwirrt, eine Steuerung für die Motorsteuerung zu entwickeln, und dementsprechend wurde ein Thema für den Artikel formuliert. Heute werde ich über den Prozess der Bildung einer dreiphasigen PWM für die Motorsteuerung sprechen und die vorteilhaften Unterschiede zwischen TMS320F28 und anderen Steuerungen wie STM32F334, STM32G484, XMC4200 und anderen erläutern.


Als Stand werde ich den Controller in der Entwicklung verwenden, leider kann ich nicht im Detail über das Eisenteil sprechen. Wenn ich jedoch sage, dass der Controller auf dem TMS320F28027 + DRV8353RSRGZT-Bundle basiert, können Sie sich die Treiberdaten ansehen und das allgemeine Schaltungskonzept sehen + es gibt ein Debugging auf diesem Stein und das Referenzdesign ist darauf offen.


BLDC-Treiber


Im Prinzip ist es bei der gleichen Art von Schaltung möglich, BLDC-Motoren zu steuern, die Spannungspegel "verbrauchen", und gewöhnliche Dreiphasenmotoren, die bereits einen sinusförmigen Ausgang wünschen. Ich werde beide Optionen als zeigen Der Weg zum Sinus liegt in der Bildung von Spannungspegeln.


Oszillogramm Nummer 1


Ein bisschen über Eisen


Der Leistungsteil des Treibers besteht ideologisch aus 3 Halbbrückenwandlern, wahrscheinlich sind alle Chastotniks und Steuerungen zur Steuerung von BLDC-Motoren in allen Koptern auf ähnliche Weise hergestellt:


Dreiphasenbrücke


Ein Unterschied - ich habe keinen Eingangsgleichrichter, weil Die Steuerung wird anfänglich von einer konstanten Spannung gespeist. Die Stromquelle in meinem Fall ist eine Anordnung von Li-Ionen-Batterien in Form von 18650-Zellen. Der verwendete DRV8353RSRGZT-Treiber kann nur 3 Leistungshalbbrücken steuern. Auch in der verwendeten Version des Steins sind eingebaute Operationsverstärker für die Arbeit mit Shunts als Stromsensoren eingebaut Gleichstrom / Gleichstrom, der bis zu 70 ... 80 V verarbeiten kann, und all dies ist sehr flexibel über SPI konfiguriert. Zum Beispiel ist es sehr praktisch, den maximalen Impulsstrom der Transistorsteuerung einstellen zu können.


Auch in dieser Serie gibt es Treiber mit einem anderen Funktionsumfang, zum Beispiel mit analoger Steuerung, nicht SPI oder ohne eingebauten DC / DC und ohne Operationsverstärker. Für den Preis sind sie nicht sehr unterschiedlich und ich habe das "kühnste" genommen, wie Sie wahrscheinlich schon verstanden haben. Das Ganze sieht sehr schön aus, aber ich habe mich ziemlich leichtfertig dem Design der Treiberbindung genähert und 2 bedeutende Probleme gelöst. In der Tat gibt es nur ein Problem - dies ist eine starke Überhitzung:


Wärmebildkamera


Dieses Problem wurde jedoch aus zwei Gründen verursacht. Tatsächlich besteht die Essenz des Problems in der Überhitzung des Fahrers. Auf dem Thermogramm ist der Fahrer mit einem Strom von 5 A belastet (für ihn ist es fast im Leerlauf) und nichts als der Fahrer und der MK selbst werden ein wenig erwärmt. Transistoren sind nicht einmal sichtbar, sie haben eine PCB-Temperatur, bei 5A gibt es spärliche Wärmeverluste.


  • Fehler Nr. 1
    Ich wurde von einem Freund dazu aufgefordert, ehrlich gesagt, ich hätte dies als letzten Ausweg angesehen - DC / DC ist in den Treiber eingebaut, der 15 ... 50 V Eingang empfängt und 3,3 V für die Stromversorgung von MK, Logik, Komparatoren und Operationsverstärkern liefert. Es scheint, dass meine Projekte LM5008- und LM5017-Mikrochips in Form separater Mikrochips haben und ich 60 V ruhig auf 3,3 V reduziert habe, ohne dass eine Erwärmung bei einem Strom von 100-150 mA spürbar war, aber alles stellte sich als schwieriger heraus - der Gesamtwirkungsgrad des Wandlers stellte sich bei einem Strom als etwa 65-70% heraus 300 mA! Tatsache ist, dass der Wandler selbst 3,3 V liefern kann, der Wirkungsgrad jedoch gering ist. Es ist optimal, die Ausgangsspannung auf 10-12-15 V einzustellen. Als der Ausgang 12 V 100 mA betrug, hörte mein Fahrer praktisch auf, sich aufzuwärmen, und der Wirkungsgrad erreichte angenehme 88%. Die Lösung des Problems besteht darin, den Eingang mit dem eingebauten Gleichstrom / Gleichstrom um 15 ... 50 V auf 12 V und dann mit einem bereits billigen externen Gleichstrom / Gleichstrom von 12 V auf 3,3 V zu senken.


  • Fehler Nr. 2
    Der zweite Fehler ist offensichtlicher und das erste, worauf ich sündigte, so gut ich konnte. Tatsache ist, dass bei Chips im QFN-Paket die Hauptwärme durch den "Bauch" abgeführt wird, normalerweise auf dem GND sitzt und durch mehrere Durchkontaktierungen (Via) am Boden haftet und die gesamte Wärme ruhig dorthin fließt. Anfangs habe ich die magere Effizienz des eingebauten Gleichstroms / Gleichstroms mit einer großen Spannungsdifferenz nicht berücksichtigt, so dass es mich nicht störte, dass der thermische Abfall ("Bauch") an einem festen GND-Polygon auf der inneren Schicht haftete, auf der äußeren Schicht hatte ich kein Kupfer unter dem Bauch als Polygon GND Als Ergebnis stellte sich heraus, dass ~ 0,5 W Wärme auf dem Chip freigesetzt werden und sich in der inneren Schicht der Platine ableiten, dh der Wirkungsgrad ist sehr schlecht. Die Lösung des Problems besteht darin, dass Sie auf der äußeren Schicht (untere Schicht) einen Erdtestboden erstellen müssen und dies nicht tun:

Leiterplatte


Infolgedessen wurden bei der zweiten Revision von Eisen diese Fehler korrigiert: Ein externer DC / DC-Wandler 12-3,3 V wurde hinzugefügt und das GND-Polygon wurde zusätzlich auf die untere Schicht gefüllt und das Chip-Pad wurde darauf gepflanzt + das interne feste Grundpolygon wurde erhalten. Nach solchen Verbesserungen sank die Temperatur im Dauerbetrieb von +82 auf +43 ° C:


Thermogramm


Wie Sie sehen können, ist die Temperatur aufgrund der Verringerung der Verluste unter den gleichen Bedingungen erheblich gesunken, und die Wärme wird jetzt gleichmäßiger über den Platinenbereich verteilt und überhitzt den Treiber oder den Mikrocontroller nicht lokal. Im Prinzip war alles Eisen, nichts Interessanteres passierte und funktionierte stabil. Daher empfehlen sie möglicherweise die Verwendung des DRV8353- Treibers.


Implementierung einer Hardware-Phasenverschiebung von 120 o


Ein Merkmal des dreiphasigen Netzwerks ist, dass der Strom in den Phasen nicht synchron ist, sondern um 120 ° gegenüber dem benachbarten verschoben ist. Was ist diese 120 o Phasenverschiebung im Allgemeinen? In einfachen Worten ist dies eine Verschiebung des Startpunkts der Erzeugung um 1/3 der Periode. Aus mathematischer Sicht beträgt die Signalperiode , was bedeutet, dass das zweite Signal um 2π / 3 und das dritte um 4π / 3 verschoben werden muss. Aus elektronischer Sicht wird die Periode durch die Countdown-Periode unseres Timers festgelegt. Wenn wir beispielsweise mit 60 MHz takten, möchten wir eine PWM mit einer Frequenz von 50 kHz erhalten, was bedeutet, dass die Countdown-Zeit des Timers zwischen 0 und 1200 liegt (60 000 000 Hz / 50 000 Hz = 1200). Um nun 3 Phasen mit einer Verschiebung von 120 ° zu erhalten , müssen wir die 1. Phase nicht berühren, +400 zum aktuellen Wert für die 2. Phase hinzufügen und +800 zur aktuellen Phase hinzufügen.


Wenn wir Mikrocontroller auf dem Kortexkern verwenden, können wir die Verschiebung entweder durch Schreiben einer mathematischen Formel oder durch Verwenden der Ereignissynchronisation implementieren. Es war immer wieder erstaunlich für mich, warum ST, NXP und andere nicht nur registrierten, wo der Verschiebungswert geschrieben werden würde. Glücklicherweise hat TI dies in seinem TMS320F28xxx getan, um die Verschiebung einzustellen, schreiben Sie einfach ein Register! Ich werde Ihnen nicht sagen, warum die Softwarelösung nicht optimal ist. Ich möchte nur sagen, dass MK-Formeln nicht sehr schnell berücksichtigt werden. Der Profi mit Synchronisation von Ereignissen ist bereits adäquater und auf stm würde ich genau das tun, aber diese Option erlaubt es nicht, den Phasenwert im laufenden Betrieb zu ändern, dh für einige phasenverschobene Brücken bleibt nur die Softwareversion übrig. Ist der Vorteil der Fähigkeit, die Phasenhardware zu steuern? Es liegt an Ihnen zu entscheiden, meine Aufgabe ist es Ihnen zu sagen, dass es möglich ist. Für mich ist dies ein offensichtliches Plus, wenn wir über die Steuerung eines elektrischen Antriebs oder von Spannungswechselrichtern mit einem dreiphasigen Ausgang sprechen.


Konfigurieren wir nun die Erzeugung von PWM-Signalen in Form von 3 komplementären Paaren mit Totzeit und Phasenverschiebung. Bisher ohne Sinus. Ich werde die folgenden Paare verwenden: EPWM1A + EPWM1B, EPWM2A + EPWM2B und EPWM4A + EPWM4B. Dies sind die Signale, die vom Mikrocontroller zum Treiber gelangen.


  • Schritt 1
    Es ist erforderlich, den GPIO-Multiplexer mithilfe des GPAMUX- Registers für die Arbeit mit PWM zu konfigurieren und die Pull-Ups des Ausgangs zur Stromversorgung auszuschalten, damit beim Einschalten alle Beine kein Protokoll haben und die Schlüssel nicht geöffnet werden. Der aktuelle Schutz wird sicherlich sparen, aber es ist besser, dies nicht zu tun. Beachten Sie auch, dass Sie für den Zugriff auf die Setup-Register diese mit dem Befehl EALLOW abrufen und dann den Überschreibschutz mit dem Befehl EDIS wieder aktivieren müssen .

void InitGPIOforPWM (void) { EALLOW; GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1; // Disable pull-up on GPIO0 (EPWM1A) GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1; // Disable pull-up on GPIO1 (EPWM1B) GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // Configure GPIO1 as EPWM1B GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1; // Disable pull-up on GPIO2 (EPWM2A) GpioCtrlRegs.GPAPUD.bit.GPIO3 = 1; // Disable pull-up on GPIO3 (EPWM2B) GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; // Configure GPIO2 as EPWM2A GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1; // Configure GPIO3 as EPWM2B GpioCtrlRegs.GPAPUD.bit.GPIO6 = 1; // Disable pull-up on GPIO6 (EPWM4A) GpioCtrlRegs.GPAPUD.bit.GPIO7 = 1; // Disable pull-up on GPIO7 (EPWM4B) GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 1; // Configure GPIO6 as EPWM4A GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 1; // Configure GPIO7 as EPWM4B EDIS; } 

  • Schritt 2
    Richten Sie die PWM-Signalerzeugung ein. Es ist notwendig, eine Frequenz von 50 kHz und eine Phasenverschiebung von 120 o zu erhalten . In diesem Fall verwende ich das übliche PWM, da in diesem Controller auch HRPWM vorhanden ist. Dies ist wichtig zu beachten. Das PWM-Modul wird mit der Kernfrequenz getaktet, dh 60 MHz. Ich habe im ersten Artikel auf TMS320 gezeigt, wie die PLL-Frequenz angepasst wird. Ich werde es nicht wiederholen, aber am Ende des Artikels wird es ein Archiv mit dem Code geben und es wird möglich sein, dort nachzuschauen.

  void InitPWM (void) { // EPWM Module 1 config EPwm1Regs.TBPRD = 600; // Set priod EPwm1Regs.TBPHS.half.TBPHS = 0; // Set phase EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Symmetrical mode EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Master enable EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Sync down-stream module EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable dead-time module EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary EPwm1Regs.DBFED = 20; // dead-time on 20 tick EPwm1Regs.DBRED = 20; // dead-time off 20 tick // EPWM Module 2 config EPwm2Regs.TBPRD = 600; EPwm2Regs.TBPHS.half.TBPHS = 400; // Set phase = 400/1200 * 360 = 120 deg EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Slave enable EPwm2Regs.TBCTL.bit.PHSDIR = TB_DOWN; // Count DOWN on sync (=120 deg) EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // sync flow-through EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; EPwm2Regs.DBFED = 20; EPwm2Regs.DBRED = 20; // EPWM Module 4 config EPwm4Regs.TBPRD = 600; EPwm4Regs.TBPHS.half.TBPHS = 400; EPwm4Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; EPwm4Regs.TBCTL.bit.PHSEN = TB_ENABLE; EPwm4Regs.TBCTL.bit.PHSDIR = TB_UP; EPwm4Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm4Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; EPwm4Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm4Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm4Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm4Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm4Regs.AQCTLA.bit.CAU = AQ_SET; EPwm4Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm4Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; EPwm4Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; EPwm4Regs.DBFED = 20; EPwm4Regs.DBRED = 20; } 

Nun ein bisschen mehr Details ... schreiben Sie in das TBPRD- Register den Punkt oder besser "Punkt / 2", weil Wenn der Zeitgeber in beide Richtungen gezählt wird, stellt sich heraus, dass die Periode 600 der Frequenz des Ausgangs-PWM-Signals von 50 kHz im Komplementärpaarmodus entspricht. In das TBPHS- Register schreiben wir den Phasenwert, um den wir uns verschieben müssen, in diesem Fall 400 von 600, was 2π / 3 entspricht. Es ist erwähnenswert, dass wir die 1. Phase nicht verschieben, daher ist die Verschiebung 0, für die 2. Phase ist die Verschiebung 400, aber für die 3. Phase erscheint es logisch, 800, aber irgendwie 800 von 600 zu schreiben nicht wirklich ... deshalb schreiben sie die Verschiebung nicht relativ zur 1. Phase, sondern relativ zur vorherigen, dh zur 2 .. Als Ergebnis erhalten wir, dass wir in der 3. Phase 400 schreiben und dies 2π / 3 zwischen Phase 2 und 3 entspricht. Da die 2. Phase bereits verschoben ist, ergibt sich zwischen Phase 1 und 3 "2π / 3 + 2π / 3 = 4π" / 3 "und aus elektronischer Sicht sieht alles logisch aus.


Damit die Phasen verstehen, wer sich relativ zu wem bewegt, wird ein Boss benötigt. Daher wird EPWM1 ​​mithilfe des PHSEN- Bits in den Master-Modus und EPWM2 bzw. EPWM4 als Slaves gesetzt. Mit den SYNCOSEL- Bits wird auch der Synchronisationspunkt gesetzt, dh wo die Verschiebung abgelesen werden soll. EPWM1 ​​ist mit dem Start des Timers synchronisiert, dh mit der Nullperiode, und EPWM2 und EPWM4 sind bereits relativ zur Signalflanke des vorherigen Kanals synchronisiert: Der vorherige Kanal für EPWM2 ist EPWM1 ​​und für EPWM4 ist es EPWM2.


Jetzt müssen noch komplementäre Paare eingeschaltet und die Totzeitdauer eingestellt werden. Mit den POLSEL- Bits setzen wir eine nicht inverse PWM, dh bei Erreichen des eingestellten Wertes des Komparators (Referenz) wird am Ausgang ein Protokoll generiert. 1. In OUT_MODE setzen wir die Totzeiterzeugung sowohl am Rand als auch beim Abfall des Signals. Dementsprechend schreiben DBFED und DBRED in die Register die Dauer der Totzeit in Ticks.


  • Schritt 3
    Jetzt bleibt es, den Tastverhältniswert in das CMPA- Register zu schreiben, das jedem Kanal entspricht, und Sie können das Ergebnis beobachten.

  EPwm1Regs.CMPA.half.CMPA = 300; // duty for output EPWM1A EPwm2Regs.CMPA.half.CMPA = 300; // duty for output EPWM2A EPwm4Regs.CMPA.half.CMPA = 300; // duty for output EPWM4A 

Dreiphasen-PWM


Voila! Die Oszilloskopsonden sind mit dem Treiberausgang verbunden. Der gelbe Kanal ist unser EPWM1, also der Master. Der blaue Kanal ist EPWM2 und er ist um 2π / 3 (oder 400 Abtastwerte) relativ zum gelben Kanal verschoben, und der grüne Kanal ist um weitere 400 Abtastwerte verschoben. Somit erhalten wir 3 Phasen, wobei jede Phase um 120 ° verschoben ist.


Lassen Sie uns nun die Oszilloskopsonden vom Ausgang der Leistungsbrücke auf die Steuersignale übertragen, die aus dem Mikrocontroller kommen, und die Totzeit innerhalb des komplementären Paares überprüfen:


Oszillogramm Nummer 2


Wie Sie sehen können, entspricht die eingestellte Totzeit der tatsächlichen. Die Dauer einer Probe beträgt 1 / 60.000.000 Hz = 16,6 ns und wir erhalten 20 Proben, was der Totzeit von 20,6 16 ns = 332 ns entspricht *, was ungefähr dem entspricht, was im Oszillogramm beobachtet wird.


Eigentlich, wo dies nützlich sein kann, in der Form, wie es jetzt ist. Die naheliegendste Option sind mehrphasige DC / DC-Wandler für diejenigen, die den verschachtelten DC / DC-Wandler googeln möchten . Dies ist eine äußerst interessante technische Lösung, die die Größe der Leistungsinduktivitäten erheblich reduzieren, die Ausgangskapazität von Kondensatoren verringern und auch den Wirkungsgrad erhöhen kann. Auf einem einfachen TMS320F28027 können Sie einen 4-Phasen-Wandler implementieren, und all dies wird sehr einfach im Code und nur in Hardware implementiert.


Wir erzeugen eine dreiphasige Wechselspannung


Bei vielen Problemen reicht es nicht aus, am Ausgang diskrete Werte von 0 oder VCC zu erhalten, es wird eine Sinuswelle benötigt. Ich habe einen Artikel , der über die Bildung einer einphasigen Wechselspannung spricht, und dort wird die "tabellarische" Methode verwendet, dh die Werte für die Sinuswelle wurden ursprünglich berechnet. Grundsätzlich kann dies auch dreiphasig erfolgen, ich möchte jedoch eine alternative Option aufzeigen, nämlich die Berechnung des Zollwerts in Echtzeit oder im laufenden Betrieb.


Es gibt eine Funktion. Die PWM-Frequenz beträgt in diesem Fall ebenfalls 50 kHz und die Phasenverschiebung wird zwischen den Perioden dieses Signals eingestellt. Wenn wir also eine Sinuskurve mit einer Frequenz von 50 Hz modulieren, geht die Hardware-Phasenverschiebung "verloren", sie bleibt zwischen den PWMs bestehen, jedoch nicht innerhalb der Sinuskurve, sodass Software durchgeführt werden muss. Trigonometrie ist eine schwere Sache für TMS320F28027, aber sie ist nicht sehr beschäftigt mit mir. Lassen Sie es also zählen. Wenn Sie eine Aufgabe haben, die viele Berechnungen erfordert, benötigen Sie einen Controller mit TMU und FPU, z. B. TMS320F280049, der die Mathematik viel schneller umdrehen kann.


Um die Tastwerte in die PWM zu laden, benötigen wir einen Timer, dessen Periode die Abtastfrequenz einstellt. Ich benötige eine Periode von 20 ms (1/50 Hz = 20 ms) und nehme die Anzahl der Schritte in einer Sinuskurve, sagen wir 20, als Ergebnis sollte ein Interrupt mit einer Frequenz von 0,02 s / 20 = 0,001 ms = 1 kHz erzeugt werden. In diesem Interrupt schreibe ich den Wert in die PWM . Der Einfachheit halber nehme ich einen normalen CPU0- Timer und konfiguriere ihn:


 void InitTimer0ForGenerator (void) { EALLOW; PieVectTable.TINT0 = &cpu_timer0_isr; EDIS; InitCpuTimers(); ConfigCpuTimer(&CpuTimer0, 60, 1000); CpuTimer0Regs.TCR.bit.TIE = 1; CpuTimer0Regs.TCR.bit.TSS = 0; IER |= M_INT1; PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // Enable TINT0 in the PIE: Group 1 interrupt 7 EINT; // Enable Global interrupt INTM ERTM; // Enable Global real-time interrupt DBGM } __interrupt void cpu_timer0_isr (void) { CpuTimer0.InterruptCount++; /* *   -  . ... */ PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge this interrupt to receive more interrupts from group 1 } 

Die Funktionen InitCpuTimers und ConfigCpuTimer sind Standard, alle Einstellungen sind in ihnen enthalten. Wir müssen nur die Kernfrequenz (60 MHz) und die Zählperiode in Mikrosekunden (1000 μs = 1 ms) übertragen, was 1 kHz entspricht, und wir brauchten sie. Wo also in der Konfigurationsfunktion Interrupts aktiviert werden und die Adresse des Handlers unseres Interrupts übergeben wird, wo alles passieren wird.


Jetzt ist es notwendig, die Sinusformel erneut zu „erfinden“. Dazu benötigen Sie Kenntnisse der Schultrigonometrie und das ist alles. Und so ... haben wir eine Funktion y = sin (x) zeichnen wir diese Funktion:


y = sin (x)


Wie Sie in der Grafik sehen können, variiert die Amplitude von y von -1 bis 1, aber wir wollen von 0 bis 1, weil Mit einer minimalen Amplitude haben wir 0 V und mit einem Maximum (entspricht 1) haben wir + VCC. Um -1 ... + 1 zu "zeichnen", brauchen wir eine bipolare Ernährung, aber das ist es nicht. Sie müssen das Diagramm in eine positive Richtung verschieben. Wenn wir es nur anheben, wird es von 0 auf +2 und wir können nur auf +1. Sie müssen also durch 2 und nur etwas teilen! Beginnen wir mit dem Teilen und Zeichnen für y = (sin (x) / 2):


y = (sin (x) / 2)


Ja! Jetzt hat der Graph einen Bereich von -0,5 bis +0,5, das heißt, die Amplitude ist 1. Es ist bereits besser, aber wir haben die negativen Werte noch nicht beseitigt. Verschieben wir den Graph also einfach um 0,5 nach oben. Dazu müssen wir nur diesen Wert zum Ergebnis hinzufügen und die Formel erhalten y = 0,5 + (sin (x) / 2) und zeichnen Sie den Graphen für diese Funktion:


y = 0,5 + (sin (x) / 2)


Jetzt ist alles absolut perfekt geworden: Die Sinuskurve hat eine Amplitude von 0 bis 1, negative Werte fehlen. Die Formel y = 0,5 + (sin (x) / 2) beschreibt die 1. Phase. Nun ist es notwendig, eine Phasenverschiebung hinzuzufügen, um die Phasen 2 und 3 zu erhalten. Dazu subtrahieren Sie 2π / 3 bzw. 4π / 3 von x und erhalten die Formeln für die verbleibenden Phasen y = 0,5 + (sin (x-2π / 3) / 2) und y = 0,5 + (sin (x-4π / 3) / 2). Wir erstellen 3 Diagramme und sehen, ob es wie die Wahrheit aussieht:


3 Phasen


Nicht schlecht! Das Bild ähnelt dem, was normalerweise in Lehrbüchern der Elektrotechnik gemalt wird, wenn es sich um ein Dreiphasennetz oder Asynchronmotoren handelt. Übrigens ist 2.0943 2π / 3 und 4.1866 4π / 3, ich habe sie sofort gezählt und sie erscheinen in meinem Code. Insgesamt haben wir 3 Gleichungen:


  • Phase A - y = 0,5 + (sin (x) / 2)
  • Phase B - y = 0,5 + (sin (x-2π / 3) / 2)
  • Phase C - y = 0,5 + (sin (x-4π / 3) / 2)

Seitens der Mathematik scheint alles einfach und klar zu sein, aber jetzt muss es an die Realität der Mikrocontroller angepasst werden. Unsere Sinuswelle ist nicht analog, sondern hat "Schritte", das heißt, sie ist diskret, da wir in meinem Fall nur Spannung oder 0 V oder + 15 V (VCC) einstellen können. Früher habe ich geschrieben, dass ich 20 Schritte haben werde, also werde ich für 1 Periode 20 Berechnungen haben.


Lassen Sie uns zunächst entscheiden, was x ersetzt werden soll . Die Periode unserer Sinuskurve beträgt , was bedeutet, dass der Abtastschritt 2π / 20 beträgt. Dementsprechend besteht die Sinuskurve aus 20 Punkten, als ob wir ein Diagramm auf den Punkten erstellen und zwischen ihnen annähern. Infolgedessen ist der Wert im ersten Schritt sin (2π * (1/20), im zweiten Schritt sin (2π * (2/20)), im dritten Schritt * sin (2π (3/20)) und so weiter, wenn wir Wenn es 20/20 erreicht, bedeutet dies das Ende des Zeitraums und es muss erneut mit dem Zählen begonnen werden. Korrigieren wir anhand der empfangenen Daten die Formeln:


  • Phase A - y = 0,5 + (sin (2π * (n / N)) / 2)
  • Phase B - y = 0,5 + (sin (2π * (n / N) -2π / 3) / 2)
  • Phase C - y = 0,5 + (sin (2π * (n / N) -4π / 3) / 2)

Nun betrachten wir den Sinuswert an jedem bestimmten Punkt in der Grafik. Dementsprechend ist n der aktuelle Schritt, N ist der Gesamtschritt (20). Nach diesen Formeln erhalten wir einen Wert von 0 bis 1, aber in Wirklichkeit arbeiten wir nicht mit einer abstrakten Amplitude. Die Amplitude hängt in unserem Fall vom Arbeitszyklus ab, weil Die Einschaltdauer ändert sich von 0 auf 600 (aus den PWM-Einstellungen), dann ist 0 0 und 1 entspricht 600. Auf dieser Grundlage berechnen wir sie neu in eine reelle Formel, um den Wert zu erhalten, der in das CMPA- PWM-Register geladen wird:


  • Phase A - Pflicht1 = A (0,5 + (sin (2π (n / N)) / 2))
  • Phase B - Pflicht2 = A (0,5 + (sin (2π (n / N) -2π / 3) / 2))
  • Phase C - Duty4 = A (0,5 + (sin (2π (n / N) -4π / 3) / 2))

Dementsprechend ist A der Maximalwert der Amplitude, d. H. 600, n ist der aktuelle Schritt, N ist die Gesamtzahl der Schritte (20). Die Werte von Duty1, Duty2, Duty4 sind die umgerechneten realen Werte des Duty Factors, der in den CMPA geladen wird. Schreiben wir nun den Code für den aktualisierten Interrupt-Handler und deklarieren alle erforderlichen Variablen:


 float activeStep = 0.0; float amplitude = 600.0; float allStep = 20.0; const float pi = 3.1415; // π const float piTwo = 6.2831; // 2π const float phaseShifted120deg = 2.0943; // 2π/3 const float phaseShifted240deg = 4.1866; // 4π/3 __interrupt void cpu_timer0_isr (void) { if (activeStep >= allStep) {activeStep = 0;} activeStep++; EPwm1Regs.CMPA.half.CMPA = ((uint16_t)(amplitude * (0.5 + (sinf(piTwo * (activeStep / allStep)) / 2)))); EPwm2Regs.CMPA.half.CMPA = ((uint16_t)(amplitude * (0.5 + (sinf(piTwo * (activeStep / allStep) - phaseShifted120deg) / 2)))); EPwm4Regs.CMPA.half.CMPA = ((uint16_t)(amplitude * (0.5 + (sinf(piTwo * (activeStep / allStep) - phaseShifted240deg) / 2)))); PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge this interrupt to receive more interrupts from group 1 } 

Der Code ist, wie Sie sehen, der einfachste, wenn Sie verstehen, was zu tun war, und einfache Mathematik für das zu lösende Problem. Jedes Mal, wenn der Interrupt aufgerufen wird, erhöhen wir die Variable activeStep , die die Schrittnummer enthält. Sie ändert sich von 0 auf 20 und wird dann zurückgesetzt. Es stellt sich heraus, dass wir in einer Periode 20 Schritte und 20 Berechnungen für jede Phase durchführen. Um nicht ständig 2π / 3 und 4π / 3 in der Formel zu zählen, habe ich sie sofort gezählt, um sie als Konstanten zu verwenden.


Berechnungen haben sich als Minimum herausgestellt, für diesen MK ist es absolut nichts. Auf Wunsch kann die Anzahl der Punkte deutlich erhöht werden, beispielsweise auf bis zu 200. Alles hängt von der Aufgabe ab. Das Ändern der PWM-Frequenz erfolgt durch Ändern der Interrupt-Anruffrequenz und der Anzahl der Schritte. Sie können auch die variable Amplitude und die Spannung am Ausgang des Stromrichters ändern.


Nach dem Herunterladen des Codes auf den Mikrocontroller erhalten Sie das entsprechende Bild:


Oszillogramm Nummer 1


Wenn Sie den Graphen entlang Y strecken, ist es besser, die Fehler des Signals zu sehen. Dies ist eine Folge der geringen Anzahl von Abtastschritten, es gilt eine bedingte Regel: Je mehr Punkte, desto schöner das Signal.


Oszillogramm Nummer 3


Fazit


Heute habe ich über den Prozess der Phasenverschiebungsbildung in Mehrphasensystemen gesprochen, im Prinzip gibt es nichts Kompliziertes, insbesondere bei Verwendung von TMS320F28. Der Rest hängt von den Algorithmen ab. Im Prinzip gibt es auf den riesigen Flächen von Runet viele Artikel, in denen Steuerungs- und bürstenlose Motoren, asynchrone und alle möglichen anderen Dinge gekaut werden. Sie müssen nur die Logik ändern.


Ich hoffe, dass dieses Material nützlich und nicht besonders langweilig zu lesen ist. Wie immer ist die Quelle beigefügt:


Archivieren Sie mit dem Projekt für Code Composer Studio

Source: https://habr.com/ru/post/de457548/


All Articles