Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
waggelomma [2022/06/23 21:42] – student | waggelomma [2023/07/03 10:16] (aktuell) – Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Kurzbeschreibung ====== | ||
+ | |||
+ | Der Hintergrund unseres Projekts ist ein medizinischer: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | |||
+ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | |||
+ | ====== Aufbau ====== | ||
+ | |||
+ | Das 7‘‘ LCD Touch-Display lässt sich über ein Desktop-Icon starten. Es öffnet sich eine grafische Oberfläche mit zwei Buttons mit den Beschriftungen „Zeitprogramm“ und „Manuell“. Nachdem sich der Anwender zwischen den zwei Optionen entschieden hat, erscheinen mehrere Buttons, die bedient werden können. Je nachdem für welche Option sich der Benutzer entschieden hat, lassen sich die Buttons unterschiedlich bedienen. Beispielsweise kann man bei der Auswahl „Manuell“ kein Zeitprogramm starten, sondern nur per manueller Steuerung die einzelnen Kammern füllen oder leeren. Welche Buttons sich wann bedienen lassen, wird durch das angehangene Fließdiagramm deutlich. Die Motoren (ONPIRA Luftpumpen, 12V) pumpen Luft in die jeweiligen Kammern rein bzw. saugen diese ab. Da die Motoren immer zeitgleich Luft pumpen und absaugen, müssen die Magnetventile (stromlos offen, 12V) die Luftzufuhr steuern. Über die Steckplatinen sind die H-Brücken angeschlossen. An den H-Brücken sind die Motoren und die Magnetventile verkabelt. | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | |||
+ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | |||
+ | ====== Bauteile ====== | ||
+ | |||
+ | * 3x H-Brücke | ||
+ | {{ : | ||
+ | * 2x ONPIRA Luftpumpe, 12V | ||
+ | {{ : | ||
+ | * 4x Magnetventile 12V, 0.4bar, offen | ||
+ | {{ : | ||
+ | * 1x DR. WINKLER Zwilling Sitzkissen mit 2 getrennten Luftkammern (43x43cm) | ||
+ | {{ : | ||
+ | * 2x Steckplatinen | ||
+ | {{ : | ||
+ | * 1x 7‘‘ LCD Touch-Display | ||
+ | {{ : | ||
+ | * 1x GPIO-Adapterkabel | ||
+ | * 1x T-Cobbler für den Raspberry Pi | ||
+ | {{ : | ||
+ | * 1x ZIPPY FlightMax 2800mAh 30C | ||
+ | {{ : | ||
+ | * Kabel | ||
+ | * Schläuche | ||
+ | * Adapter für die Schläuche aufgrund unterschiedlicher Durchmesser | ||
+ | |||
+ | |||
+ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | |||
+ | ====== Schaltplan ====== | ||
+ | |||
+ | {{ : | ||
+ | // | ||
+ | |||
+ | |||
+ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | ====== Quellcode ====== | ||
+ | |||
+ | Zunächst haben wir alle benötigten Bibliotheken und GPIO's importiert. | ||
+ | |||
+ | <file c Code.c> | ||
+ | import RPi.GPIO as gpio # | ||
+ | import pygame_horstEdition as horst # | ||
+ | import time # | ||
+ | |||
+ | |||
+ | #region GPIO-Müll | ||
+ | gpio.setwarnings(False) | ||
+ | |||
+ | gpio.setmode(gpio.BOARD) | ||
+ | gpio.setup(12, | ||
+ | gpio.setup(11, | ||
+ | gpio.setup(13, | ||
+ | gpio.setup(15, | ||
+ | gpio.setup(29, | ||
+ | gpio.setup(21, | ||
+ | gpio.setup(22, | ||
+ | gpio.setup(36, | ||
+ | gpio.setup(16, | ||
+ | gpio.setup(32, | ||
+ | gpio.setup(40, | ||
+ | |||
+ | #endregion | ||
+ | </ | ||
+ | |||
+ | Danach haben wir uns um das Touch-Display gekümmert. Hier haben wir die Auflösung des Bildschirms festgelegt und alle Knöpfe, Icons und die dazugehörigen Texte angelegt. | ||
+ | |||
+ | <file c Code.c> | ||
+ | |||
+ | horst.start((1920, | ||
+ | |||
+ | bildschenTitel = horst.Picture((217, | ||
+ | |||
+ | knoppekAutomatisch = horst.Knopp((138, | ||
+ | bildschenAutomatisch = horst.Picture((225, | ||
+ | knoppekManuell = horst.Knopp((1026, | ||
+ | bildschenManuell = horst.Picture((1248, | ||
+ | |||
+ | Kammerli = horst.Rect((74, | ||
+ | Kammerli.setVisible(False) | ||
+ | schriftKammerli = horst.Text((214, | ||
+ | schriftKammerli.setVisible(False) | ||
+ | Kammerre= horst.Rect((1289, | ||
+ | Kammerre.setVisible(False) | ||
+ | schriftKammerre = horst.Text((1420, | ||
+ | schriftKammerre.setVisible(False) | ||
+ | |||
+ | #region HorstElemente | ||
+ | knoppekStart = horst.Knopp((74, | ||
+ | knoppekStart.setActive(False) | ||
+ | knoppekStart.setVisible(False) | ||
+ | schriftStart = horst.Text((207, | ||
+ | schriftStart.setVisible(False) | ||
+ | |||
+ | knoppekZeitprogramm = horst.Knopp((544, | ||
+ | knoppekZeitprogramm.setActive(False) | ||
+ | knoppekZeitprogramm.setVisible(False) | ||
+ | schriftZeitprogramm = horst.Text((624, | ||
+ | schriftZeitprogramm.setVisible(False) | ||
+ | |||
+ | knoppekPause = horst.Knopp((1019, | ||
+ | knoppekPause.setActive(False) | ||
+ | knoppekPause.setVisible(False) | ||
+ | schriftPause = horst.Text((1135, | ||
+ | schriftPause.setVisible(False) | ||
+ | |||
+ | knoppekEnde = horst.Knopp((1482, | ||
+ | knoppekEnde.setActive(False) | ||
+ | knoppekEnde.setVisible(False) | ||
+ | schriftEnde = horst.Text((1618, | ||
+ | schriftEnde.setVisible(False) | ||
+ | |||
+ | knoppekDrucklihoch = horst.Knopp((74, | ||
+ | knoppekDrucklihoch.setActive(False) | ||
+ | knoppekDrucklihoch.setVisible(False) | ||
+ | bildschenDrucklihoch = horst.Picture((150, | ||
+ | bildschenDrucklihoch.setVisible(False) | ||
+ | |||
+ | knoppekDrucklirunter = horst.Knopp((374, | ||
+ | knoppekDrucklirunter.setActive(False) | ||
+ | knoppekDrucklirunter.setVisible(False) | ||
+ | bildschenDrucklirunter = horst.Picture((450, | ||
+ | bildschenDrucklirunter.setVisible(False) | ||
+ | |||
+ | knoppekDruckrehoch = horst.Knopp((1294, | ||
+ | knoppekDruckrehoch.setActive(False) | ||
+ | knoppekDruckrehoch.setVisible(False) | ||
+ | bildschenDruckrehoch = horst.Picture((1370, | ||
+ | bildschenDruckrehoch.setVisible(False) | ||
+ | |||
+ | knoppekDruckrerunter = horst.Knopp((1591, | ||
+ | knoppekDruckrerunter.setActive(False) | ||
+ | knoppekDruckrerunter.setVisible(False) | ||
+ | bildschenDruckrerunter = horst.Picture((1665, | ||
+ | bildschenDruckrerunter.setVisible(False) | ||
+ | |||
+ | slider = horst.Slider((74, | ||
+ | slider.setVisible(False) | ||
+ | |||
+ | #endregion | ||
+ | |||
+ | horst.refresh() | ||
+ | |||
+ | </ | ||
+ | |||
+ | Nun werden alle benötigten Methoden deklariert. Dies haben wir gemacht, um später weniger Arbeit zu haben, da dann nur noch die einzelnen Methoden aufgerufen werden müssen und man sich unnötige Schreibarbeit spart. | ||
+ | |||
+ | <file c Code.c> | ||
+ | #region Hauptfunktionen | ||
+ | def ElBlaso(kammer): | ||
+ | # | ||
+ | if(kammer ==1): #wir pusten in Kammer 1 | ||
+ | gpio.output(22, | ||
+ | gpio.output(21, | ||
+ | else: #wir pusten in Kammer 2 | ||
+ | gpio.output(12, | ||
+ | gpio.output(11, | ||
+ | |||
+ | def ElSaugo(kammer): | ||
+ | # | ||
+ | if(kammer==1): | ||
+ | gpio.output(22, | ||
+ | gpio.output(21, | ||
+ | else: #Kammer 2 wird angesprochen | ||
+ | gpio.output(12, | ||
+ | gpio.output(11, | ||
+ | |||
+ | def ElHalto(kammer): | ||
+ | # | ||
+ | # | ||
+ | if(kammer==1): | ||
+ | gpio.output(22, | ||
+ | gpio.output(21, | ||
+ | else: # | ||
+ | gpio.output(12, | ||
+ | gpio.output(11, | ||
+ | |||
+ | def reicht(): | ||
+ | gpio.output(36, | ||
+ | gpio.output(11, | ||
+ | gpio.output(22, | ||
+ | gpio.output(21, | ||
+ | gpio.output(12, | ||
+ | gpio.cleanup() | ||
+ | |||
+ | def Motörchen(state): | ||
+ | # | ||
+ | gpio.output(36, | ||
+ | |||
+ | def KritischeAbbruchfrage(): | ||
+ | if knoppekEnde.isPressed(): | ||
+ | reicht() | ||
+ | exit() | ||
+ | |||
+ | def DruckVerstello(input): | ||
+ | horst.keepAlive() | ||
+ | time.sleep(0.2) | ||
+ | zeitpunkt = time.time() | ||
+ | if(input ==1): #wenn input = 1 | ||
+ | | ||
+ | | ||
+ | if(input == 2): #wenn input = 2 | ||
+ | ElSaugo(1) | ||
+ | ElHalto(2) | ||
+ | if(input == 3): #wenn input=3 | ||
+ | ElBlaso(2) | ||
+ | ElHalto(1) | ||
+ | if(input == 4): #wenn input = 4 | ||
+ | ElSaugo(2) | ||
+ | ElHalto(1) | ||
+ | Motörchen(1) | ||
+ | while time.time()-zeitpunkt < 10: #zeit - jetzigem zeitpunkt kleiner 10 --> while schleife läuft 10sek | ||
+ | horst.keepAlive() | ||
+ | time.sleep(0.2) | ||
+ | KritischeAbbruchfrage() | ||
+ | if (knoppekDruckrehoch.isPressed()or knoppekDruckrerunter.isPressed()or knoppekDrucklihoch.isPressed()or knoppekDrucklirunter.isPressed()): | ||
+ | break #... dann brich ab --> 10sek werden nicht abgewartet, sondern bricht ab | ||
+ | Motörchen(0) #motoren aus | ||
+ | |||
+ | def MannoProgram(): | ||
+ | while 1: # | ||
+ | horst.keepAlive() | ||
+ | if knoppekDruckrehoch.isPressed(): | ||
+ | DruckVerstello(3) | ||
+ | if knoppekDruckrerunter.isPressed(): | ||
+ | DruckVerstello(4) | ||
+ | if knoppekDrucklihoch.isPressed(): | ||
+ | DruckVerstello(1) | ||
+ | if knoppekDrucklirunter.isPressed(): | ||
+ | DruckVerstello(2) | ||
+ | KritischeAbbruchfrage() #wenn ende knopf gedrückt wird, wird alles beendet --> Methode wird aufgerufen | ||
+ | if knoppekPause.isPressed(): | ||
+ | time.sleep(0.2) | ||
+ | |||
+ | def GroßKnoppeksWech(): | ||
+ | knoppekAutomatisch.setActive(False) | ||
+ | knoppekAutomatisch.setVisible(False) | ||
+ | knoppekManuell.setActive(False) | ||
+ | knoppekManuell.setVisible(False) | ||
+ | bildschenAutomatisch.setVisible(False) | ||
+ | bildschenManuell.setVisible(False) | ||
+ | |||
+ | def KleineKnoppeksHer(): | ||
+ | knoppekZeitprogramm.setActive(True) | ||
+ | knoppekZeitprogramm.setVisible(True) | ||
+ | knoppekStart.setActive(True) | ||
+ | knoppekStart.setVisible(True) | ||
+ | knoppekPause.setActive(True) | ||
+ | knoppekPause.setVisible(True) | ||
+ | knoppekEnde.setActive(True) | ||
+ | knoppekEnde.setVisible(True) | ||
+ | knoppekDrucklihoch.setActive(True) | ||
+ | knoppekDrucklihoch.setVisible(True) | ||
+ | knoppekDrucklirunter.setActive(True) | ||
+ | knoppekDrucklirunter.setVisible(True) | ||
+ | knoppekDruckrehoch.setActive(True) | ||
+ | knoppekDruckrehoch.setVisible(True) | ||
+ | knoppekDruckrerunter.setActive(True) | ||
+ | knoppekDruckrerunter.setVisible(True) | ||
+ | slider.setVisible(True) | ||
+ | Kammerli.setVisible(True) | ||
+ | Kammerre.setVisible(True) | ||
+ | |||
+ | def bildschenWech(): | ||
+ | bildschenDrucklihoch.setVisible(False) | ||
+ | bildschenDrucklirunter.setVisible(False) | ||
+ | bildschenDruckrehoch.setVisible(False) | ||
+ | bildschenDruckrerunter.setVisible(False) | ||
+ | |||
+ | def bildschenHer(): | ||
+ | bildschenDrucklihoch.setVisible(True) | ||
+ | bildschenDrucklirunter.setVisible(True) | ||
+ | bildschenDruckrehoch.setVisible(True) | ||
+ | bildschenDruckrerunter.setVisible(True) | ||
+ | |||
+ | def textWech(): | ||
+ | schriftKammerli.setVisible(False) | ||
+ | schriftKammerre.setVisible(False) | ||
+ | schriftStart.setVisible(False) | ||
+ | schriftZeitprogramm.setVisible(False) | ||
+ | schriftPause.setVisible(False) | ||
+ | schriftEnde.setVisible(False) | ||
+ | |||
+ | def textHer(): | ||
+ | schriftKammerli.setVisible(True) | ||
+ | schriftKammerre.setVisible(True) | ||
+ | schriftStart.setVisible(True) | ||
+ | schriftZeitprogramm.setVisible(True) | ||
+ | schriftPause.setVisible(True) | ||
+ | schriftEnde.setVisible(True) | ||
+ | |||
+ | #endregion | ||
+ | |||
+ | </ | ||
+ | |||
+ | Jetzt folgen einige Schleifen, die verschiedene Methoden und Variablen aufrufen. Diese steuern dann die Funktionen und Sichtbarkeiten der einzelnen Knöpfe. | ||
+ | |||
+ | <file c Code.c> | ||
+ | |||
+ | while 1: | ||
+ | horst.keepAlive() | ||
+ | time.sleep(0.2) | ||
+ | if knoppekAutomatisch.isPressed(): | ||
+ | # | ||
+ | GroßKnoppeksWech() | ||
+ | KleineKnoppeksHer() | ||
+ | bildschenHer() | ||
+ | textHer() | ||
+ | while 1: # | ||
+ | horst.keepAlive() | ||
+ | | ||
+ | if knoppekStart.isPressed(): | ||
+ | timenow = time.time() | ||
+ | ElBlaso(1) | ||
+ | ElBlaso(2) | ||
+ | Motörchen(1) | ||
+ | | ||
+ | while time.time()-timenow < 150: #zeit - jetzigem zeitpunkt kleiner 150 --> while schleife läuft 150sek | ||
+ | horst.keepAlive() | ||
+ | time.sleep(0.2) | ||
+ | KritischeAbbruchfrage() #wenn ende knopf gedrückt wird, wird alles beendet --> Methode wird aufgerufen | ||
+ | ElHalto(1) | ||
+ | ElHalto(2) | ||
+ | Motörchen(0) #motoren aus | ||
+ | knoppekStart.setActive(False) | ||
+ | knoppekZeitprogramm.setActive(True) #aktiviert Zeitprgrammknoppek | ||
+ | | ||
+ | KritischeAbbruchfrage() #wenn ende knopf gedrückt wird, wird alles beendet --> Methode wird aufgerufen | ||
+ | |||
+ | if knoppekZeitprogramm.isPressed(): | ||
+ | timenow = time.time() #legt aktuelle Zeit auf timenow | ||
+ | while time.time()-timenow < 20: #zeit - jetzigem zeitpunkt kleiner 20 --> while schleife läuft 20sek | ||
+ | zeitjeloofen = 0 #variable zeitjeloofen am anfang auf 0 gesetzt | ||
+ | horst.keepAlive() | ||
+ | slider.newValue((time.time()-timenow)/ | ||
+ | horst.refresh() | ||
+ | if time.time()-timenow < 15: #zeit - jetzigem zeitpunkt kleiner 15 --> wenn wir innerhlab der 15sek sind, dann... | ||
+ | ElSaugo(2) #... luft aus kammer rechts raus | ||
+ | Motörchen(1) #motoren an | ||
+ | else: | ||
+ | ElHalto(2) | ||
+ | Motörchen(0) #motoren aus | ||
+ | KritischeAbbruchfrage() | ||
+ | if knoppekPause.isPressed(): | ||
+ | zeitjeloofen = time.time()-timenow | ||
+ | Motörchen(0) #motoren aus | ||
+ | ElHalto(1) #elhalto kammerli | ||
+ | ElHalto(2) | ||
+ | while 1: # | ||
+ | horst.keepAlive() | ||
+ | time.sleep(0.2) | ||
+ | MannoProgram() | ||
+ | KritischeAbbruchfrage() | ||
+ | if knoppekPause.isPressed(): | ||
+ | timenow = time.time()-zeitjeloofen | ||
+ | break # | ||
+ | ElHalto(1) | ||
+ | |||
+ | ElHalto(1) #nach den 20sek, luft halten in beiden kammern | ||
+ | ElHalto(2) | ||
+ | KammerMehr = 2 # | ||
+ | KammerWenig= 1 # | ||
+ | while 1: # | ||
+ | zeitjeloofen = 0 #zeit, die gelaufen ist, liegt bei 0sek | ||
+ | timenow = time.time() #legt aktuelle Zeit auf timenow | ||
+ | while time.time()-timenow < 20: #schleife, wechselspiel der kammern beginnt und slider läuft insgesamt 20sek | ||
+ | horst.keepAlive() | ||
+ | slider.newValue((time.time()-timenow)/ | ||
+ | horst.refresh() | ||
+ | if time.time()-timenow < 15: # | ||
+ | ElSaugo(KammerWenig) | ||
+ | ElBlaso(KammerMehr) | ||
+ | Motörchen(1) | ||
+ | else: #nach den 15sek, wird luft in beiden kammern für 5sek gehalten | ||
+ | ElHalto(KammerMehr) #luft wird gehalten | ||
+ | ElHalto(KammerWenig) | ||
+ | Motörchen(0) | ||
+ | KritischeAbbruchfrage() | ||
+ | | ||
+ | if knoppekPause.isPressed(): | ||
+ | zeitjeloofen = time.time()-timenow | ||
+ | Motörchen(0) #motoren aus | ||
+ | ElHalto(1) #luft wird in kammer gehalten | ||
+ | ElHalto(2) | ||
+ | while 1: # | ||
+ | horst.keepAlive() | ||
+ | time.sleep(0.2) | ||
+ | MannoProgram() #manuelles Programm wird gestartet (Methode wird aufgerufen) | ||
+ | KritischeAbbruchfrage() | ||
+ | if knoppekPause.isPressed(): | ||
+ | timenow = time.time()-zeitjeloofen | ||
+ | break | ||
+ | | ||
+ | if(KammerMehr==1): | ||
+ | KammerMehr=2 #.. kriegt kammer rechts in der nächsten runde luft | ||
+ | KammerWenig=1 #.. und die linke kriegt luft abgezogen | ||
+ | else: # | ||
+ | KammerMehr=1 | ||
+ | KammerWenig=2 | ||
+ | |||
+ | time.sleep(0.2) | ||
+ | |||
+ | if knoppekManuell.isPressed(): | ||
+ | GroßKnoppeksWech() # | ||
+ | KleineKnoppeksHer() | ||
+ | bildschenHer() # | ||
+ | textHer() | ||
+ | MannoProgram() | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | |||
+ | ====== Probleme ====== | ||
+ | |||
+ | Zu Beginn unseres Projekts hatten wir die Idee, die Motoren mit dem Luftdruck in den Kammern zu steuern und diesen auch ausgeben zu lassen. Das heißt, dass die Kammern einen gewissen Druck erreicht hätten und sich der Kammerdruck anhand dessen reguliert hätte. Allerdings hat dies nicht funktioniert. | ||
+ | |||
+ | Zuerst hatten wir die MPX5500DP Drucksensoren erhalten, die den Druck analog ausgeben, weshalb wir hier mit dem AD-Wandler arbeiten mussten. Da der Druck in den Kammern zu gering war und die Drucksensoren ihn nicht registrieren konnten, hat es nicht funktioniert. Danach bekamen wir die Drucksensoren BME280, die bereits digital waren, wodurch der AD-Wandler wegfiel. Leider bekamen wir immer wieder die Fehlermeldung „Connection timed out“. Warum es letztendlich nicht funktionierte, | ||
+ | |||
+ | |||
+ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
+ | ====== Quellen ====== | ||
+ | |||
+ | Extern bezogene Bibliothek (pygame_horstEdition as horst) | ||
+ | |||
+ | Skripte aus der Vorlesung | ||
+ | |||
+ | Anleitung zur Erstellung vom Desktop-Icon: | ||