Letztes Mal haben wir einen H-Brücken-Wechselrichter aus Transistoren gebaut. Um die Effizienz zu erhöhen, werden wir nun MOSFETs nutzen.
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.
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.
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];
}
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.
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\)
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 \%\)