Was ist ein guter Satz von PWM-Werten, um Sinuswellen für einen 3-Phasen-Motor zu erzeugen?

Ich baue eine synchron rotierende Funkenstrecke für eine Tesla-Spule. Ich habe eine funktionierende MCU (Kinetis K64F), die eine 230-Volt-Wechselrichterplatine antreibt und einen 3-Phasen-Synchronmotor dreht. Der Motor ist selbst ein Synchronmotor, und die Leistung, die ich ihm gebe, muss auch sein: synchronisiert mit der Wechselstromleitung. Deshalb habe ich mich entschieden, meine eigene Hardware zu bauen. Ich kann die Leistung meines laufenden Antriebs mit einem kommerziellen vergleichen und sehe, dass meiner den Motor unterfordert.

Der im Laden gekaufte 3-Phasen-Wechselrichter bringt den Motor auf Hochtouren, in eine Synchronisierung, die sich langsam auf eine Seite verschiebt, ohne dass eine Möglichkeit besteht, ihn zu steuern. Während mein Laufwerk mehr als eine Minute mit wackelndem Geräusch braucht, um auf Geschwindigkeit zu kommen, und dann mit der Zeilenfrequenz absolut stabil ist. Ich kann es auf beiden Seiten um jeweils ein Grad verschieben. Das ist was ich brauche.

Ich denke also, es müssen die Daten sein, die ich an die 6 PWM-Kanäle sende. Meine naive Lösung dafür war, beim Start ein Array mit Sinuswerten zu füllen. Ich mache 2 positive Halbzyklen wie folgt:

int Winkel; doppelter Parameter; externes Doppelhalten[370];

 for (angle=0; angle<=179; angle++) {
   param  = 255 * sin (angle*PI/180);
   hold[angle] = param;      // fill first half of the array
   hold[angle+180] = param;  // fill second half with duplicate data
 }

Dann lese ich in einem periodischen Interrupt dieses Array von Sinuswerten wie folgt aus:

    if (angle1 < 180) { PWM1_SetRatio8(hold[angle1]); }
    else if (angle1 == 180) { PWM1_SetRatio8(0); }
    else if (angle1 > 180) { PWM2_SetRatio8(hold[angle1]); }
    if (angle1 >= 360) { angle1 = 0; PWM2_SetRatio8(0); }

    if (angle2 < 180) { PWM3_SetRatio8(hold[angle2]); }
    else if (angle2 == 180) { PWM3_SetRatio8(0); }
    else if (angle2 > 180) { PWM4_SetRatio8(hold[angle2]); }
    if (angle2 >= 360) { angle2 = 0; PWM4_SetRatio8(0); }

und so weiter für angle3, die alle 120 Grad voneinander entfernt sind. Ich sehe jetzt, dass 180 pro Halbzyklus zu viel sind, also habe ich es auf nur 20 heruntergeteilt, aber ohne Änderung der Motorleistung.

Ich sperre mein internes Array mit 360 Werten mit einem präzisen Nulldurchgangsimpuls von außen, um sie synchron zu halten.

Also habe ich mich über Magic Sine Waves informiert und das klingt gut. Aber ich müsste eine Menge Code umschreiben, um es zu verwenden, und ich muss Geschwindigkeiten von 58 bis 62 Hz abdecken, was die Energieunternehmen mir bieten. Wenn ich ein Array von Magic Sine-Werten füllen würde, würde ich eine Übergangsverzerrung bekommen, wenn ich auf die verschiedenen Zeilenfrequenzen umschalte.

Dann las ich über Dreieckswellen, die die Sinuswerte modulieren und eine zusätzliche dritte Harmonische hinzufügen, um mehr Leistung zu erhalten. Das klingt nach dem Weg nach vorn. Ich kann zur Laufzeit eine Reihe vorberechneter Werte einlesen und loslegen. Hat jemand Erfahrung mit dem Aufbau eines solchen Datensatzes? Oder kann mir ein paar Tipps geben, wie man das macht?

Wenn Ihre MCU schnell genug ist, können Sie einen zweiten Timer verwenden, um die Periode des ersten zu optimieren, um an einem einzigen Tisch zu bleiben.
Ist die PWM schnell genug, um eine Tischgenauigkeit von 1 Grad zu benötigen? Es ist sinnlos, den Ausgangswert öfter als einmal pro Impuls zu aktualisieren. Ich würde erwarten, dass Sie mit etwa 12 Werten auskommen und den Motor immer noch auf einer Rechteckwelle in jedem Kanal drehen können.
Ja, die CPU hat 120 Mhz, also habe ich viel Geschwindigkeit zur Verfügung. Wenn ich eine magische Sinustabelle für 60 Hz erstelle, kann ich kleine Anpassungen an den Werten "hinter den Kulissen" vornehmen, sodass meine Ausgaberoutine immer nur die frischesten Zahlen ohne Berechnung ausgibt.

Antworten (2)

Ich weiß nicht, ob das überhaupt hilft, aber ich habe ein wenig an diesem Problem gearbeitet. Harmonic Elimination PWM Es klingt genauso wie magische Sinuswellen. Wenn ich nur aus dem Kopf denke, würde ich eine kombinierte Einzeltabelle der Schaltzeiten für alle 3 Phasen der Wellenform vorberechnen und einen einzigen Interrupt verwenden. Wenn die Interrupts auftreten, schalten Sie den jeweiligen Kanal um und ändern Sie dann die Zeit bis zum nächsten Interrupt. Um die Frequenz zu ändern, skalieren Sie die Daten aus der Tabelle. Dies sollte keine Probleme mit Verzerrungen über den von Ihnen angegebenen Frequenzbereich verursachen. Es sollte auch ziemlich genau sein, wenn Sie eine 120-MHz-CPU haben. Ich hatte eine Basisversion davon, die an einem Ultraschallwandler bei 40 kHz an einem 4-MHz-AVR arbeitete.

Vielen Dank dafür. Ich habe Blender verwendet, um eine genaue Zeichnung zu erstellen, und mich für die Dreieckswellenmodulation entschieden. Ich stelle die Länge eines halben Sinuswellenzyklus in Blendereinheiten auf die gleiche Anzahl von Mikrosekunden ein, die ich benötige. So kann ich die Pulsweiten direkt von der Zeichnung in usec ablesen. Ich weiß, es ist nicht die beste Lösung, aber ich muss diese Hürde überwinden, damit ich mich um all die anderen Probleme kümmern kann!

Ich habe Grants Lösung ausprobiert und der Motor war noch schwächer! Also ging ich zurück zu meinen naiven Sinuswerten und nahm diese kleine Änderung vor:

 for (angle=0; angle<=179; angle++) {
   param  = 265 * sin (angle*PI/180);
   if (param > 255) param = 255;
   hold[angle] = param;
   hold[angle+180] = param;
 }

Wie Sie sehen können, habe ich den Sinuswert mit 265 statt mit 255 multipliziert und die Werte beim Überlauf wieder auf 255 reduziert. Dadurch wird die Sinuswelle verstärkt und begrenzt. Bei Anschluss an den Motor drehen diese Werte ihn in etwa 3 oder 4 Sekunden synchron. Mein Messgerät misst unheimliche 120,0 Volt zwischen jeder der 3 Phasen.

Ich denke immer noch, dass dies eine naive Lösung ist, aber es wird vorerst reichen!