Der vom Generator erzeugte Wechselstrom (3 Phasen) wird zunächst über den Brücken-Gleichrichter in Gleichstrom umgewandelt, der alle weiteren Komponenten versorgt und schließlich zur Batterieladung verwendet wird.
Das zentrale Element der Schaltung ist der große Step-Down-Converter in der Mitte links. Er transformiert die variable Generatorspannung auf die Ladeschlussspannung der Batterie und lässt somit den Generator möglichst effizient mit hoher Spannung und geringer Stromstärke laufen.
Am Spannungswandler befinden sich zwei Potentiometer. Mit dem einen lässt sich eine feste Ausgangsspannung einstellen (Ladeschlussspannung), mit dem anderen ein konstanter Widerstand, der den Stromfluss und damit die Belastung des Generators bzw. die Ladeleistung bestimmt. Da der Generator jedoch sehr unterschiedliche Leistungen liefert, muss die Belastung permanent angepasst werden, weshalb das ursprüngliche Potentiometer durch ein ansteuerbares, digitales Potentiometer ersetzt wird. Über den Microcontroller (Arduino Uno) lassen sich somit beliebige Widerstandswerte einstellen, durch die alle Formen der Leistungssteuerung ermöglicht werden.
Um die jeweils passende Generatorbelastung zu bestimmen, müssen die aktuelle Spannung und im Falle von MPPT auch der Stromfluss gemessen werden. Nachdem die Batteriespannung den Messbereich des Microcontrollers übersteigt (0-5V) , kommt ein Spannungsteiler zum Einsatz, der die aktuelle Ladespannung verkleinert und über den analogen Eingang des Arduino A0 messbar wird. Der Stromsensor misst den Stromfluss zur Batterie, wird über die Spannung des Arduinos versorgt und liefert Messwerte über den analogen Eingang A1.
Der Microcontroller selbst wird direkt vom Generator mit Strom versorgt. Da seine Versorgungsspannung nur bei 5V liegt, wird ein kleiner Step-Down-Wandler dazwischengeschaltet, der die schwankende Generatorspannung herunter transformiert und stabil hält. Der Regler wird also nur dann gestartet, wenn auch tatsächlich Strom vom Windrad produziert wird.
Sobald der Generator eine Spannung über 5V erzeugt, schaltet sich der Microcontroller ein, setzt den digitalen Widerstand auf den Startwert und ist sofort startklar. Sobald die Generatorspannung über der Batteriespannung liegt, wird das Relais 2 geschlossen und die Ladung beginnt. Sobald die Spannung unter die Akkuspannung sinkt, wird der Stromkreis zur Batterie wieder getrennt. Bei weiterer Spannungssenkung unter die Arduino Betriebsspannung schaltet der Regler komplett aus. Eine Entladung der Batterie ist somit ausgeschlossen, was bei vielen Ladereglern nicht der Fall ist. Bei (tage-) langen Windpausen können dadurch relativ große Stand-By-Verluste vermieden werden.
Arduino Programm-Code
Neben den Variablen-Deklarationen und Funktionen (siehe unten im kompletten Quell-Code) findet der eigentliche Algorithmus innerhalb der sich permanent wiederholenden Loop-Schleife statt. Bei jedem Durchlauf werden die Werte für die Spannung und die Stromstärke über die entsprechenden Funktionen als globale Variablen eingelesen. Sobald die Generatorspannung einen Mindestwert (start_voltage) übersteigt, wird das Relais zur Batterie (PIN9) freigeschaltet.
Nachdem die Messwerte des Stromsensors relativ große Schwankungen aufweisen, werden immer 100 Messwerte in einem Array (array_current) gespeichert und daraus der Mittelwert gebildet. Die aktuelle Leistung wird aus der eingelesenen Spannung (voltage) mal der gemittelten Stromstärke (current) bestimmt. Der Wert 'diff_power' gibt die Leistungsdifferenz zur vorherigen relevanten Leistungsmessung wieder, die in der Variablen 'last_power' bei der letzten Beslastungsänderung (Funktion Up() oder Down()) gespeichert wurde.
Sobald die aktuelle Leistung (power) eine bestimmte Differenz (step) zur zuletzt gespeicherten Leistung (last_power) überschreitet, wird, je nach Richtung, das Potentiometer stärker belastet bzw. entlastet und ein neuer "last_power"-Wert gespeichert. Bei langsamen Beschleunigungen, sollte allein diese Abfrage genügen, um das Windrad in seinem optimalen Arbeitspunkt zu halten.
Um jedoch sicherzugehen, dass gerade bei schnellen Drehzahlwechseln keine notwendigen Potentiometeranpassungen übersprungen wurden, sorgen zwei weitere Mechanismen für ein permanentes Abtasten der maximal möglichen Leistung. Immer wenn bei schnellen Beschleunigungen ein Leistungssprung besonders groß ist (step_flag) wird die Variable "flag" auf 1 gesetzt. Daraufhin wird das Potentiometer in kurzer Folge solange stärker belastet bzw. entlastet, bis eine Richtungsumkehr in den Leistungswerten erreicht ist. Genauso wird bei längeren Gleichgewichtsphasen, in denen die Leistung konstant bleibt, solange weiterbelastet bis es auch hier zu einer Richtungsumkehr kommt. Die Geschwindigkeit beider Nachjustierungen kann über einen Zähler (counter) eingestellt werden - d.h. nach wieviel Schleifendurchgängen nachgeregelt werden soll.
Schließlich folgt noch die Abfrage der aktuellen Stromstärke, die darüber entscheidet, ob der Lastwiderstand über das entsprechende Relais (PIN8) zugeschaltet oder abgeschaltet wird.
Am Ende der Loop-Schleife wird ermittelt, ob die Generatorspannung (voltage) unterhalb der Ladespannung (stop-voltage) ist um ggfls. die Batterie über das entsprechende Relais (PIN9) zu trennen. Sollte in diesem Fall der digitale Widerstand nicht schnell genug heruntergeregelt worden sein, wird das Potentiometer neu resettet und auf seinen Start-Wert gesetzt.
Hier ist der komplette Programm-Code aufgelistet und kann ganz einfach mittels Copy/Paste in den Arduino Compiler eingefügt werden. Der Code ist ein erster Prototyp und wurde noch nicht unter Realbedingungen getestet.
#define ANALOG_IN_PIN_A1 A1
#define ANALOG_IN_PIN_A0 A0
#define CS 12
#define UD 10
#define INC 11
#define PIN8 8
#define PIN9 9
int pot_position;
int max_pot_pos = 40;
int min_pot_pos = 3;
bool pot_reset = 0;
int i = 0;
int t = 0;
float R1 = 11;
float R2 = 1;
float ref_voltage = 5.0;
int adc_value = 0;
double voltage = 0;
float adc_voltage = 0;
float stop_voltage = 14.5;
float start_voltage = 12;
float power = 0;
float last_power = 0;
float diff_power = 0;
float array_power[101];
float current = 0;
float array_current[101];
float sum_current = 0;
float av_current = 0;
float max_current = 9;
float resistance = 0;
bool direction = 0;
bool flag = 0;
int counter = 0;
float step = 3;
float step_flag = 8;
void setup()
{
// set pin mode
pinMode(INC, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(UD, OUTPUT);
pinMode(PIN8, OUTPUT);
pinMode(PIN9, OUTPUT);
// open serial monitor
Serial.begin(9600);
Pot_Reset();
}
void Pot_Reset()
{
Serial.println("Resetting potentiometer please wait...");
for(int i=0; i<=102; i++)
Down();
pot_position = 0;
for(int i=0; i<=3; i++)
Up();
pot_reset = 1;
}
void Show_Values()
{ Serial.print("voltage: ");
Serial.println(voltage);
Serial.print("current: ");
Serial.println(current);
Serial.println("");
Serial.print("power: ");
Serial.println(power);
Serial.print("last_power: ");
Serial.println(last_power);
Serial.print("diff_power: ");
Serial.println(diff_power);
Serial.println("");
Serial.print("pot_position: ");
Serial.println(pot_position);
Serial.println("");
Serial.println("");
delay (200);
}
void Up()
{
pot_position++;
digitalWrite(CS, LOW);
digitalWrite(UD, HIGH);
delay (5);
digitalWrite(INC, HIGH);
digitalWrite(INC,LOW);
delay (5);
last_power = power;
counter = 0;
if (direction == 0 && flag == 1)
flag = 0;
direction = 1;
pot_reset = 0;
}
void Down()
{
pot_position--;
digitalWrite(CS, LOW);
digitalWrite(UD, LOW);
delay (5);
digitalWrite(INC, HIGH);
digitalWrite(INC, LOW);
delay (5);
last_power = power;
counter = 0;
if (direction == 1 && flag == 1)
flag = 0;
direction = 0;
pot_reset = 0;
}
void Get_Voltage()
{
adc_value = analogRead(ANALOG_IN_PIN_A1);
adc_voltage = (adc_value * ref_voltage) / 1024.0;
voltage = adc_voltage / (R2/(R1+R2)) ;
voltage = voltage -0.2;
}
void Get_Current()
{
adc_value = analogRead(ANALOG_IN_PIN_A0);
adc_voltage = (adc_value*ref_voltage) / 1024;
current = -(adc_voltage -2.5)/0.1;
// current = current - 0.1;
if (current < 0) current = 0;
}
void loop()
{
Get_Voltage();
Get_Current();
if (voltage > start_voltage)
{ digitalWrite(PIN9, LOW);
array_current[i] = current;
i++;
if (i>=100)
{ current = 0;
for (t=0; t<=100; t++)
current = current+array_current[t];
current = current/100;
power = voltage * current;
diff_power = last_power - power;
if (diff_power < 0) diff_power = -diff_power;
//Show_values();
if (power < last_power && pot_position > min_pot_pos && last_power-power > step) Down();
if (power > last_power && pot_position < max_pot_pos && power-last_power > step) Up();
if (diff_power < step) counter++; // Gleichgewicht
if (diff_power > step) counter = 0; // kein Gleichgewicht
if (diff_power > step_flag) flag =1; // schnelle Beschleunigung
// Nachtracking bei schneller Beschleunigung
if (direction == 1 && counter >= 2)
{ if (flag == 1 && pot_position < max_pot_pos)
{ Up();
counter = 0;
}
}
// Nachtracking bei "Gleichgewicht"
if (direction == 1 && counter >= 4 && pot_position < max_pot_pos)
{ Up();
counter = 0;
}
// Nachtracking bei schneller Beschleunigung
if (direction == 0 && counter >= 2)
{ if (flag == 1 && pot_position > min_pot_pos)
{ Down();
counter = 0;
}
}
// Nachtracking bei "Gleichgewicht"
if (direction == 0 && counter >= 4 && pot_position > min_pot_pos)
{ Down();
counter = 0;
}
if (current < max_current)
digitalWrite(PIN8, High); // Dump Off
if (current >= max_current)
{ Down();
digitalWrite(PIN8, LOW); // Dump On
}
i = 0;
}
}
power = voltage *current;
if (voltage < stop_voltage && power < 2)
{ digitalWrite(PIN, HIGH);
if (pot_position >= 3 && pot_reset == 0)
Pot_Reset();
}
delay(1);
}