Organspendebox

Auf dem Bild fehlt die eigentlich angedacht Holzbox sowie das Gefäß, welches die „Organe“ fassen sollte.

Projektbeschreibung

Die Organspendebox ist ein Modell einer echten Organspendebox, welche die Kernaufgaben einer solchen Box erfüllt. Die Box ist ausgestattet mit einem Positionsschalter und Schrittmotor, einem Display, sechs Edelstahldrucktastern (mit farbigem LED-Ring), einem roten Arcardebutton sowie Lüfter und Temperatursensor.

Der Schrittmotor wird in Kombination mit dem Positionsschalter zum Öffnen und Schließen des Deckels verwendet. Der Temperatursensor misst die Temperatur der gewünschten Oberfläche oder Umgebung. Wenn die gemessene Temperatur höher ist als die Wunschtemperatur, fängt der Lüfter an zu kühlen.

Mit Hilfe der sechs Edelstahldrucktastern lässt sich das Menü, welches auf dem Display angezeigt wird, steuern. Dabei sind immer die Taster für den Benutzer relevant, dessen LED-Ring leuchtet, wobei die LED-Ringe auf 3 verschiedene Schaltkreise aufgeteilt wurden. Taster ohne leuchtenden LED-Ring sind für den Moment irrelevant. Die Taster sind dazu da, sich durch das Menü zu navigieren, die Temperatur zu ändern, die Eingabe zu bestätigen und wieder zurück ins Hauptmenü zu kommen.

Das Menü besteht aus der Deckelsteuerung, Lüftersteuerung, Temperatursteuerung, Zeitinfo sowie der Temperaturinfo.

Über die Deckelsteuerung lässt sich der Deckel öffnen und schließen, über die Lüftersteuerung lässt sich der Lüfter an- und ausschalten. Die Temperatursteuerung gibt die aktuelle Temperatur aus und es lässt sich eine Wunschtemperatur festlegen. Im Menü Temperaturinfo wird die gemessene und angegebene Wunschtemperatur ausgegeben. Das Menü Zeitinfo gibt die Laufzeit des Programms aus.

Neben den Edelstahltastern ist ein zusätzlicher roter Arcardebutton verbaut, mit welchem sich das Programm beenden lässt.

Der Raspberry Pi ist mit Verkabelung und Hardware in einer separaten Box verstaut, was die Bedienung des Menüs über Taster und Display angenehmer und geordneter macht. Lediglich Schrittmotor, Temperatursensor, Endschalter und Lüfter hängen aus der Box heraus. Diese lassen sich flexibel an ein Gefäß oder eine weitere Box befestigen, welche dann als eigentliche Organspendebox dient.

Bauteile

Die bei dem Projekt verbauten Teile sind:

  • Raspberry Pi 4B
  • externe 12V Spannungsversorgung
  • 2x Breadboard 400 Pin
  • Schrittmotor inkl. Treiberplatine
  • Transistor
  • Lüfter
  • 9x 10kΩ Widerstand
  • 4-Zeilen-LCD-Display
  • Arcardebutton
  • 6x Edelstahltaster mit LED-Ring
  • Positionsschalter
  • DHT22 Temperatur und Feuchtigkeitsmesser

Aufbau

Code

Lüfter

Sobald der Lüfter manuell, über das entsprechende Menü, oder auf Grund der Bedingung, dass die gewünschte Temperatur niedriger ist, als die vom DHT22 gemessene Temperatur gestartet wird, dreht er so lange hoch, bis er seine maximale Drehzahl erreicht hat.

Das Starten des Lüfters wird über folgenden Code realisiert:

gpio.setup(32, gpio.OUT) #Initalisierung des GPIO-Pins (beliebiger GPIO-Pin nutzbar)
 
r = gpio.PWM(32, 100) #PWM-Steuerung (GPIO-Pin, Frequenz)
 
r.start(0) #nur bei Starten des Lüfters notwendig
 
for i in range(0, 100, 2): #Starten des Lüfters mit langsamen Hochdrehen (von 0Hz bis 100Hz in 2er Schritten)
    r.ChangeDutyCycle(i)
    time.sleep(0.05)

Der Unterschied bei dem Code zum Stoppen des Lüfters besteht darin, dass die Range nicht aufsteigend, sondern absteigend gesetzt werden muss und anschließend noch

r.stop()

hinzugefügt werden muss.

Der Lüfter muss über eine externe 12V Spannungsversorgung gespeist werden.

Schrittmotor

Da der Schrittmotor mit Magneten und deren durch Spannung erzeugten Magnetfelder gedreht wird, muss man jeden Magneten einzeln ansprechen. Man benötigt dementsprechend vier GPIO-Pins, die jeweils einen Magneten ansteuern. Je nach dem, in welcher Reihenfolge man die Magneten mit Spannung versorgt, dreht sich der Motor in die eine, bzw. andere Richtung.

Der Code für die Drehung nach links ist folgender:

schrittmotorsteuerung.py
gpio.setup(11, gpio.OUT) #IN1 auf Treiberplatine des Schrittmotors
gpio.setup(16, gpio.OUT) #IN2
gpio.setup(18, gpio.OUT) #IN3
gpio.setup(22, gpio.OUT) #IN4
 
gpio.output(11, gpio.HIGH)
time.sleep(0.008)
gpio.output(11, gpio.LOW)
time.sleep(0.008)
gpio.output(16, gpio.HIGH)
time.sleep(0.008)
gpio.output(16, gpio.LOW)
time.sleep(0.008)
gpio.output(18, gpio.HIGH)
time.sleep(0.008)
gpio.output(18, gpio.LOW)
time.sleep(0.008)
gpio.output(22, gpio.HIGH)
time.sleep(0.008)
gpio.output(22, gpio.LOW)
time.sleep(0.008)

Wichtig hierbei ist, dass die GPIOs in der richtigen Reihenfolge und nach dem HIGH-Schalten auch wieder auf LOW geschaltet werden.

Zusätzlich muss der Schrittmotor über eine externe Spannungsversorgung mit 12V gespeist werden.

externe Textdatei

Da wir in 2 Scripten unterschiedliche Konfigurationen der GPIO-Pins genutzt haben (BCM und BOARD) konnten wir diese Scripte nicht zu einem zusammenführen, da nur jeweils eine Konfiguration pro Script möglich ist.

Um die Werte, die in der einen Datei generiert werden in die andere zu übernehmen, mussten wir uns mit einer Textdatei behelfen, in welche die eine Datei die Werte schreibt und die andere Datei diese dann ausliest und anschließend weiter verarbeiten kann.

Schreiben und Lesen einer Datei erfolgt über den Aufruf der Datei mit den benötigten Rechten, sowie dem zu schreibenden Inhalt:

#Script 1
 with open("/home/*/*/*/tempc.txt", "w") as f: #tempc.txt schreibend öffnen, Wert schreiben und .txt schließen
     f.write(*zu schreibender Wert*) 
 
#Script 2     
with open("/home/*/*/*/tempc.txt", "r") as f: #tempc.txt lesend öffnen, Wert wird als String gespeichert und .txt schließen
    *Variable* = f.read() 

Die Textdatei muss vorher angelegt sein und der Dateipfad muss vollständig und korrekt angegeben werden.

Tasterabfragen

Für die Steuerung der verschiedenen Menüseiten und Zeilen, sowie das Bestätigen haben wir Taster angeschlossen. Hierfür haben wir externe Taster benutzt, welche zusätzlich noch einen LED-Ring haben. Dieser muss gesondert angesteuert werden.

Einen Tasterzustand auszulesen ist mit wenigen Zeilen Code möglich:

gpio.setup(33, gpio.IN) #Initalisierung -- ganz Wichtig, als "IN" initalisieren! --
 
if gpio.input(33) == True: #if-Anweisung, was gemacht werden soll, wenn der Taster betätigt wurde

Bei dem Anbringen von externen Tastern muss allerdings zwischen der Leiterbahn zum Raspberry und der Leiterbahn des Tasters ein Widerstand zwischengeschaltet werden, da der Taster „flimmert“. Er sendet also kein exaktes Signal, sondern flimmert durch gewisse Restspannung immer zwischen „1“ und „0“. Diese geringe, jedoch ausreichende Restspannung kann durch den Widerstand abgetragen werden, wodurch der Taster immer ein exaktes Signal sendet.

Das Ansteuern der LED-Ringe kann über einen freien GPIO-Pin erfolgen:

gpio.setup(31, gpio.OUT) #Initalisierung
 
gpio.output(31, gpio.HIGH) #wenn der LED-Ring leuchten soll, muss der output auf HIGH geschaltet werden

Die Menüsteuerung unseres Projektes würde über eine Reihe von if-Anweisungen programmiert.

Durch eine am Anfang des Codes angelegt Hilfsvariable (mpage), welche in Abhängigkeit der Menüpunktauswahl einen bestimmten Wert annimmt, konnte für jeden Wert eine if-Anweisung geschrieben werden. Diese umfasst den entsprechenden Code für die unterschiedlichen Menüseiten.

Als Beispiel ein Auszug aus dem Code:

if mpage == 1 #Deckelsteuerung
    #Anweisungen, was passieren soll, wenn mpage == 1
elif mpage == 2 #Lüftersteuerung
    #Anweisungen, was passieren soll, wenn mpage == 2
elif mpage == 3 #Temperatursteuerung
    #Anweisungen, was passieren soll, wenn mpage == 3
elif mpage == 99 #Temperaturänderung
    #Anweisungen, was passieren soll, wenn mapge == 99

Zum Abspringen in die unterschiedlichen Menüseiten wurde ein Hauptmenü entwickelt, welches auf dem Display ausgegeben wird. Durch Bestätigen der ausgewählten Funktion wird die Variable mpage auf den Wert gesetzt, der in der if-Anweisung als Bedingung für die Menüseite steht.

Als Code:

if mpage == 0 #Hauptmenü
    if mvisible == 0: #Hilfsvariable zur einmaligen Displayaktualisierung
        mcol = 0 #Variable, in welcher Zeile ">", was als Zeiger fungiert sich befinden soll
        lcd.lcd_clear() #Displayausgaben löschen, da sonst die neue Anzeige nur zu der alten hinzugefügt werden würde, was nicht die gewünschte Ausgabe zur Folge hat
        lcd.lcd_display_string("   ORGANSPENDEBOX", 1) #Display Zeile 1
        lcd.lcd_display_string("> Deckelsteuerung", 2) #Display Zeile 2
        lcd.lcd_display_string("  Lueftersteuerung", 3) #Display Zeile 3
        lcd.lcd_display_string("  Temp.Steuerung", 4) #Display Zeile 4
        mvisible = 1 #nach einmaliger Aktualisierung des Displays auf 1 setzten, damit in die else-Anweisung gegangen wird
    else: #Zeilensteuerung mit Absprung in jeweiliges Menü bei Bestätigung
        if mcol == 0: #Wenn der "Zeiger" sich in Zeile 1 befindet
            if gpio.input(15) == True: #Wenn der Taster zum bestätigen gedrückt wird, welcher mit dem GPIO-Pin 15 (BOARD-Konfiguration) verbunden ist
                mpage = 1 #setzte den Wert der Variablen mpage auf 1
                mvisible = 0
                time.sleep(0.25)

Durch das Setzen des Wertes der Variable wird in der oben gezeigten Menüsteuerung nun der Code ausgeführt, der in der if-Anweisung für mpage == 1 steht.

Temperatursensor

Um den Temperatursensor anzusteuern und die Werte auslesen zu können, ist das Einbinden der CircuitPython-DHT-Bibliothek von adafruit notwendig.

Bei dem Download ist eine Datei dabei, die als Testdatei zum Ausprobieren des Temperatursensors dient. Diese Datei haben wir verwendet, die von uns nicht benötigten Zeilen entfernt und die weiter oben beschriebenen Zeilen zum Schreiben in eine externe Datei hinzugefügt.

Das gesamte Script sieht dann so aus:

dht.py
#Beispielscript von adafruit (bearbeitet: nicht benötigte Zeilen entfernt und Schreiben in externe .txt Datei hinzugefügt)
import time #Zeit
import board #CircuitPython, welches Board genutzt wird (Adafruit)
import adafruit_dht #DHT-Bibliothek (Adafruit)
 
#Data-Pin für DHT, pulseio==False, da nicht CircuitPython kompatibel
dhtDevice = adafruit_dht.DHT22(board.D4, use_pulseio=False)
 
try:
        while True:
                try:
                        temperature_c = dhtDevice.temperature #Temperatur in Variable speichern
                        with open("/home/*/*/*/tempc.txt", "w") as f:
                                f.write("{:.1f}".format(temperature_c)) #.txt schreibend öffnen, formatierten Wert schreiben und .txt schließen
                        time.sleep(0.5)
 
                except RuntimeError as error: #da häufig Error, einfach ignorieren
                        pass
 
except Exception as error:
        pass
 
except KeyboardInterrupt:
        dhtDevice.exit()

Hierbei ist zu beachten, dass der Data-Pin von dem DHT22 auch an dem Pin des Raspberrys angeschlossen ist, der im Script angegeben ist. Sollte das nicht möglich sein, muss der Data-Pin dementsprechend abgeändert werden.

Hinweise

Hier sind noch ein paar nützliche Hinweise, die uns zu einem erfolgreichen Projekt verholfen haben:

  • macht einen Plan, wie Ihr an das Projekt herangehen wollt
  • Schritt für Schritt abarbeiten und nicht von hinten anfangen
  • nicht zu komplex denken
  • behaltet den Überblick über Eure Bauteile und deren Verkabelung
  • nicht aufgeben oder verzweifeln, wenn etwas nicht von Anfang an perfekt funktioniert

;-)