Um den Ladezustand der Brennstoffzelle zu ermitteln, verwenden wir eine kleine IR-Lichtschranke, die von oben auf den Wasserspiegel der Zelle zielt. Damit die Lichtschranke sicher auslöst, schwimmt auf dem Wasser ein rundes Stückchen Styropor. Beim Aufladen der Zelle entsteht Gas, das den Wasserspiegel ansteigen lässt. Bei Erreichen eines bestimmten Pegels löst die Lichtschranke aus, und wir wissen, dass die Zelle aufgeladen ist.
Die Kunst besteht nun darin, die Lichtschranke so einzustellen, dass sie auslöst, kurz bevor das Gas aus der Brennstoffzelle entweichen kann. Es schadet aber nichts, wenn das Aufladen durch eine nicht optimal eingestellte Lichtschranke etwas zu früh endet.
Wie Sie im Schaltplan unseres Testaufbaus in Abbildung 2 sehen, arbeitet die Lichtschranke mit 5 Volt. Die GPIO des Raspberry Pi verträgt jedoch maximal 3,3 Volt. Daher gibt es zwischen dem Ausgang der Lichtschranke und dem GPIO-Eingang des RasPi zwei in Durchlassrichtung geschaltete Dioden. Dort fällt die überschüssige Spannung ab, und wir laufen nicht Gefahr, den Mini-Rechner zu beschädigen. Hier kamen im Test 1N4007 zum Einsatz, die gerade in der Bastelkiste lagen, es genügen aber durchaus viel kleinere Typen.

Abbildung 2: Der komplette Schaltplan zu unserem Testaufbau. Eine detaillierte Beschreibung des INA3221-Messmoduls finden Sie im I2C-Workshop in diesem Heft.
Um das Laden beziehungsweise Entladen der Zelle steuern zu können, bauten wir in die Leitungen von der Solarzelle und zum Motor Relaiskontakte ein. Dafür verwendeten wir ein Relaismodul von der Stange [4]. Die Relais und die Lichtschranke schlossen wir an die GPIO-Ports 0 bis 2 an. Das INA3221-Messmodul verwendet die I2C-Schnittstelle des Raspberry Pi.
Testprogramm
Nachdem wir mit dem Aufbau unserer Experimentierumgebung fertig sind, können wir nun beginnen, das Testprogramm zu schreiben. Das Testprogramm (Listing 1) ist in Go [5] geschrieben und verwendet die Gobot-Bibliothek [6]. Die Installationsanleitung für beides finden Sie im Teil 18 der I2C-Reihe [7].
Das Programm FT_Brennzelle.go (Listing 1) lädt die Brennstoffzelle über das Solarpaneel auf, bis die IR-Lichtschranke auslöst. Danach startet das Entladen der Brennstoffzelle über das Riesenrad. Dabei erscheinen die Betriebsparameter wie Ströme, Ladung und Spannung auf dem Bildschirm. Nach dem kompletten Entladen der Zelle zeigt das Programm noch eine kleine Zusammenfassung an.
Listing 1
package main
import (
"fmt"
"os"
"time"
"gobot.io/x/gobot"
"gobot.io/x/gobot/drivers/i2c"
"gobot.io/x/gobot/drivers/gpio"
"gobot.io/x/gobot/platforms/raspi"
)
func main() {
charge:=0.0
maxCharge:=0.0
t:=0
chargeTime:=0
raspberry:=raspi.NewAdaptor()
sensor:=i2c.NewINA3221Driver(raspberry)
ir:=gpio.NewButtonDriver(raspberry, "11")
k1:=gpio.NewLedDriver(raspberry, "12")
k2:=gpio.NewLedDriver(raspberry, "13")
work:=func() {
k1.Off()
k2.On()
gobot.Every(6000*time.Millisecond, func() {
voltage,_:=sensor.GetLoadVoltage(1)
i1,_:=sensor.GetCurrent(1)
i2,_:=sensor.GetCurrent(2)
i3,_:=sensor.GetCurrent(3)
charge=charge+(i3/10)
t=t+6
fmt.Printf("Time : %d s\n",t)
fmt.Printf("Voltage : %.2f V\n",voltage)
fmt.Printf("Current Panel : %.2f mA\n",i1)
fmt.Printf("Current Motor : %.2f mA\n",i2)
fmt.Printf("Current Cell : %.2f mA\n",i3)
fmt.Printf("Charge : %.4f mA/h\n\n",charge/60)
if (voltage<0.3) {
fmt.Printf("MaxCharge : %.2f mA/h\n",maxCharge)
fmt.Printf("ChargeTime : %d s\n",chargeTime)
k1.On()
k2.On()
os.Exit(0)
}
})
ir.On(gpio.ButtonPush, func(data interface{}) {
fmt.Println("Cell full")
k1.On()
k2.Off()
maxCharge=charge/60
chargeTime=t
})
}
robot:=gobot.NewRobot(
"Raspberry Pi",
[]gobot.Connection{raspberry},
[]gobot.Device{sensor,ir,k1,k2},
work,
)
robot.Start()
}
Am Anfang des Codes stehen die nötigen Importe (Zeilen 2 bis 10), in unserem Fall zunächst jene der Bibliotheken für die Anzeige von Werten (fmt), für betriebssystemnahe Funktionen (os) und zur Zeitsteuerung (time). Darauf folgen die Importe der speziellen Gobot-Bibliotheken, deren Funktion sich aus den sprechenden Namen erschließt.
Am Anfang der Funktion main() definieren wir Variablen zum Speichern der Betriebsparameter der Brennstoffzelle: (charge für die aktuelle Ladung, maxCharge für die Ladung der voll aufgeladenen Zelle, t für die Programmlaufzeit und chargeTime für die Ladezeit (Zeilen 14 bis 16).
Die folgenden fünf Zeilen definieren die Objekte zur Kommunikation mit der Hardware (Zeilen 17 bis 21). Dabei beziehen sich die Pinnummern tatsächlich auf jene des 40-poligen GPIO-Anschlusses des Raspberry Pi, nicht auf die Notation von WiringPi oder die BCM-Notation.
Die nächsten Zeilen definieren die Funktion work() (Zeilen 22 bis 53), die alle weiteren Funktionen für unseren Testaufbau definiert. Die ersten beiden Zeilen schalten den GPIO-Port k1 aus und k2 an. Hier gilt es zu beachten, dass das Relaismodul mit umgekehrter Logik arbeitet. Schalten wir also einen GPIO-Ausgang auf Off, schaltet sich der entsprechende Relaisausgang auf On. In unserem Fall wird durch die Anweisungen die elektrische Verbindung zwischen Paneel und Brennstoffzelle hergestellt (Kontakt k1 geschlossen), das Aufladen beginnt.
Die nächste Zeile definiert innerhalb der Funktion work() eine weitere Funktion, die alle 6 Sekunden startet (Zeilen 25 bis 45). Sie misst alle Werte unseres Versuchsaufbaus und gibt sie auf dem Bildschirm aus. Hier ist auch die Bedingung für das Beenden des Programms implementiert: Fällt die Betriebsspannung der Zelle unter 0,3 Volt, terminiert das Programm (Zeilen 38 bis 44). Vorher gibt es noch die Betriebsparameter der Brennstoffzelle aus und setzt die GPIO-Ports auf On (umgekehrte Logik des Relaismoduls), um alle Stromkreise aufzutrennen.
Falls Sie sich nun wundern, warum hier immer von der “Funktion” die Rede ist: Das Gobot-Framework arbeitet an dieser Stelle mit anonymen Funktionen, die keinen Namen haben. Solche kommen zum Einsatz, wenn aus syntaktischen Gründen eine Funktion im Code nötig ist, diese aber so speziell ausfällt, dass sie kein zweites Mal verwendet werden kann. Man spart sich dann den Aufwand, ihr einen Namen zu geben, was zudem den Code kompakter und lesbarer macht. Innerhalb der Funktion work() gib es noch eine weitere anonyme Funktion, die startet, sobald die Lichtschranke auslöst (Zeilen 46 bis 52). Sie trennt das Paneel von der Brennstoffzelle und verbindet diese mit den Riesenrad.
Am Ende des Programms stehen noch einige Zeilen außerhalb der work()-Funktion (Zeilen 54 bis 59). Sie dienen dazu, um den Gobot-Roboter zu starten.
Sie starten das Programm mit dem Kommando go run FT_Brennzelle.go. Abbildung 3 zeigt ein Beispiel für die Ausgaben. Dabei hat das Laden der Zelle etwas mehr als eine Stunde benötigt. Das Entladen dauerte sogar noch länger, weil der Motor das Riesenrad mit sehr wenig Strom in Bewegung versetzen kann. Lassen Sie sich nicht von den geringen Abweichungen des Stromsensors verwirren, sie liegen innerhalb der Toleranzen.
Fazit
Es überrascht, wie viel elektrische Energie die kleine Brennstoffzelle speichern kann. Dabei blieben wir in unserem Versuch noch weit von den möglichen Lade- und Entladezeiten der Zelle entfernt: Mit ausreichend Ladeleistung lässt sie sich in rund 3 Minuten voll laden.






