Wechselstromquelle (Teil 10)

Elektronik AC PWM MOSFETs

Letztes Mal haben wir einen H-Brücken-Wechselrichter aus Transistoren gebaut. Um die Effizienz zu erhöhen, werden wir nun MOSFETs nutzen.

Verbesserung der Effizienz durch MOSFETs

Beim letzten Mal haben wir eine H-Brücken-Wechselrichterschaltung mit Transistoren gebaut. Diese Lösung erwies sich, als einfacher zu bauen, als die vorherigen Lösungen, die komplexe Verstärkerschaltungen erforderten. H-Brücken-Wechselrichter können sehr effizient sein, aber unsere Lösung war es definitiv nicht. Ein Hauptproblem war der hohe Strom, der durch die Basis der Transistoren floss, und deren hohe Verlustleistung. Beide Probleme können gelöst werden, indem die Transistoren durch MOSFETs ersetzt werden, und genau das werden wir heute tun.

MOSFETs und andere Feldeffekttransistoren (FETs) sind spannungsgesteuert, während die klassischen bipolaren Sperrschichttransistoren (BJTs) stromgesteuert sind. Für FETs wird aufgrund ihrer anderen Funktionsweise ein anderes Namensschema verwendet. Im Prinzip entspricht jedoch das Gate (G) in etwa der Basis (B) des Transistors. Der Kollektor (C) entspricht dem Drain (D) eines FETs, und der Emitter (E) der Source (S). Ähnlich wie bei normalen Transistoren gibt es n- und p-Kanal-MOSFETs. Bei MOSFETs fließt jedoch kein Strom durch das Gate, wie es bei der Basis eines Transistors der Fall ist. Ferner haben MOSFETs in der Regel einen viel geringeren Innenwiderstand und damit eine geringere Verlustleistung als Transistoren. Dies ist besonders vorteilhaft, wenn MOSFETs als Schalter verwendet werden. Beide Eigenschaften helfen uns, die Effizienz unserer Schaltung zu steigern.

Warum werden angesichts all dieser Vorteile nicht einfach MOSFETs verwendet? Nun, MOSFETs sind nicht nur schwieriger zu bauen und daher teurer, sie haben auch einige Nachteile. Der erste ist, dass sie bei Verpolung leiten. Ein n-Kanal-MOSFET verhält sich wie eine Diode, wenn man eine positive Spannung an seinen Source-Pin anlegt. In Schaltplänen wird dies oft durch das Einzeichnen einer zusätzlichen Diode über dem MOSFET veranschaulicht. Je nach Anwendung ist dieses Verhalten ein Problem oder nicht. Für unsere Schaltung ist es keines. Wichtiger ist für uns die Tatsache, dass viele MOSFETs eine relativ hohe Schwellspannung benötigen, um komplett durchzuschalten. Nicht alle MOSFETs können direkt mit den 5 V des Arduino Uno betrieben werden. Das wichtigste Problem für uns ist jedoch, dass das Gate von MOSFETs, besonders wenn sie groß sind, eine große Kapazität hat. Das bedeutet, dass man entweder langsame Schaltgeschwindigkeiten akzeptieren muss, was wir nicht können, da wir PWM verwenden, oder das Gate mit einem hohen Strom laden und entladen muss. Für letzteres benötigt man normalerweise einen MOSFET-Treiber. In unserem Fall werden wir jedoch ein fertiges MOSFET-H-Brückenmodul mit dem BTN7960 verwenden.

Aufbau der Schaltung

Zuerst bauen wir die Schaltung auf. Durch die Verwendung des vorgefertigten Moduls ist diese weniger komplex als die vorherigen. Sie besteht nur aus dem Arduino, der MOSFET H-Brücke und einem LC-Filter mit einem 51 Ω Lastwiderstand.

Das MOSFET-Modul ist eigentlich als Motortreiber konzipiert und verwendet zwei BTN7960 MOSFET-Halbbrücken. Das Modul enthält alles, was man für die Ansteuerung von Motoren benötigt. Zusätzlich verfügt es über einen Übertemperatur-, Überspannungs-, Unterspannungs- und Kurzschlussschutz. Es besitzt zudem einen internen Totzeitgenerator, weshalb wir dies nicht mehr im Arduinoprogramm implementieren müssen.

Allerdings hat das Modul auch seine Grenzen. Da es als Motortreiber gedacht ist, benötigt es keine besonders schnellen Schaltgeschwindigkeiten. Das Maximum liegt bei 25 kHz. Das bedeutet, dass wir die Frequenz unseres PWM-Signals verringern müssen. Hinzu kommt, dass das Modul mehr als die üblichen 5 V Versorgungsspannung des Arduino benötigt. Die ideale Versorgungsspannung liegt zwischen 8 V und 18 V. Das Modul beginnt bei 5,5 V zu arbeiten, 5 V allerdings sind nicht ausreichend. Bei 5 V löst der Unterspannungsschutz bei Lastspitzen aus und schaltet die MOSFETs ab. Es ist nicht möglich, eine stabile Sinusschwingung zu erzeugen. Um das Modul zu verwenden, benötigen wir also eine externe Stromversorgung. Zu diesem Zweck kannst du ein Labornetzteil oder eine 9 V-Batterie nutzen. Glücklicherweise verfügt das Modul über einen integrierten Logik-Pegel-Wandler, sodass wir die 5 V des Arduino für die Steuersignale nutzen können.

Um das Modul an den Arduino Uno anzuschließen, verbinde die PWM-Pins 9 und 10 mit RPWM und LPWM. Darüber hinaus müssen wir die MOSFETs einschalten. Dazu verwenden wir die Pins 6 und 7 und verbinden diese mit R_EN und L_EN. Um das Modul mit Strom zu versorgen, müssen die 5V des Arduino mit dem VCC-Pin des Logik-Pegel-Wandlers verbunden werden. Der VIN-Pin mit der größeren Spannung muss mit der Schraubklemme B+ verbunden werden und wird zur Stromversorgung der MOSFETs verwendet. Das Ausgangssignal, das mit dem LC-Filter und der Last verbunden werden muss, liegt an den Schraubklemmenanschlüssen M+ und M- an.

Der Code

Werfen wir einen Blick auf den Code. Im Prinzip ist es derselbe wie für die Transistor-H-Brücke, mit der Ausnahme, dass wir keine Totzeitgenerierung mehr brauchen. Es gibt allerdings zwei neue Teile, die einer Erklärung bedürfen. Aber jetzt erst einmal der ganze Code im Überblick:

#include <EEPROM.h>

// PWM frequency is 7.8 kHz so we can update roughly every 256 us in phase correct mode
const int usPerCommand = 300;

// Precalculated Voltage Buffer
const int BUFFER_SIZE = 256;
unsigned int voltages[BUFFER_SIZE];
unsigned int steps;
unsigned int usPerStep;

unsigned int current_step = 0;
unsigned long start_time;

// Setup frequency
void setup() {
  // Read desired frequency
  Serial.begin(9600);
  Serial.print("Enter Frequency (Hz): ");

  // Wait 10s for input otherwise take stored value
  Serial.setTimeout(10000);
  float frequency = Serial.parseFloat();
  if(frequency == 0) EEPROM.get(0, frequency);
  else EEPROM.put(0, frequency);

  Serial.println(frequency);

  // Calculate number of possible steps
  int possible_steps = 1000000/usPerCommand/frequency;

  // Steps need to be a multiple of 4 to keep the sine form
  steps = (possible_steps  / 4) * 4;
  if(steps > BUFFER_SIZE) steps = BUFFER_SIZE;
  if(steps < 4) steps = 4;

  // Time per Step
  usPerStep = 1000000 / (frequency * steps);
  if(usPerStep < usPerCommand) usPerStep = usPerCommand;

  // Precalculate Sine Values 0-5 V
  for(int i = 0; i < steps; i++) {
    int value = sin(i*3.14*2/steps) * 255 + 255;
    voltages[i] = constrain(value, 0, 1022);
  }

  Serial.print("Number of output steps: ");
  Serial.println(steps);

  Serial.print("Microseconds per step: ");
  Serial.println(usPerStep);

  Serial.print("Archieved Frequency (Hz): ");
  Serial.println(1000000.0/float(steps)/float(usPerStep));

  // Enable a prescaler of 1 for timer 1 but count to 1023
  // choose phase correct mode and invert output 10
  TCCR1A = (1<<WGM11)|(1 << COM1A1)|(1 << COM1B1)|(1 << COM1B0);
  TCCR1B = (1<<CS10);
  TIMSK1 |= (1<<TOIE1);

  // Enable PWM pins
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  
  // Enable MOSFETs
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  digitalWrite(6, HIGH);
  digitalWrite(7, HIGH);

  // Initially set start time
  start_time = micros();
}

ISR(TIMER1_OVF_vect) {
  OCR1A = voltages[current_step];
  OCR1B = voltages[current_step];
}

// Output values
void loop() {
  current_step++;
  if(current_step >= steps) current_step = 0;

  while(micros()-start_time < usPerStep);
  start_time += usPerStep;
}

Was ist neu? Nun, die erste offensichtliche Änderung ist, dass wir jetzt die Pins 6 und 7 als Ausgänge konfigurieren und sie auf HIGH setzen, um die MOSFETs zu aktivieren. Das ist weder speziell noch erklärungsbedürftig. Der schwierigere Teil ist der für die Erzeugung des PWM-Signals. Hier gibt es einige Änderungen, um die Frequenz des PWM-Signals an die Limits des MOSFET-Moduls anzupassen.

Statt der ursprünglichen 31,25 kHz verwenden wir nun eine Frequenz von 7,8 kHz. Dies ist eine Reduktion um den Faktor vier und kann erreicht werden, indem man den Zähler, der das PWM-Signal erzeugt, von 0 bis 1023 statt von 0 bis 255 zählen lässt. Zu diesem Zweck habe ich den Timer mit den folgenden Codezeilen umkonfiguriert:


// Enable a prescaler of 1 for timer 1 but count to 1023
// choose phase correct mode and invert output 10
TCCR1A = (1<<WGM11)|(1 << COM1A1)|(1 << COM1B1)|(1 << COM1B0);
TCCR1B = (1<<CS10);
TIMSK1 |= (1<<TOIE1);

Ein Nachteil dieser Lösung ist, dass wir nicht länger die vordefinierte analogWrite Funktion benutzen können. Aus diesem Grund müssen wir nun die PWM-Pins 9 und 10 manuell als Ausgang konfigurieren und manuell den Zielwert im Timerinterrupt setzen, so wie es unten gezeigt wird.

ISR(TIMER1_OVF_vect) {
  OCR1A = voltages[current_step];
  OCR1B = voltages[current_step];
}

Das Ergebnis

Wie sieht unser Ergebnis aus? Die Sinuskurve wird durch das MOSFET-Modul leicht verzerrt. Dies lässt aber sich durch eine Verringerung der Amplitude beheben, da die Verzerrung nur in der Nähe des Maximal- und Minimalwerts auftritt. In diesem Tutorials geht es jedoch primär um die Ausgangsleistung und den Wirkungsgrad und weniger um die Erzeugung einer perfekten Sinuskurve, weshalb ich hier nicht weiter auf dieses Problem eingehen werde. Die Ausgangsleistung beträgt bei einer Effektivspannung von ca. 5,5 V:

\(P_{out} = {U^2 \over R} = {{5,5 V}^2 \over 51 Ω} \approx 0,6 W\)

Ist dies die maximale Ausgangsleistung? Nein, sicherlich nicht. Der limitierende Faktor ist in diesem Fall der hohe Widerstand der Spule. Bei höheren Strömen würde sie überhitzen und kaputt gehen. Mit einer geeigneten Spule für höhere Ströme kann eine erheblich höhere Ausgangsleistung erzielt werden.

Die erzeugte Sinuswelle wird leicht verzerrt

Wie sieht es mit dem Wirkungsgrad aus? Um den Wirkungsgrad zu messen, habe ich den Gesamtstromverbrauch gemessen. Dazu habe ich einen kleinen 0,56 Ω Widerstand und einen 1 uF Kondensator zum Glätten des Signals parallel geschaltet. Die beiden habe ich in Reihe zum Arduino geschaltet und den Spannungsabfall mit dem Oszilloskop gemessen. Wie du im Bild unten sehen kannst, betrug er im Durchschnitt 68 mV, was einem Eingangsstrom von etwa 120 mA entspricht.

\(I = {U \over R} = {68 mV \over 0,56 Ω} \approx 120 mA\)

Strommessung mit dem Oszilloskop und einem 0,56 Ω Widerstand

Dies entspricht einer Eingangsleistung von 1,08 W für den Arduino und unsere eigentliche Schaltung.

\(P_{in} = U \cdot I = 9 V \cdot 120 mA = 1,08 W\)

Der Gesamtwirkungsgrad liegt also bei etwa 56 %, was besser ist als das, was wir mit all unseren vorherigen Lösungen erreicht haben. Ein respektables Ergebnis, wenn man bedenkt, dass wir einen Motortreiber als Wechselrichter missbrauchen und durch den hohen Widerstand der Spule eine Menge Energie verlieren. In den vorherigen Effizienzangaben zu den Schaltungen mit Verstärker wurde zudem der Stromverbrauch des Arduino's anders als hier nicht mit eingerechnet.

\(\eta = {P_{out} \over P_{in}} = {0.6 W \over 1.08 W} \approx 56 \%\)

Vorheriger Beitrag Nächster Beitrag