Adaption an Multi-MCU - Neuprogrammierung MATLAB® GUI: Unterschied zwischen den Versionen

Aus Technische Beeinflussbarkeit der Geschmacksache Kaffee
Zur Navigation springen Zur Suche springen
Keine Bearbeitungszusammenfassung
 
(46 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
= Melina Scherf, 25.07.2023, offene Themen =
= Madita vom Stein, 27.07.2023 - Abschlussbemerkung MATLAB®-GUI =
* Messwertpuffr -> Vernünftige Reihenfolge
[[Datei:Startseite der alten GUI.png|thumb|500px|rechts|Abbildung 12: Startseite der alten GUI]]
* Initalisierung bageschlossen zum Schluss erscheinen
[[Datei:Startseite der neuen GUI.png|thumb|500px|rechts|Abbildung 11: Startseite der neuen GUI]]
* Durchrollieren
[[Datei:Programme der alten GUI.png|thumb|500px|rechts|Abbildung 10: Programme der alten GUI]]
* Messwerte erst bei Knopfdruck starten
[[Datei:Programme der neuen GUI.png|thumb|500px|rechts|Abbildung 9: Programme der neuen GUI]]
* Fehlerfall >>> Überschreibung?
[[Datei:Manueller Modus der alten GUI.png|thumb|500px|rechts|Abbildung 8: manueller Modus der alten GUI]]
* Signaölwort M/B!
[[Datei:Manueller Modus der neuen GUI.png|thumb|500px|rechts|Abbildung 7: manueller Modus der neuen GUI]]
* Fehlerfall in Msicherkurve wenn 0
[[Datei:Reinigungsprogramm (neue GUI).png|thumb|500px|rechts|Abbildung 6: Reinigungsprogramm (neue GUI)]]
* Anzeige von Messwerten letzten fehlen
* Zuordnung Ventile
* Knöpfe funktionsfähig
* VrbindungImport ident vor Terminator?
* Anzeige der Istwerte
* Heizung nicht funktionsfähig 
* Herizung/ Pumpe stellen() keine Visualisierung
* Stellfunktionen für Bypass und Brühgruppendrossel
* Optimierung Status/Bildwechsel der neuen Ventilschaltung
* Regler und funktionsschaltung ändern


* neue Aktorenstellung
Die MATLAB®-GUI ist die graphische Bedieneroberfläche der Laborsiebträgermaschine. Die in der GUI durch den Anwender eingegebenen Befehle, beispielsweise das Schalten eines Ventils, werden über den im Hintergrund laufenden MATLAB®-Programmcode an eine Schnittstelle weitergegeben. Diese Schnittstelle steuert die Multi-MCUs an, die direkt auf die Maschine zugreifen. <br>
* Vorschlag init_mcus()
Als Anwender gelten Studierende, sowie Lehrende, die im Rahmen der „Geschmackssache Kaffee“ an der Labormaschine arbeiten; also Testversuche fahren oder die Maschine weiterentwickeln. Die MATLAB®-GUI ist demnach nicht für den Endanwender der Maschine gedacht. Das verkaufsfähige Endprodukt soll, wie auf dem Markt üblich, mit Schaltern und Knöpfen ausgestattet sein. <br> <br>


* Fehlerpuffer
Zum Zeitpunkt des Projektstartes lag bereits eine MATLAB®-App inklusive GUI vor [85]. Statt einer Einarbeitung und Weiterentwicklung in den bestehenden Code, erschien eine vollständige Neuaufsetzung der MATLAB®-App und GUI sinnvoller. <br> <br>
* Antwort durchrollieren
* Kommandopuffer
* connected


Im Hinblick auf die oben genannten Anwender wurde bei der Zielsetzung die Erleichterung der Arbeit im Labor priorisiert. Da die studentischen Arbeitskräfte zum Großteil einer hohen Fluktuation unterliegen, wurde außerdem auf eine intuitive Bedienbarkeit und eine hohe Übersichtlichkeit geachtet. Dadurch soll das Einfinden in die MATLAB®-GUI erleichtert, und folglich die Einarbeitungszeit verkürzt werden. <br> <br>


= Melina Scherf, 23.07.2023, Ventilschaltung automatischer Wechsel =
Sowohl die alte als auch die neue MATLAB®-GUI ist in Tabs unterteilt. Diese gliedern sich in die Startseite, einen manuellen Modus und einen automatischen Modus für Bezugsprogramme. Die neue MATLAB®-GUI beinhaltet zusätzlich einen Tab für das Reinigungsprogramm, welches im Rahmen der Projektarbeit entstanden ist. <br>
                if app.manualOverwriteAktiv == 1
Die bisherige MATLAB®-GUI weist zudem Verbesserungspotenzial auf. So war der gesamte Laptop-Bildschirm durch die GUI ausgefüllt. In der neuen GUI wurde bewusst ein Format von 1720 x 880 Pixeln gewählt, sodass wahlweise am oberen oder unteren Rand der GUI ein im Hintergrund liegendes Programm sichtbar ist. Im Falle der Weiterentwicklung der Systemsoftware könnte dies das Command Window von MATLAB® sein, sodass Fehlermeldungen sofort zur Kenntnis genommen werden. <br>
                    if app.flag_Y01 == 0
Ebenfalls neu ist, dass die Tabs nicht die gesamte Oberfläche der GUI einnehmen, sondern es einen immer sichtbaren Bereich gibt. Dieser bringt vier Vorteile mit sich. Erstens wird nicht für jeden Tab ein eigener Button für das Speichern des Messwertepuffers benötigt. Stattdessen gibt es diesen Button ein einziges Mal, aber in dem Bereich, auf den ein Zugriff jederzeit möglich ist. Ein zweiter Vorteil ist, dass die für das Geschmackserlebnis besonders relevanten Messwerte Leitungsdruck [mbar] und Durchflussrate [ml / s] ständig sichtbar sind. Auch der Error-Button, sowie der zugehörige Reset-Error-Button, ist in allen Tabs relevant. Die Verschiebung in den immer sichtbaren Bereich brachte auch hier eine erhöhte Reaktionsgeschwindigkeit auf Probleme mit sich, worin der dritte Vorteil liegt. Bei der Reaktion auf Probleme ist auch der Notaus-Button von Bedeutung. Hier können durch schnelles Handeln Schäden an Menschen und Maschine vermieden werden. Ebenfalls in dem immer sichtbaren Bereich ist der jeweilige
                    % wenn das Ventil geschlossen ist -> Öffnen
Programmstatus der einzelnen Platinen. Das hat den Vorteil, dass immer erkennbar ist, ob diese verbunden sind; nicht nur auf der Startseite. <br>
An der Startseite selbst hat sich kaum etwas verändert. Es gibt hier nach wie vor die Buttons „manueller Modus“, „Verbinden“, sowie „Debug“. Weiterhin gibt es Eingabefelder für Daten wie beispielsweise das Datum, die Kaffeesorte oder den Mahlgrad, die den Messwerten zugeordnet werden. Es ist außerdem einstellbar, wie oft die Daten gesichert werden sollen. <br>
Während der Tab „Programme“ in der alten MATLAB®-GUI neben drei Schalter für Kaffeebezug, Teewasserbezug und Dampfbezug auch noch sehr viele andere Inhalte, die nicht direkt den Programmen zuordbar sind, wie beispielsweise die k-Faktoren der Regler, beinhaltet, ist dieser Tab in der neuen GUI minimalistischer gehalten. Da die Programme bisher gar nicht existieren,
gibt es hier lediglich vier Buttons als Platzhalter. Ein Programm wird über diese gestartet und gestoppt. Der aktuelle Programmstatus ist an dem jeweils nebenstehenden Lämpchen erkennbar, wobei „rot“ bedeutet, dass das Programm in dem Moment aktiv ist. Während ein Programm durchläuft, sind Ventilschaltungen und Zustandsparameter in dem manuellen Modus nachverfolgbar. <br>
Ansonsten ist der manuelle Modus primär dazu gedacht, dass Ventile einzeln geschaltet, Parameter einzeln geändert, und dadurch Programme entwickelt und getestet werden können. Das Prozessbild der alten GUI ist sehr detailliert und informativ, dadurch aber leider auch sehr unübersichtlich. Es sind auch die Wege des Brauchwassers hin zur Abtropfschale dargestellt. Dies ist bei Hydraulikplänen unüblich und verbraucht zusätzlichen Platz. Durch die vielen Farben und
Formen wird die Aufmerksamkeit des Benutzers immer wieder hin zu anderen Stellen gelenkt. Dadurch, dass die Messwerte recht klein und an wenig intuitiven Stellen dargestellt sind, sind diese schwierig zu finden. Die Schalter für die Grundeinstellungen stehen nicht gesammelt und in keiner sinnvollen Reihenfolge. <br>
In der neuen GUI dagegen sind diese Schalter in schlüssiger Reihenfolge, gesammelt oben links abgebildet. Die Bezeichnungen der Messwerte sind größer und fett gedruckt geschrieben. Die Messwerte selbst sind grau hinterlegt. Die Positionierung der Werte ist im Vergleich zu vorher logisch. Die Mischtemperatur befindet sich zum Beispiel an der Stelle, wo gedrosseltes Kalt- und in der Heizwendel erhitztes Warmwasser zusammentreffen. Die Brühgruppenwerte sind direkt in der angedeuteten Brühgruppe zu finden. Insgesamt ist das neue Prozessbild deutlich ruhiger. Es sind nur die wichtigsten Stränge dargestellt. Die Brauchwasserleitungen sind angedeutet. <br>
Ein Hauptunterschied der neuen zur alten GUI liegt in der Ventildarstellung. Während zuvor durch Lämpchen in den Ventilen signalisiert wurde, ob, beziehungsweise wie, ein Ventil geschaltet ist, wird dies in der neuen GUI durch einen Bildwechsel deutlich. Klickt der Benutzer auf das Ventil im Prozessbild, ändert sich das im MATLAB®-Code hinterlegte Ventilbild und das Ventil wird geschaltet. <br>
Da vor Beginn des Projektstartes noch kein Reinigungsprogramm existierte, gibt es den betreffenden Tab lediglich in der neuen GUI. Hier gibt es einen Button zum Start des Programmes, sowie eine Anzeige zum aktuellen Status. Es ist außerdem eine Beschreibung des Ablaufs und Hinweise dazu eingefügt. <br>
Durch die zuvor angesprochenen Maßnahmen ist die neue MATLAB®-GUI übersichtlicher und intuitiver zu bedienen als die alte GUI. Sie ist außerdem auf dem neusten Stand des Hydraulikplans und bildet somit die Labormaschine treffend ab. <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br>


                          app.Y01.Icon = '2WegeRechts.png'; % Ändern des Bildes im Reiter "manueller Modus" zu geöffnet
= Melina Scherf, 25.07.2023, offene Themen =
                          app.flag_Y01 = 1;                % Ändern der Statusinformation, wie das Ventil steht
Der generelle Aufbau des Programmcodes wurde in einzelne Unterüberschriften unterteilt, sodass zukünftigen Bearbeitern die Zugehörigkeit der Funktionen verständlich wird. Diese lauten: Initialisierung und Verarbeitung MCUs, Programm- und Regleraufruf, Regler, Aktorenstellung. Es ist darauf zu achten, dass Programm- und Regleraufruf sowie Regler nur an den Programmcode angepasst wurden, ihre Funktionsweise jedoch nicht verändert wurde. <br>
                    else
Von zukünftige Bearbeitende sind noch Verbesserungen vorzunehmen. Eine Statusmeldung am Ende der Initialisierung, dass diese beendet wurde, ist nicht der letzte Eintrag in der Statusleiste. Hier muss eine künstliche Verlangsamung vorgenommen werden. Die Initialisierungsfunktion wird häufiger als 4x aufgerufen. Dies liegt daran, dass durch den Import des ident-Programmes, vor Aufruf der ident()-Funktion, bereits ein Terminator gesendet wird. <br>
                    % wenn das Ventil geöffnet ist -> Schließen
Die im Reiter „manueller Modus“ angelegten Schalter sind noch nicht auf Funktionalität überprüft worden. Die Messwerte starten beim letzten Testdurchlauf des Programms automatisch mit der Initialisierung der MWP. Dieses sollte erst durch Betätigung eines Schalters geschehen. Zudem war das Signalwort der einkommenden Messwerte nicht gleichermaßen definiert (M und B!). <br>
Die Abspeicherung der Messwerte in den Messwertpuffer erfolgt nach einer nicht mehr passenden Logik. Da dies Auswirkungen auf die Regler und Programme hat und diese thematisch nicht Teil der Projektgruppe SoSe2023 waren, wurde dies nicht angepasst. Die Anzeige der Messwerte ist noch fehlerhaft oder kein entsprechendes Anzeigelabel mehr in der Oberfläche vorhanden (Messwert 11-15). Hier sollte die Sinnhaftigkeit dieser Messwerte überprüft werden.<br>
Es sollte zudem überprüft werden, ob es während einer Verarbeitungsroutine der Messwerte durch eine neu eingelesene Antwort zu Fehlern kommt. In der Praxis ist dies nie aufgetreten, der Code bietet jedoch die Option. <br>
Die Schaltung der Heizung ist aktuell fehlerhaft. Der Aufruf muss als PWM-Signal übermittelt werden. Die Zuordnung der Ventile erwies sich ebenso als fehlerhaft, sodass manche Ventile nicht oder falsch angesteuert wurden. Die angepasste Ventilschaltung, insbesondere der Icon-Wechsel, bietet Potentiale zur Verbesserung und Vereinfachung. Zusätzlich müssen die geänderten Stellungsaufrufe in den Programm- und Regleraufruf eingepflegt werden. <br>
Der ResetError-Button sowie der Notaus-Knopf haben aktuell noch keine Funktion. Außerdem wurde die Funktionen zum Durchrollieren der Antworten [85] entfernt, da die neue MCU nur eine Statuszeile je Platine und eine allgemeine besitzt.  <br>
Aufgrund der Zerstörung der Platinen, bedarf es einer ausführlicheren Übergabe, sodass das erstellte Reinigungsprogramm aus Zeitmangel nicht implementiert wurde. Dieses muss eingefügt und nochmals getestet werden. Aus denselben Gründen wurde ein automatischer Kaffee- und Teewasserbezug nicht realisiert. Diese Bezüge werden jedoch ähnlich dem Reinigungsprogramm ablaufen, womit eine Orientierung daran möglich ist.


                          app.Y01.Icon = '2WegeGeschlossen.png'; % Ändern des Bildes im Reiter "manueller Modus" zu geschlossen
                          app.flag_Y01 = 0;                      % Ändern der Statusinformation, wie das Ventil steht
                    end
                else


                      if ismember('Y01', varargin)
= Melina Scherf, 23.07.2023, Ventilschaltung automatischer Wechsel =
                        % wenn der String "Y01" der Funktion übergeben wurde (in varargin enthalten ist)
Es soll bei der Magnetventilschaltung in MATLAB® verhindert werden, dass mit jedem Funktionsaufruf der Icon-Wechsel angelegt werden muss und bei zukünftigen automatischen Programmabläufen die Schaltung der Ventile auf der Oberfläche zu beobachten ist. Dazu wurde der Icon-Wechsel der Funktion zur Ventilschaltung hinzugefügt. Im manuellen Modus wird anhand der Statusflag das Bild gewechselt. Im automatischen Modus werden alle Icons der in der Übergabe enthaltenden Ventile zur geöffneten Position gewechselt, alle anderen zur geschlossenen. Somit wird auch der Aufruf vereinfacht und ist im automatischen und manuellen Modus identisch.
                        % hierbei muss die Funktion ismember benutzt werden, da es sich bei varargin um ein cell array handelt
  app.ventile_stellen("'Yxx'");
   
                          app.Y01.Icon = '2WegeRechts.png';      % Ändern des Bildes im Reiter manueller Moduszu geöffnet (da im Funktionsaufruf enthalten)
                          app.flag_Y01 = 1;                      % Ändern der Statusinformation über Ventilstellung
                      else
                          app.Y01.Icon = '2WegeGeschlossen.png'; % Ändern des Bildes im Reiter manueller Moduszu geschlossen (da nicht im Funktionsaufruf enthalten)
                          app.flag_Y01 = 0;                     % Ändern der Statusinformation über Ventilstellung
                      end
                end


Button pushed:
app.ventile_stellen("'Y01'"); % Aufruf der Funktion zur Schließung/Öffnung des Ventils


= Melina Scherf, 14.06.2023, Ventilschaltung (Python) =
= Melina Scherf, 14.06.2023, Ventilschaltung (Python) =
Der MicroPython-Code für die zuvor beschriebene Funktionsweise der Ventilschaltung wurde erstellt und auf der Seite zum [[Schalten Magnetventile SSR-Platine Multi-MCU]] erklärt.
Der MicroPython-Code für die Ventilschaltung ab August 2023 wurde erstellt und auf der Seite zum [[Schalten Magnetventile SSR-Platine Multi-MCU]] erklärt.
 


= Melina Scherf, 07.06.2023, Ventilschaltung (MATLAB) =
= Melina Scherf, 07.06.2023, Ventilschaltung (MATLAB) =
Um die Schaltung der Aktoren übersichtlicher zu gestalten, sollen direkt in den Programmen (automatischer Modus) oder bei Wertänderung (manueller Modus) Funktionen aufgerufen werden. <br>
Um die Schaltung der Aktoren übersichtlicher zu gestalten, sollen direkt in den Programmen (automatischer Modus) oder bei Wertänderung (manueller Modus) Funktionen aufgerufen werden. <br>
Die Schaltung der Ventile erfolgt aktuell zunächst über die Festlegung der Sollwerte:
Somit wurde je eine Funktion für die Heizung, Pumpe und das Dosierventil erstellt, die zukünftigen an allen Stellen – automatischer und manueller Modus - aufgerufen werden soll, die einer Stellung bedürfen. Diese Funktion sind bereits im Januar 2023 vorhanden gewesen. Anders verhält es sich mit der Ventilschaltung, diese wurde vollständig neu programmiert. <br>
Die Schaltung der Ventile erfolgte im Januar 2023 über die Festlegung der Sollwerte:
     app.ventileSollIntern=[0 1 0 1 0 0 0 0 0 0];  
     app.ventileSollIntern=[0 1 0 1 0 0 0 0 0 0];  
Dieser Vektor wird anschließend im SOLL/IST-Vergleich verarbeitet.
Dieser Vektor wird anschließend im SOLL/IST-Vergleich verarbeitet. <br>
Dies ist in der Handhabung sehr umständlich, da zu einem die Zuordnung der Ventile schwer fällt und zum anderen die Position nicht mehr zum aktuellen Stand der Maschine passt, was zukünftig verhindert werden soll. Aktuelle Schaltung: [Y01, Y03, Y04, Y05, Y13, Y06, Y07, Y08, Y09, Y00] <br>
Dies ist in der Handhabung sehr umständlich, da zu einem die Zuordnung der Ventile schwerfällt und zum anderen die Position der Ventile im Vektor nicht mehr zum aktuellen Stand der Maschine passt, was zukünftig verhindert werden soll. Aktuelle Schaltung: [Y01, Y03, Y04, Y05, Y13, Y06, Y07, Y08, Y09, Y00]  
Daher wurde die neue Funktion ventile_stellen() programmiert, die eine unbekannte Anzahl an Eingaben verarbeiten kann. Ein möglicher Aufruf könnte wie folgt aussehen:
Daher wurde die neue Funktion ventile_stellen() programmiert, die in der Lage ist eine unbekannte Anzahl an Eingaben zu verarbeiten. Die doppelten Anführungszeichen werden benötigt, da bei der Übertragung an Python eines gelöscht wird (Indikator String).
    app.ventile_stellen("Y01", "Y13", "Y07");
    Aufruf: app.ventile_stellen("‘Y01‘", "‘Y13‘", "‘Y07‘");
Die Eingaben werden in der Funktion in dem Vektor zu_schaltende_ventile gespeichert.
Im automatischen Modus werden alle Ventile, die in dieser Funktion genannt werden, geöffnet, alle nicht genannten geschlossen. Eine Anwendung dieser Funktionsweise auf den manuellen Modus ist jedoch nicht möglich, da sonst bei Schaltung eines Ventils (Drücken auf Ventilicon) zeitgleich alle anderen Ventile mitgeschaltet werden würden. Die Funktion ist jedoch in der Lage zwischen automatischem und manuellem Modus zu unterscheiden. Im manuellen Modus werden dahingehend die übergebenen geschlossenen Ventile geöffnet und andersherum. Theoretisch würde es im manuellen Modus reichen nur einen Wert zu übergeben, denn manuell ist es bisher nur möglich, ein Ventil gleichzeitig zu schalten. Um aber zukünftigen Komplikationen aus dem Weg zu gehen und für zukünftige Bearbeiter eine bessere Übersichtlichkeit und Anpassungsmöglichkeit zu garantieren, wurde sich für dafür entschieden, einen Mehrfach-Aufruf trotzdem anzulegen.
Im automatischen Modus werden nun alle Ventile, die in dieser Funktion genannt werden, auf 1 gesetzt, alle nicht genannten auf 0. Dazu werden die zu schaltenden Ventile mit der Funktion ventile_schalten_automatisch() an die SSR-Platine übergeben:
    writeline(app.ssr_platine, sprintf(['ventile_schalten_automatisch(', repmat('%s, ', 1, numel(app.zu_schaltende_ventile)-1), '%s)'], app.zu_schaltende_ventile));
Im automatischen Modus werden nur die Werte der eingegebenen Ventile invertiert (ON -> OFF oder OFF -> ON) und dafür in der Funktion ventile_schalten_manuell() übergeben:
    writeline(app.ssr_platine, sprintf(['ventile_schalten_manuell(', repmat('%s, ', 1, numel(app.zu_schaltende_ventile)-1), '%s)'], app.zu_schaltende_ventile));
Theoretisch würde es im manuellen Modus reichen nur einen Wert zu übergeben, denn manuell kann bisher nur ein Ventil gleichzeitig geschaltet werden. Um aber zukünftigen Komplikationen aus dem Weg zu gehen und für zukünftige Bearbeiter eine bessere Übersichtlichkeit und Anpassungsmöglichkeit zu garantieren, wurde sich für den Vektor entschieden.
 
Für Dosierventil, Pumpe und Heizung sollen die bestehenden Funktionen zusammengelegt werden, sodass die Visualisierung und Stellung der Aktoren in je einer Funktion erfolgt. (noch zu machen)
 
 
            app.SSR_Status.Text = char('def_ventile = ventile_schalten_neu.init()'); % Anzeige im Statusfeld der SSR
            writeline(app.ssr_platine, 'def_ventile = ventile_schalten_neu.init()'); % Abspeichern der Ventilnamen mit zugehörigem Pin
 
            % Es ist eine Unterscheidung des Schaltens der Ventile aus dem automtischen und aus dem manuellen Modus vorzunehmen.
            % Im automatischen Modus werden alle im Funktionsaufruf genannten Ventile geöffnet und alle nicht genannten geschlossen.
            % Dies kann jedoch nicht auf den manuellen Modus übertragen werden, da dort, durch Klicken auf ein Bild in der Graphikoberfläche, nur der Wert EINES Ventiles geändert werden soll
 
            if app.manualOverwriteAktiv == 1
                % wenn der Manual Overwrite aktiviert ist
 
                  app.SSR_Status.Text = sprintf(['ventile_schalten_neu.ventile_schalten_manuell(def_ventile, ', repmat('%s, ', 1, numel(varargin{:})-1), '%s)'], varargin{:});      % Anzeige im Statusfeld SSR
                  writeline(app.ssr_platine, sprintf(['ventile_schalten_neu.ventile_schalten_manuell(def_ventile, ', repmat('%s, ', 1, numel(varargin{:})-1), '%s)'], varargin{:})); % Befehl an MicroPython
                    % Aussehen des Befehls an Python: ventile_schalten_neu.ventile_schalten_manuell(def_ventile, xxx)
                    % An der Stelle xxx werden alle der Funktion übergebenenen Ventile als String (in '' mit Komma abgetrennt) an MicroPython geschickt
                    % Da nicht festgelegt wurde, wieviele Ventile übergeben werden, wird mittels der repmat Funktion die unbekannte Anzahl eingefügt.
                    % Für weitere, ausführlichere Erklärungen der Funktion siehe Wiki: http://www.institut-fuer-kaffeetechnologie.de/Wiki/index.php?title=Adaption_an_Multi-MCU_-_Neuprogrammierung_MATLAB%C2%AE_GUI
 
                % Das Ändern der Statusinformation über die Stellung des Ventils sowie die Bildänderung im Reiter Manueller Modus erfolgen bereits in der Callback-Funktion
 
 
            else
                % Wenn der Manual Overwrite nicht aktiv ist
 
                app.SSR_Status.Text = sprintf(['ventile_schalten_neu.ventile_schalten_manuell(def_ventile, ', repmat('%s, ', 1, numel(varargin{:})-1), '%s)'], varargin{:});          % Anzeige in Statusfeld SSR
                writeline(app.ssr_platine, sprintf(['ventile_schalten_neu.ventile_schalten_automatisch(def_ventile, ', repmat('%s, ', 1, numel(varargin{:})-1), '%s)'], varargin{:})); % Befehl an Python
                 
                % Ändern der Statusinformation über die Stellung des Ventils sowie Bildänderung im Reiter manueller Modus
                % Somit kann bei automatischen Programmabläufen optisch die Schaltung der Ventile auf der Oberfläche nachvollzogen werden
            end


= Madita vom Stein, 06.06.2023 =
= Madita vom Stein, 06.06.2023 =
'''Beschreibung Prozessbild manueller Modus der GUI'''<br><br>
'''Beschreibung Prozessbild manueller Modus der GUI'''<br><br>
[[Datei:20230512 Prozessbild manueller Modus GUI.png|thumb|1000px|gerahmt|zentriert|alternativtext=Prozessbild manueller Modus der GUI]]
[[Datei:20230512 Prozessbild manueller Modus GUI.png|thumb|1000px|gerahmt|zentriert|Abbildung 5: Prozessbild manueller Modus der GUI]]
Auf dem Prozessbild sind die wesentlichen Zusammenhänge der im Mai 2023 aktuellen Labormaschine dargestellt. <br><br>
Auf dem Prozessbild sind die wesentlichen Zusammenhänge der im Mai 2023 aktuellen Labormaschine dargestellt. <br><br>
Das Magnetventil Y01 ist das Ventil für den Festwasseranschluss. <br>
Das Magnetventil Y01 ist das Ventil für den Festwasseranschluss. <br>
Zeile 122: Zeile 74:
Der Dampfhahn ist als 3/2-Wege-Magnetventil Y13 ausgeführt. Im nicht-geschalteten Zustand wird das Kondenswasser zwischen Dampfhahn und -lanze in die Abtropfschale abgeleitet. <br>
Der Dampfhahn ist als 3/2-Wege-Magnetventil Y13 ausgeführt. Im nicht-geschalteten Zustand wird das Kondenswasser zwischen Dampfhahn und -lanze in die Abtropfschale abgeleitet. <br>
Der Stahlboiler der Labormaschine weist 3,6 Liter Gesamtvolumen auf und wird auf 2,4 Liter befüllt. Mit einem 1800 Watt leistungsgeregeltem Heizelement wurden 12 Minuten Aufheizzeit ermittelt. <br>
Der Stahlboiler der Labormaschine weist 3,6 Liter Gesamtvolumen auf und wird auf 2,4 Liter befüllt. Mit einem 1800 Watt leistungsgeregeltem Heizelement wurden 12 Minuten Aufheizzeit ermittelt. <br>


= Melina Scherf, 26.05.2023, Ventilschaltung =
= Melina Scherf, 26.05.2023, Ventilschaltung =
Die Schaltung der Ventile wurde zusätzlich angepasst. Zuvor wurde eine Abfrage der IST- und SOLL-Stellwerte der Ventile durchgeführt und bei Abweichungen ein Vektor an die STM32 geschickt, die die Ventile bei 1 auf ON und bei 0 auf OFF geschaltet hat. <br>
Die Schaltung der Ventile im automatischen Modus wurde angepasst. Im Januar 2023 wurde eine Abfrage der IST- und SOLL-Stellwerte der Ventile durchgeführt und bei detektierten Abweichungen ein Vektor an die STM32 geschickt, die die Ventile entsprechend geschaltet hat.  
Der Vergleich bleibt vorläufig bestehen, nun wird aber bei abweichenden Werten direkt eine Funktion "Yxx__on" bzw. "Yxx_off" aufgerufen. In dieser erfolgt die Ansprache der Ventile auf der Multi-MCU über einen writeline-Befehl, der die Funktionen ventil_on(pin) bzw. ventil_off(pin) auf den Platinen aufruft. Die Definition der Pins wurde zuvor in der Initialisierung in einem Vektor gespeichert, dessen Werte über Indizes händisch zugeordnet und aufgerufen werden:
Der Vergleich bleibt vorläufig bestehen, welcher bei abweichenden Werten einer neu eingeführten Statusflag ab August 2023 eine Funktion "Yxx__on" bzw. "Yxx_off" direkt aufgerufen. Die Zuordnung der Pins zu den jeweiligen Ventilen erfolgt bereits in der Initialisierungsfunktion der SSR.
    writeline(app.ssr_platine, 'a = ventil_schalten.init()'); (Initialisierung)
Je nach Stellung des Ventils wird das Icon in der Oberfläche im Reiter „manueller Modus“ angepasst.  
    writeline(app.ssr_platine, 'ventil_schalten.ventil_on(a[0])'); (Funktionsaufruf auf MCU)
Je nach Stellung des Ventils wird das Icon in der Oberfläche angepasst. <br>
Beachtet werden muss jedoch, dass bisher die ON-Funktion die Ventile OFF schaltet und umgekehrt. Dieses Problem soll zukünftig über eine Neuprogrammierung der Ventilschaltung behoben werden.
 
        function Y01_off(app)
            app.SSR_Status.Text = char('ventil_schalten.ventil_off(a[0])'); % Anzeige des Befehls in der Oberfläche im Statusfeld der SSR           
            writeline(app.ssr_platine, 'ventil_schalten.ventil_off(a[0])'); % Schließen des Ventil Y01 mit dem Pin an 1. Stelle des Vektors a (in ssr_initalisieren() definiert)
        end
 
        function Y01_on(app)
            app.SSR_Status.Text = char('ventil_schalten.ventil_on(a[0])'); % Anzeige des Befehls in der Oberfläche im Statusfeld der SSR           
            writeline(app.ssr_platine, 'ventil_schalten.ventil_on(a[0])'); % Öffnen des Ventil Y01 mit dem Pin an 1. Stelle des Vektors a (in ssr_initalisieren() definiert)
           
        end
 
SOLL-IST
            if ~app.ventileIstIntern(1) == app.ventileSollIntern(1)
                % wenn Soll-Ist-Wert abweichend
 
                if app.ventileSollIntern(1)
                    % wenn Ventil offen sein sollte
 
                    app.ventileIstIntern(1) = 1;      % Speichern des neuen Istzustandes
                    app.Y01_on();                    % Funktion zum Öffnen des Ventils
                    app.Y01.Icon = '2WegeRechts.png'; % Ändern des Bildes der Ventilstellung im Reiter "manueller Modus"
                    app.flag_Y01 = 1;                % Statusindikator auf offen               
                   
                else
                    % wenn Ventil geschlossen sein sollte
 
                    app.ventileIstIntern(1) = 0;          % Speichern des neuen Istzustandes
                    app.Y01_off();                        % Funktion zum Schließen des Ventils
                    app.Y01.Icon = '2WegeGeschlossen.png'; % Ändern des Bildes der Ventilstellung im Reiter "manueller Modus"
                    app.flag_Y01 = 0;                      % Statusindikator auf geschlossen
                end
     
            end
 
= Melina Scherf, 25.05.2023, connected() =
 
 
 
connected()
 
Die neu erstellten Platinen und die geschriebene Software wurden erstmals zusammengeführt. Die Initialisierung erfolgt in den meisten Fällen problemlos. Um die Fehlerfälle zu beseitigen wurde in die Initialisierungsfunktion eine Abfrage nach dem Verbindungsstatus eingefügt. Hierbei wird am Ende der Initialisierung die connected()-Funktion aufgerufen, die lediglich das Wort "connected" bei Ausführung rücksendet. Wird diese Wort von der GUI erkannt wird der Verbindungsstatus auf 1 gesetzt. Sollte diese Antwort nicht erkannt werden, wird die Initialisierungsroutine nochmals abgerufen. <br>
  if app.ssr_connected == 0
Initalisierungszeug
                        writeline(app.ssr_platine, 'import verbunden');
                        writeline(app.ssr_platine, 'verbunden.connected()');
                        if contains(app.zeile_char, 'connected')
                            app.ssr_connected = 1;
                            app.Verbinden_Button.Enable = 0;
                            app.SSR_Status.Text = ('SSR-Platine Initialiserung abgeschlossen');
                           
                        end
end
 
-> wieder rausgenommen, durch zukünftige Projektgruppen zu bearbeiten (Frage ob nötig)
 
= Melina Scherf, 24.05.2023, Initalisierung BAS, SSR, MWP; Aktorenstellung: Pumpe, Heizung, Dosierventil =
Erstmalige Zusammenführung
 
 
 
Dazu wurden die Initialisierungsfunktionen der beiden Platinen um die Schrittmotorinitialisierung erweitert wurden, die jedoch zu großen Teilen aus der bestehenden GUI übernommen wurden. <br>
Es wurden zudem kleinere Anpassungen in den writeline-befehlen vorgenommen, diese betreffen jedoch nur Groß- und Kleinschreibung.
 
SSR
function ssr_initalisieren(app, ~,~)
            % Initalisierungsfunktion der SSR-Platine
            % Import aller benötigten Pythonprogamme + mechanische Initalisierung
            % (aufgerufen aus init_mcus())
         
              % SCHRITTMOTOREN
           
                    app.zeile_char_ssr = char('import Schrittmotor');          % Anzeige des Befehls in der GUI-Oberfläche (Statusfeld SSR)
                    writeline(app.ssr_platine, 'import Schrittmotor');          % Import des Schrittmotor-Python-Programmes
                       
                    app.zeile_char_ssr = char('seq = Schrittmotor.sequenz()');  % Anzeige des Befehls in der GUI-Oberfläche
                    writeline(app.ssr_platine, 'seq = Schrittmotor.sequenz()'); % Steuersequenz für die Schrittmotoren festlegen
 
 
                  %Dosierventil
 
                    app.zeile_char_ssr = char('pins = Schrittmotor.Dosierventil_Pins()'); 
                    writeline(app.ssr_platine, 'pins = Schrittmotor.Dosierventil_Pins()'); % Festlegung der benötigten Pins des Dosierventils
   
                    app.zeile_char_ssr = char('dosierventil = Schrittmotor.setup(pins)');
                    writeline(app.ssr_platine, 'dosierventil = Schrittmotor.setup(pins)'); % Festlegung der Ansprache des Dosierventiles
   
                    app.zeile_char_ssr = char('dosierventil_pos = -1');
                    writeline(app.ssr_platine, 'dosierventil_pos = -1'); % Initialisierungsposition in der Schrittmotorsequenz
 
 
 
                  %mechanische Initialisierung
 
                    writeline(app.ssr_platine, 'dosierventil_pos = Schrittmotor.forwardStep(800, dosierventil_pos, seq, dosierventil, "endDosier")');
                    pause(1);
                    writeline(app.ssr_platine, 'dosierventil_pos = Schrittmotor.backwardStep(800, dosierventil_pos, seq, dosierventil, "endDosier")');
                    pause(1);
                    % Befehle zum Vorwärts- und Rückwärtsstellen des Dosierventils
                    % in diesem Fall 800 vorwärts sowie 800 rückwärts Halbschritte
                    % Rückgabe des Signalwortes "endDosier" nach Abschluss des Vorganges
 
              % VENTILE
                   
                  % ALT (getestet)
                    writeline(app.ssr_platine, 'import ventil_schalten');    % Import des Python-Programmes
                    writeline(app.ssr_platine, 'a = ventil_schalten.init()'); % Speicherung eines Vektors mit den Pins der Ventile
                    app.Y01_off();                                            % Aufruf der Funktionen zur Schließung aller Ventile -> sicherer Zustand
                    app.Y03_off();
                    app.Y04_off();
                    app.Y05_off();
                    app.Y13_off();
                    app.Y06_off();
                    app.Y07_off();
                    app.Y08_off();
                    app.Y09_off();
 
 
BAS
 
            % SCHRITTMOTOREN
 
                app.zeile_char_bas = char('import Schrittmotor');          % Anzeige des Befehls in der GUI-Oberfläche (Statusfeld BAS)
                writeline(app.bas_platine, 'import Schrittmotor');          % Import des Schrittmotor-Python-Programmes 
 
                app.zeile_char_bas = char('seq = Schrittmotor.sequenz()');  % Anzeige des Befehls in der GUI-Oberfläche
                writeline(app.bas_platine, 'seq = Schrittmotor.sequenz()'); % Steuersequenz für die Schrittmotoren festlegen


= Melina Scherf, 24.05.2023, Initialisierung BAS, SSR, MWP; Aktorenstellung: Pumpe, Heizung, Dosierventil =
[[Datei:Initialisierung.png|thumb|500px|rechts|Abbildung 4]]
Es erfolgte die erstmalige Zusammenführung der Elektronik mit der Software. <br>
'''Initialisierung''' <br>
Im Zuge dessen wurden die Initialisierungen auf den neu geschriebenen Python-Code angepasst.
Auf der SSR werden zusätzlich die Heizung und Ventile initialisiert. Letztere werden alle geschlossen, um einen gesicherten Zustand herzustellen.
Die Initialisierung der Pumpe findet auf der BAS statt.
Die zuvor verwendete MWP-Initialisierung der simulierten Messwerte wurde zum Import der realen Messwerterfassung geändert. [Abb. 4] <br>
'''Aktorenstellung''' <br>
Die Schaltung der Aktoren erfolgt durch writeline-Befehle, welche von MATLAB® an Python geschickt werden. Diese wurden im Code auf den aktuellen Python-Code angepasst und an die jeweils vorgesehenen Platinen gesendet. <br>
Bei der Einarbeitung ist jedoch aufgefallen, dass die Stellung der Aktoren einiges an Einarbeitungszeit bedarf, welche durch Vereinfachung verkürzt werden soll. Die Stellung erfolgte Stand Januar 2023 im manuellen sowie automatischen Modus über eine Änderung der Soll-Wert. Am Ende des gerade ablaufenden Programmes wurde ein Soll-Ist-Vergleich aufgerufen, welcher alle Aktoren bei mindestens einer festgestellten Abweichung stellt. [85]  <br>
Um einen unübersichtlichen, großen Befehl zur Stellung aller Aktoren zu vermeiden, wurde der Soll-Ist-Vergleich im automatischen Modus beibehalten, jedoch wird bei festgestellter Abweichung eines Aktors dieser sofort gestellt. Der Vergleich wird vorerst beibehalten, da ein Direkt-Aufruf in den Programmen viele Konsequenzen nach sich ziehen würde, die in der Praxis getestet werden müssen. Da der Schwerpunkt dieser Projektarbeit zunächst auf der Implementierung der Multi-MCU lag, bleibt dies ein offenes ToDo für zukünftige Projektgruppen.  <br>
Im manuellen Modus wurde jedoch direkt in die Callbacks bei Wertänderung die Neustellung einprogrammiert und erfolgt Stand August 2023 nicht mehr über einen Soll-Ist-Vergleich.


                %Brühgruppendrossel
= Melina Scherf, 22.05.2023, neue GUI =
                app.zeile_char_bas = char('pins = Schrittmotor.Bruehgruppendrossel_Pins()');
                writeline(app.bas_platine, 'pins = Schrittmotor.Bruehgruppendrossel_Pins()'); % Festlegung der benötigten Pins der Brühgruppendrossel


                app.zeile_char_bas = char('drossel = Schrittmotor.setup(pins)');         
[[Datei:Schalter Einblendung.png|thumb|500px|rechts|Abbildung 3: Flussdiagramm - Bedienbarkeit der Schalter im Reiter "Manueller Modus"]]
                writeline(app.bas_platine, 'drossel = Schrittmotor.setup(pins)'); % Festlegung der Ansprache des Dosierventiles     
Der Programmcode wurde in die von Madita vom Stein erstellte GUI importiert. <br>


                app.zeile_char_bas = char('drossel_pos = -1');
Sobald der Bediener die App startet, werden im Hintergrund alle nötigen Kalibrierkurven und die Eingaben im Reiter „Start“ vor letzter Schließung der App geladen. Im Reiter „manueller Modus“ werden für alle Ventile die Start-Icons im Zustand „geschlossen“ eingefügt, sodass die Stellung der Ventile graphisch angezeigt wird. Es wurde bei Mausklick auf das Bild im Reiter „Manueller Modus“ im manuellen Modus der Wechsel des Icons und die Negierung (Umkehrung) der Stellung des Ventils realisiert, welches durch eine Flag detektiert wird. <br>
                writeline(app.bas_platine, 'drossel_pos = -1');  % Initialisierungsposition in der Schrittmotorsequenz
Zudem werden die Schalter im Reiter „Manueller Modus“ ausgegraut und sind somit zu diesem Zeitpunkt nicht bedienbar. Dies garantiert, dass keine Funktionen abgerufen werden können, die entweder noch nicht initialisiert sind oder überwacht werden müssen.
Nach abgeschlossener Initialisierung werden die Knöpfe im Reiter „manueller Modus“ in der GUI nacheinander sichtbar und bedienbar geschaltet, sobald es die sichere Bedienung der Maschine zulässt. [Abb. 3] <br>
Bei Beendigung der App wird die in der Datensicherung erwähnte Datei „last_data“ erstellt, welche die editierbaren Eingaben der Oberfläche enthält, die bei Neustart der App geladen werden. 
<br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br>


                %Bypass
                app.zeile_char_bas = char('pins = Schrittmotor.Bypass_Pins()');
                writeline(app.bas_platine, 'pins = Schrittmotor.Bypass_Pins()');  % Festlegung der benötigten Pins des Bypasses
                app.zeile_char_bas = char('Bypass = Schrittmotor.setup(pins)');
                writeline(app.bas_platine, 'Bypass = Schrittmotor.setup(pins)');  % Festlegung der Ansprache des Bypasses
                app.zeile_char_bas = char('Bypass_pos = -1');
                writeline(app.bas_platine, 'Bypass_pos = -1');  % Initialisierungsposition in der Schrittmotorsequenz
                %mechanische Initialisierung
                writeline(app.bas_platine, 'drossel_pos = Schrittmotor.forwardStep(800, drossel_pos, seq, drossel, endDrossel)');
                pause(1);
                writeline(app.bas_platine, 'drossel_pos = Schrittmotor.backwardStep(800, drossel_pos, seq, drossel, endDrossel)');
                pause(1);
                writeline(app.bas_platine, 'Bypass_pos = Schrittmotor.forwardStep(800, Bypass_pos, seq, Bypass, "endBypass")');
                pause(1);
                writeline(app.bas_platine, 'Bypass_pos = Schrittmotor.backwardStep(800, Bypass_pos, seq, Bypass, "endBypass")');
                pause(1);
              % Befehle zum Vorwärts- und Rückwärtsstellen des Bypasses/ der Brühgruppedrossel
                    % in diesem Fall 800 vorwärts sowie 800 rückwärts Halbschritte
                    % Rückgabe des Signalwortes "endDrossel" bzw. "endBypass" nach Abschluss des Vorganges
           
            %PUMPE
                app.zeile_char_bas = char('import Pumpensteuerung');
                writeline(app.bas_platine, 'import Pumpensteuerung'); %Import des Python-Programms zur Pumpensteuerung
Aktorenstellung Pumpe, Heizung, Dosierventil
Die Funktionen zum Stellen der Pumpe, Heizung und Dosierventil wurden angepasst und werden wie zuvor über den SOLL/IST-Vergleich getriggert. <br>
* Pumpe: Der Pumpe wird lediglich der Sollwert übergeben:
    writeline(app.bas_platine, sprintf('pumpe(%d)', app.pumpeSollIntern));
* Heizung: Ein- und Ausschalten ähnlich Ventilschaltung: -> FALSCH
    writeline(app.ssr_platine, 'ventil_on(3)'); (Einschalten)
    writeline(app.ssr_platine, 'ventil_off(4)'); (Ausschalten)
* Dosierventil:
    writeline(app.ssr_platine, ['dosierventil_pos = schrittmotor.forwardStep(' num2str(dosierventilStellwert*2) ', dosierventil_pos, seq, dosierventil, "endDosier")']); (Vorwärts)
    writeline(app.ssr_platine, ['dosierventil_pos = schrittmotor.backwardStep(' num2str(dosierventilStellwert*(-2)) ', dosierventil_pos, seq, dosierventil, "endDosier")']); (Rückwärts)
MWP
            app.zeile_char_mwp = char('import Messung');  % Anzeige des Befehls in der GUI-Oberfläche (Statusfeld MWP)   
            writeline(app.mwp_platine, 'import Messung');  % Import des Messung-Python-Programmes


= Melina Scherf, 20.05.2023, Verarbeitung BAS, SSR =
= Melina Scherf, 20.05.2023, Verarbeitung BAS, SSR =
[[Datei:Verarbeitungsfunktionen.png|thumb|500px|rechts|Abbildung 2: Verarbeitungsfunktionen der Platinen]]
Die Bestellung der Platinen erfolgte schneller als geplant, somit wurde statt des vorläufigen Konzeptes mit vier Platinen (SSR, BAS, MWP, RPI) bereits im Sommersemester 2023 das geplante Konzept mit drei Platinen (SSR, BAS, MWP) eingeführt.
Die RPI-Platine entfällt, sodass deren Funktionen zur Schrittmotorsteuerung auf die BAS- und SSR-Platine verteilt werden.
Die RPI-Platine entfällt, sodass deren Funktionen zur Schrittmotorsteuerung auf die BAS- und SSR-Platine verteilt werden.
* Dosierventil -> SSR
In der gesendeten Antwort wird nach den Signalwörtern der Schrittmotoren („endDrossel“, „endBypass“, „endDosier“) gesucht, welche am Ende einer Schrittmotor-Stellung übermittelt werden. Werden diese erkannt, werden die Schrittmotoren stromlos geschaltet.
* Drossel -> BAS
<br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br>
* Bypass -> BAS
 
Verarbeitungsfunktion BAS
            zeile = readline(app.bas_platine);        % Einlesen der Antwort der BAS in lokale Variable
            app.zeile_char_bas = char(zeile);        % Abspeicherung der Antwort in globale Variable
            app.BAS_Status.Text = app.zeile_char_bas; % Anzeige der Antwort in Statusfeld der BAS
           
            %SCHRITTMOTOREN
           
                    if contains(app.zeile_char_bas,'endDrossel')
                        % wenn diese Antwort das Signalwort "endDrossel" enthält
                        % dieses wird nach Beendigung des Schrittmotor-Stellens gesendet 
       
                        writeline(app.bas_platine, 'Schrittmotor.setStepperOff(drossel)'); % Stromlos-Schaltung des Schrittmotors
                        app.zeile_char_bas = char('Schrittmotor.setStepperOff(drossel)');
                    end
       
                    if contains(app.zeile_char_bas,'endBypass')
                        % wenn diese Antwort das Signalwort "endBypass" enthält
                        % dieses wird nach Beendigung des Schrittmotor-Stellens gesendet
       
                        writeline(app.bas_platine, 'Schrittmotor.setStepperOff(Bypass)'); % Stromlos-Schaltung des Schrittmotors
                        app.zeile_char_ssr = char('Schrittmotor.setStepperOff(Bypass)');
                    end
 
Verarbeitungsfunktion SSR
            zeile = readline(app.ssr_platine);        % Einlesen der Antwort der SSR in lokale Variable
            app.zeile_char_ssr = char(zeile);        % Abspeicherung der Antwort in globale Variable
            app.SSR_Status.Text = app.zeile_char_ssr; % Anzeige der Antwort in Statusfeld der SSR
           
 
            if contains(app.zeile_char_ssr,'endDosier')
                % wenn diese Antwort das Signalwort "endDosier" enthält
                % dieses wird nach Beendigung des Schrittmotor-Stellens gesendet
 
                writeline(app.ssr_platine, 'Schrittmotor.setStepperOff(dosierventil)'); % Stromlos-Schaltung des Schrittmotors
                app.zeile_char_ssr = char('Schrittmotor.setStepperOff(dosierventil)');
            end
 
 
= Melina Scherf, 18.05.2023, Verarbeitungsfunktion BAS (Messwerte) =
Verarbeitungsfunktion BAS Messwerte -> Initalisierung vorwerst über simulierte Messwerte
 
Die simulierte Messwerterfassung wurde in gleicher Weise wie für die MWP für die BAS-Platine erstellt. Beide Platinen-Verarbeitungsfunktionen greifen dabei auf dieselbe Messwert-Verarbeitungsfunktion zu, speichern die Messwerte aber zunächst in unterschiedlichen lokalen Vektoren. Hinzu kommt, dass einkommende Messwerte der BAS-Platine zusätzlich an einem "F!" zu erkennen sind.  <br>
Um dies in der Praxis zu testen wurde je die letzte Zeile des von Armin Rohnen erstellten [[Messwerte erfassen Multi-MCU|Programm zur simulierten Messdatenerfassung]] angepasst: <br>
MWP: <br>
  print('M!',T_Boiler, T_Eingang, T_Mischer, P_Boiler, Leitwert, T_Bruehgruppe, P_Bruehgruppe)
 
BAS: <br>
  print('F!', Fuellstand , Durchfluss, Pulse)
 
= Melina Scherf, 16.05.2023, Messwerte anzeigen =
                aktuelle_uhrzeit = datestr(now,'HH:MM:SS.FFF'); % Aktuelle Uhrzeit ermitteln
                uhrzeit_sekunden = str2num(aktuelle_uhrzeit(1:2))*3600 + str2num(aktuelle_uhrzeit(4:5))*60 + str2num(aktuelle_uhrzeit(7:end)); % Umrechnung in Sekunden
 
                if app.letzte_anzeige == 0 || (uhrzeit_sekunden - app.letzte_anzeige) > 1
                    % wenn es sich um die erste Anzeige handelt (letzte_anzeige == 0)
                    % oder die letzte Anzeigenaktualisierung länger als 1 Sekunde her ist
                   
                    %Anzeige der Messwerte an der zugehörigen Stelle auf der GUI-Oberfläche
                    % 1. Temperatur Boiler
                        app.Boilertemperatur.Text = num2str(round(app.messwert_puffer(end,1),1));
                           
                    % 2. Frischwassertemperatur
                        app.Frischwassertemperatur.Text = num2str(round(app.messwert_puffer(end,2),1));
 
                    % 3. Mischwassertemp
                        app.Mischwassertemperatur.Text = num2str(round(app.messwert_puffer(end,3),2));
     
                    % 4. Boilerdruck
                        app.Boilerdruck.Text = num2str(round(app.messwert_puffer(end,4)));
   
                    % 5. Wasserleitfähigkeit
                        app.Leitungsdruck.Text = num2str(round(app.messwert_puffer(end,5),1));
   
                    % 6. Füllstand
                        app.Boilerfuellstand.Text = num2str(app.messwert_puffer(end,6));
   
                    % 7. Durchfluss
                        app.Durchflussrate.Text = num2str(round(app.messwert_puffer(end,7),2));
   
                    % 8. Pulse Flowmeter
 
   
                    % 9. Temperatur hinter der Wasserwendel/ vor der Brühgruppe
                        app.BruehgruppenTemp.Text = num2str(round(app.messwert_puffer(end,9),2));
   
                    % 10. Druck in der Brühgruppe
                        app.BruehgruppenDruck.Text = num2str(round(app.messwert_puffer(end,10)));
   
                    % 11. Pumpensteuerspannung
                       
                    % 12. Bypass-Stellung
   
                    % 13. Dosierventilstellung
   
                    % 14. Brühgruppendrossel
   
                    % 15. Heizleistung PWM
 
                    app.letzte_anzeige = uhrzeit_sekunden; % Abspeichern der letzten Anzeige zur aktuellen Uhrzeit
 
                end
 
= Melina Scherf, 15.05.2023, Datensicherung=
Datenspeicherung
So werden von der Messwertplatine sieben und von der Basisplatine drei Messwerte gesendet, die nach der festgelegten Reihenfolge (s.u.) in der GUI gespeichert werden. Um diese auch sichtbar zu machen, wurde die neu erstellte Oberfläche integriert, welche automatische jede Sekunde die aktualisierten Messwerte an den zugeordneten Positionen anzeigt. <br>
Es wurde zudem die automatische (nach vorgegebener Zeit in der Oberfläche) und die manuelle Datensicherung (per Knopfdruck) programmiert. Die Dateien enthalten den aktuellen Messwertpuffer und werden mit Zeitstempel und dem Zusatz "automatisch" oder "manuell" angelegt. Bei jedem Schließen der App wird eine Sicherung mit dem Namen "last_data" erstellt, die bei jedem Neustart geladen wird.
 
      function datensicherung(app, ~, ~)
            % Sicherung aller Messwerte und Eingaben der Oberfläche im Start-Reiter
            % automatische und manuelle Datensicherung können beide mittels dieser Funktion erfolgen
   
                app.Allgemeiner_Status.Text = char('Datensicherung gestartet'); % Anzeige im allgemeinen Statusfeld
               
                % Abspeicherung der Eingaben aus dem Start-Reiter
                meta.Datum = app.Datum.Value;
                meta.Bearbeiter = app.Bearbeiter.Value;
                meta.Messzyklus = app.Messzyklus.Value;
                meta.Bemerkung1 = app.Bemerkung1.Value;
                meta.Bemerkung2 = app.Bemerkung2.Value;
                meta.Bemerkung3 = app.Bemerkung3.Value;
                meta.Kaffeesorte = app.Kaffeesorte.Value;
                meta.Mahlgrad = app.Mahlgrad.Value;
                meta.Kaffeemenge = app.Kaffeemenge.Value;
                meta.Tamperdruck = app.Tamperdruck.Value;
   
                % Überschriften der jeweiligen Messwerte
                meta.messpunkt(1).Value = 'Boilertemperaturwert';
                meta.messpunkt(2).Value = 'Frischwassertemperatur';
                meta.messpunkt(3).Value = 'Mischwassertemperatur';
                meta.messpunkt(4).Value = 'Boilerdruck';
                meta.messpunkt(5).Value = 'Leitfähigkeit';
                meta.messpunkt(6).Value = 'Füllstand';
                meta.messpunkt(7).Value = 'Durchfluss';
                meta.messpunkt(8).Value = 'Pulse vom Flowmeter';
                meta.messpunkt(9).Value = 'Brühgruppenwassertemperatur';
                meta.messpunkt(10).Value = 'Brühgruppendruck';
                meta.messpunkt(11).Value = 'Pumpenansteuerung';
                meta.messpunkt(12).Value = 'Pumpenbypass';
                meta.messpunkt(13).Value = 'Dosierventilstellung';
                meta.messpunkt(14).Value = 'Brühgruppendrossel';
                meta.messpunkt(15).Value = 'Heizleistung PWM';
               
                % Speicherung der Messwerte mit zugehörigem Zeitstempel
                messdaten.data = app.messwert_puffer;
                messdaten.time = app.zeitstempel_messung;
               
                % es soll unterschieden werden, ob es sich um eine manuelle oder automatische Datensicherung handelt (Kennzeichnung im Dateinamen)
                % dazu wurden die Variablen automatische_datensicherung und manuelle_datensicherung angelegt, die bei den Aurufen der Funktion auf 1 gesetzt werden
                % sollte weder eine automatische noch manuelle Datensicherung erwünscht sein, die Funkion aber aufgerufen wird, handelt es sich um die Sicherung bei
                % Schließung der App
         
                if app.automatische_datensicherung == 1
                    % wenn es sich um eine automatische Datensicherung handelt
 
                    app.automatische_datensicherung = 0;          % Rücksetzen auf 0
                    t = char(datetime);                          % Abspeichern der aktuellen Uhrzeit             
                    datei = [t(8:11) t(4:6) t(1:2) '_Time' t(13:14) '.' t(16:17) '.' t(19:20) '_automatisch']; %Festlegen des Dateinamens als "YYYYMMDD_Timehh.mm.ss_automatisch"
                                                                                                              % Achtung im Dateinamen kein ':' möglich!
                    folder = 'C:\Users\Rohnen\Desktop\Labormaschine\application\Test GUI Multi-MCU\MCU_Test\20230525\Datensicherung'; % Festlegen des Speicherortes
                    save_data = fullfile(folder, [datei '.mat']); % Erstellung des vollständigen Speicherpfades (inklusive Dateiname)
                    save([save_data], 'meta', 'messdaten');      % Abspeicherung der Eingaben und Messwerte an erstelltem Speicherort
                elseif app.manuelle_datensicherung == 1
                    % wenn es sich um eine manuelle Datensicherung handelt
 
                    app.manuelle_datensicherung = 0;              % Rücksetzen auf 0
                    t = char(datetime);                          % Abspeichern der aktuellen Uhrzeit
                    datei = [t(8:11) t(4:6) t(1:2) '_Time' t(13:14) '.' t(16:17) '.' t(19:20) '_manuell']; %Festlegen des Dateinamens als "YYYYMMDD_Timehh.mm.ss_manuell"
                                                                                                          %Achtung im Dateinamen kein ':' möglich!                   
                    folder = 'C:\Users\Rohnen\Desktop\Labormaschine\application\Test GUI Multi-MCU\MCU_Test\20230525\Datensicherung'; %Festlegen des Speicherortes
                    save_data = fullfile(folder, [datei '.mat']); % Erstellung des vollständigen Speicherpfades (inklusive Dateiname)
                    save([save_data], 'meta', 'messdaten');      % Abspeicherung der Eingaben und Messwerte an erstelltem Speicherort
 
 
                else
                    % Schließung der App
                    % Die Eingaben im Reiter Start, die hier gespeichert wurden, werden beim nächsten Start der App wieder geladen
 
                    folder = 'C:\Users\Rohnen\Desktop\Labormaschine\application\Test GUI Multi-MCU\MCU_Test\20230525\last_data'; % Festlegen des Speicherortes
                    datei = ['last_data'];                        % Festlegen des Dateinamens
                    save_data = fullfile(folder, [datei '.mat']); % Erstellung des vollständigen Speicherpfades (inklusive Dateiname)
                    save([save_data], 'meta', 'messdaten');      % Abspeicherung der Eingaben und Messwerte an erstelltem Speicherort
 
 
                end
               
                app.Allgemeiner_Status.Text = char('Datensicherung abgeschlossen'); % Anzeige im allgemeinen Statusfeld
 
= Melina Scherf, 14.05.2023, Messwertverarbeitung=
 
 
Die Messwerte der Messwertplatine werden nun im Messwert-Puffer gespeichert und können von anderen functions verarbeitet werden. <br>
Dazu werden die Messwerte der MWP in einem lokalen Vektor gespeichert und dieser anhand der Indizes dem globalen Messwertpuffer zusammen mit dem Zeitstempel der Messung zugeordnet und umgerechnet. Die Zuordnung erfolgt auf Basis der bestehenden Logik, wobei es allerdings zu Unregelmäßigkeiten kommt, diese könnten zukünftig aufgearbeitet werden:
# Boilertemperatur -> MWP
# Frischwassertemperatur  -> MWP
# Mischwassertemp -> MWP
# Boilerdruck -> MWP
# Wasserleitfähigkeit -> MWP
# Füllstand -> BAS
# Durchfluss -> BAS
# Pulse Flowmeter -> BAS
# Temperatur hinter der Wasserwendel/ vor der Brühgruppe  -> MWP
# Druck in der Brühgruppe  -> MWP
# Pumpensteuerspannung
# Bypass-Stellung
# Dosierventilstellung
# Brühgruppendrossel
# Heizleistung PWM
 
           
 
            if app.verarbeitung_aktiv == 0
                % wenn gerade keine Verarbeitungsroutine durchgeführt wird, kann eine neue gestartet werden
 
                app.verarbeitung_aktiv = 1; % Variable auf 1 setzen, um erneute Verarbeitung zu verhindern
 
                messwerte_mwp = [0,0,0,0,0,0,0,0]; % Anlegen von lokalen Vektoren mit 0 als Messwerte
                messwerte_bas = [0,0,0,0,0,0];
                % im Fehlerfall von einer Platine werden nur Nullen an den entsprechenden Stellen der Oberfläche angezeigt
                % ohne diese Vektoren, keine Verarbeitung über eine Verarbeitungsfunktion, wenn eine Platine Fehlerfall hat, möglich
 
                if strcmp(app.zeile_char_mwp(1:1),'M')
                    % wenn gesendete Antwort der MWP an erster Stelle Signalwort enthielt (kein Fehlerfall auf MWP)
 
                  messwerte_mwp =str2num(app.zeile_char_mwp_neu); % 0-Vekor mit gesendeten Messwerten überschreiben
 
                end 
 
                if strcmp(app.zeile_char_bas(1:1),'B')
                    % wenn gesendete Antwort der BAS an erster Stelle Signalwort enthielt (kein Fehlerfall auf BAS)
 
                  messwerte_bas =str2num(app.zeile_char_bas_neu); % 0-Vekor mit gesendeten Messwerten überschreiben
 
                end
 
 
                %ERSTELLUNG DER ZEITPUNKTE
                aktuelle_uhrzeit = datestr(now,'HH:MM:SS.FFF');    % Aktuelle Uhrzeit ermitteln
                uhrzeit_sekunden = str2num(aktuelle_uhrzeit(1:2))*3600 + str2num(aktuelle_uhrzeit(4:5))*60 + str2num(aktuelle_uhrzeit(7:end)); % Umrechnung in Sekunden
                                                         
                if app.uhrzeit_erste_messung == 0                  % Erkennung der erstmalige Messwertverarbeitung
                    app.uhrzeit_erste_messung = uhrzeit_sekunden;  % Abspeichern des Startzeitpunktes der Messung
                    app.zeitstempel_messung(1,1) = 0;              % Startzeitpunkt an erste Stelle des Vktor mit den Zeitstempel der Messungen speichern
                else
                    app.zeitstempel_messung(end+1,1) = uhrzeit_sekunden - app.uhrzeit_erste_messung; %Hinzufügen eines weiteren Zeitstempels am Ende des Vektors           
                                                                                                    % vergangene Zeit zwischen aktueller und erster Messung
                end
               
                %VERARBEITUNG MESSWERTE
                pos_zeitstempel = length(app.zeitstempel_messung); % Anzahl der durchgeführten Messungen ermitteln = letztes Element
               
                % Abspeichern der Messwerte in letzter Zeile des Messwert-Puffer (pos_zeitstempel) und in zugewiesener Spalte
 
                %1. Boilertemperatur
                    app.messwert_puffer(pos_zeitstempel,1) = app.boilerkalibrierkurve(round(messwerte_mwp(1)*3300/4096));
                    % Umwandlung des Messwertes zu einem Boilertemperaturwert, durch Extraktion eines Spannungswert aus dem ADC-Wert und dann nachschauen in einer Tabelle.     
                % 2. Frischwassertemperatur
                    app.messwert_puffer(pos_zeitstempel,2)=(messwerte_mwp(2)*1.00416-1.68)*140/4096;
                    % Umwandlung des Messwertes zu einer Frischwassertemperatur inkl. linearer Kalibrierkurve (ADC)
                % 3. Mischwassertemp
                    app.messwert_puffer(pos_zeitstempel,3)=app.mischerkalibrierkurve(round(messwerte_mwp(3)*3300/4096));
                    % Umwandlung des Messwertes zur Mischwassertemperatur,durch extraktion eines Spannungswert aus dem ADC-Wert und dann nachschauen in einer Tabelle. 
                % 4. Boilerdruck
                    app.messwert_puffer(pos_zeitstempel,4)=4500*((messwerte_mwp(4)*1.00605-4.72)/4096)-500;
                    % Umwandlung des Messwertes zum Boilerdruck. Dieser hat einen 0-Offset von 500mV zzgl. linearer Kalibrierkurve (ADC).
                % 5. Wasserleitfähigkeit
                    app.messwert_puffer(pos_zeitstempel,5)=((messwerte_mwp(5)*1.00382-1.78)*19.8/4096)+0.2; 
                    % Umwandlung des Messwertes zur Wasserleitfähigkeit, dieser hat einen 0-Offset von 0.2mS/cm zzgl. linearer Kalibrierkurve (ADC)
                % 6. Füllstand -> BAS
                    app.messwert_puffer(pos_zeitstempel,6)=messwerte_bas(1);
                % 7. Durchfluss
                    app.messwert_puffer(pos_zeitstempel,7)=messwerte_bas(5);
                % 8. Pulse Flowmeter -> BAS
                    app.messwert_puffer(pos_zeitstempel,8)=messwerte_bas(6);
                    app.flowCounter = app.flowCounter + messwerte_bas(6);
                    % Kumulierung der Interruptmenge zur bestimmung der Bezugsmenge
                % 9. Temperatur hinter der Wasserwendel/ vor der Brühgruppen
                    app.messwert_puffer(pos_zeitstempel,9)=app.mischerkalibrierkurve(round(messwerte_mwp(6)*3300/4096));
                    % Umwandlung des Messwertes zu einer Brühgruppen oder Wasserwendeltemperatur je nach Einbau     
                    app.messPuffer(end,10)=20000*((werte(10))/4096)-2000; % gültig für AVS Römer Drucksensor
                % 10. Druck in der Brühgruppe.
                    app.messwert_puffer(pos_zeitstempel,10)=15000*((messwerte_mwp(7))/4096)-1500;
                    % gültig für SEEED Drucksensor, Umwandlung des Messwertes zum Brühgruppendruck. Dieser hat einen 0-Offset von 500mV und es wird nur der Bereich bis 4,5V verwendet
                % 11. Brühgruppentemperatur (neu??) ANPASSEN FRAGE
                    % app.messwert_puffer(pos_zeitstempel,11)= messwerte_mwp(7);
                % 11. Pumpensteuerspannung -> BAS
                    app.messwert_puffer(pos_zeitstempel,11) = app.Pumpenleistung.Value;
                % 12. Bypass-Stellung -> RPI
                    app.messwert_puffer(pos_zeitstempel,12) = app.Pumpenbypass.Value;
                % 13. Dosierventilstellung -> RPI
                    app.messwert_puffer(pos_zeitstempel,13) = app.Dosierventil.Value;
                % 14. Brühgruppendrossel -> RPI
                    app.messwert_puffer(pos_zeitstempel,14) = app.Bruehgruppendrossel.Value;
                % 15. Heizleistung PWM
                    app.messwert_puffer(pos_zeitstempel,15) = 0;
 
   
 
                if length(app.zeitstempel_messung)>app.puffer_laenge
                    % wenn Anzahl die Messungen die definierte Pufferlänge übersteigt
 
                    % Kürzung auf puffer_laenge
                    app.messwert_puffer = app.messwert_puffer(end - app.puffer_laenge:end,:);        % Löschen aller Zeilen von messwert_puffer bis auf die letzten "puffer_laenge"-Zeilen
                    app.zeitstempel_messung = app.zeitstempel_messung(end - app.puffer_laenge:end,1); % Löschen aller Zeilen von zeitstempel_messung bis auf die letzten "puffer_laenge"-Zeilen
                end


                app.messwerte_anzeigen();      % Funktionsaufruf zur Visualisierung der Messwerte in der GUI-Oberfläche     
= Melina Scherf, 18.05.2023, Messwerte anzeigen =
                app.reglerundfunktionsaufruf(); % Funktionsaufruf, die Regler und Funktionen bearbeitet 
Die Messwerte werden kontinuierlich auf der Oberfläche angezeigt und etwa jede Sekunde aktualisiert.
   
                if app.zeitpunkt_letzte_sicherung == 0
                    % wenn noch keine Sicherung erfolgte
                    app.datensicherung(app);                          % Aufruf der Funktion zur Datensicherung
                    app.zeitpunkt_letzte_sicherung = uhrzeit_sekunden; % Zeitpunkt der letzten Sicherung auf aktuellen Zeitpunkt


                elseif (uhrzeit_sekunden - app.zeitpunkt_letzte_sicherung) > app.Datensicherung.Value
= Melina Scherf, 16.05.2023, Datensicherung=
                    %wenn die vergangene Zeit zwischen letzter Sicherung und aktuellem Zeitpunkt eingegebenen Wert im Start-Reiter überschreitet
Es erfolgt eine kontinuierliche Sicherung der ermittelten Messdaten. Der Zeitabstand der
Datensicherung wird im Eingabefeld eingegeben und ist mit 120 Sekunden vorbelegt. Die
Datensicherung umfasst die letzten xx Sekunden der erfassten Messdaten. Bei jedem Schließen der
GUI wird ebenfalls eine Datensicherung vorgenommen. Diese Datensicherung ist unter dem
Dateinamen „last_data.mat“ zu finden. <br>
Zusätzlich ist eine manuelle Datensicherung durchführbar. Diese legt die Daten in einer anderen Datei
ab. Dabei wird der Dateiname aus Datum und Uhrzeit gebildet, sodass die Daten wieder einem
Ereignis zuordenbar sind, die Dateinamen eindeutig bleiben und es zu keinen Überschreibungen von
erfassten Messdaten kommt. Der Dateiname hat das Format „YYYYMMDD_Thhmmss.mat“ (ISO-Datum und Zeitangabe ohne Zwischenzeichen). <br>
Als Meta-Daten werden alle editierbaren Eingaben des Start-Reiters und eine Messpunktliste
abgespeichert. Die Amat-Datei verfügt über die Messdatenmatrix und einen Zeitvektor.


                    app.automatische_datensicherung = 1;              % Variable, die anzeigt, dass es sich um eine automatische Datensicherung handelt
= Melina Scherf, 15.05.2023, Messwertverarbeitung=
                    app.datensicherung(app);                          % Aufruf der Funktion zur Datensicherung
In der Verarbeitungsfunktion der Messwerte wird der Zeitstempel in Sekunden der jeweiligen
                    app.zeitpunkt_letzte_sicherung = uhrzeit_sekunden; % Zeitpunkt der letzten Sicherung auf aktuellen Zeitpunkt
Messung in einer neuen Zeile der Matrix abgespeichert. Die Messwerte werden in dieselbe Zeile in
                   
den Messwertpuffer gespeichert und umgerechnet. <br>
                end
Sollte der Messwertpuffer die zuvor definierte Länge überschreiten, wird sowohl dieser als auch die
Zeitstempelmatrix gekürzt. <br>
Anschließend werden die Messwerte auf der Oberfläche angezeigt. Letztendlich wird eine erste
Datensicherung (bei erster Messung) oder eine automatische Datensicherung (wenn der Zeitabstand
den auf der Oberfläche editierbaren Wert überschreitet) ausgelöst.


                app.verarbeitung_aktiv = 0; % Verarbeitung abgeschlossen, neue Verarbeitungsroutine kann beginnen
= Melina Scherf, 14.05.2023, Verarbeitungsfunktion BAS (Messwerte) =
            end
Analog zur MWP wurde ebenso die Verarbeitungsfunktion der BAS erstellt. Einziger Unterschied ist,  
dass einkommende Messwerte der BAS-Platine an einem "F!" zu erkennen sind. <br>
Die simulierte Messwerterfassung/Initialisierung wurde in gleicher Weise wie für die MWP für die
BAS-Platine erstellt. Um die Funktion in der Praxis zu testen, wurde je die letzte Zeile des von Armin
Rohnen erstellten [[Messwerte erfassen Multi-MCU|Programm zur simulierten Messdatenerfassung]]
angepasst, sodass die passende Anzahl der Messwerte wie im Real-Betrieb gesendet werden. <br>
MWP:
print('M!',T_Boiler, T_Eingang, T_Mischer, P_Boiler, Leitwert, T_Bruehgruppe, P_Bruehgruppe)
BAS:
print('F!', Fuellstand , Durchfluss, Pulse)


= Melina Scherf, 13.05.2023, Verarbeitungsfunktion MWP =
= Melina Scherf, 13.05.2023, Verarbeitungsfunktion MWP =
In der MATLAB® GUI wurde die Verarbeitungsfunktion der Messwert-Platine erstellt. Dabei handelt es sich um die Funktion, die bei gesendetem Terminator der MWP aufgerufen wird. Diese kann einkommende Messwerte (Erkennungszeichen "M!") von Fehlern unterscheiden. Der Benutzer kann anhand der Error-Lampe sicherstellen, ob es zu Fehlern kommt, diese würde in diesem Fall rot leuchten. Werden Messwerte erkannt wird eine weitere Funktion zur Verarbeitung der Messwerte aufgerufen. <br>
In der MATLAB® GUI wurde die Verarbeitungsfunktion der Messwert-Platine erstellt. Dabei handelt es  
 
sich um die Funktion, die bei gesendetem Terminator der MWP aufgerufen wird. Diese unterscheidet
Zunächst werden die einkommenden Antworten der MWP mittels des readline-Befehls eingelesen, zunächst lokal und anschließend global abgespeichert. Um dies dem Bediener zu verdeutlichen werden die Antworten in der Statusleiste der MWP angezeigt.
einkommende Messwerte (Erkennungszeichen "M!") von Fehlern. Der Benutzer ist in der Lage
  zeile = readline(app.mwp_platine);       
anhand der Error-Lampe sicherzustellen, ob es zu einem Fehler gekommen ist, diese würde in diesem  
  app.zeile_char_mwp = char(zeile);       
Fall rot leuchten. Werden Messwerte erkannt wird die messwerte_verarbeiten()-Funktion zur
  app.MWP_Status.Text = app.zeile_char_mwp;
Verarbeitung der Messwerte aufgerufen und die Error-Lampe leuchtet grün.  
                       
Um die Messwertverarbeitung nur bei einer Messwertübermittlung zuzulassen, wird mittels einer if-Abfrage die gesendete Antwort überprüft - und gegebenenfalls aufbereitet - ob es sich um eine solche handelt. Dafür wird zunächst eine Variable auf den Wert 0 gesetzt, welche nur 1 wird und eine Verarbeitung erlaubt, wenn eine Übermittlung erkannt wurde. 
  app.verarbeitung_moeglich_mwp = 0;
 
Es wird die Länge der einkommenden Antwort ermittelt, anhand dieser kann unterschieden werden, ob es sich um Messwerte handelt.
  lenstr = strlength(app.zeile_char_mwp);
      % strlength(string): Ermittelt die Länge von string
 
Es folgt die Abfrage, ob dieser String länger als 2 Zeichen ist. Sollte dies der Fall sein wird überprüft, ob an den ersten 3 Stellen der Antwort die Zeichen ">>>" stehen, diese werden ANPASSEN. Wird dieser Fall erkannt, werden diese Zeichen entfernt, die Antwortlänge um 3 gekürzt und die Antwort weiter überprüft.                 
  if lenstr>2
      if strcmp(app.zeile_char_mwp(1:3),'>>>')
        % strcmp(s1, s2): vergleicht die beiden Strings s1 und s2 miteinander
        % app.zeile_char_mwp(1:3): nur die ersten drei Stellen
        app.zeile_char_mwp = app.zeile_char_mwp(4:end);
            % app.zeile_char_mwp(4:end): alle Zeichen ab der 4. Stelle 
        lenstr = lenstr-3;                               
      end                                                                     
  end           
 
Anschließend wird überprüft, ob die (übrig gebliebene) Antwort noch mehr als ein Zeichen enthält. Sollte auch dies der Fall sein, wird nach dem Signalzeichen der Messwertübermittlung der MWP gesucht M!. Dieses Signalzeichen wird Python-seitig vor jeder Messwertübermittlung geprintet. Wird es erkannt, handelt es sich um eine Messwertübermittlung und die Variable verarbeitung_moeglich_mwp kann auf den Wert 1 gesetzt werden. Die gesendete Antwort wird in einer neuen Variable gespeichert, um zu verhindern, dass eine zwischenzeitig gesendete und eingelesene Antwort diese überschreibt
  if lenstr > 1
      if strcmp(app.zeile_char_mwp(1:1),'M')
        app.verarbeitung_moeglich_mwp = 1;           
        app.zeile_char_mwp_neu =app.zeile_char_mwp(3:end);
                                                                             
      end
  end
 
Nun wird abgefragt, ob es sich um eine Messwertübermittlung handelte und verarbeitung_moeglich_mwp den Wert 1 besitzt. Wenn zusätzlich bereits alle Platinen initialisiert wurden kann die Funktion zur Messwertverarbeitung aufgerufen werden und die Error-Lampe grün leuchten, um dies auch dem Benutzer zu signalisieren. Sollte die Antwort anders aussehen als abgefragt, bleibt verarbeitung_moeglich_mwp bei 0 und die Error-Lampe leuchtet rot.
 
  if app.verarbeitung_moeglich_mwp == 1
      if (app.ssr_init == 1 && app.bas_init == 1 && app.mwp_init == 1)
        app.messwerte_verarbeiten();
        app.Error_Lampe.Color = 'g';
      end
  else
      app.Error_Lampe.Color = 'r';
  end
 
= Melina Scherf, 07.05.2023, Simulierte Messwerte =
= Melina Scherf, 07.05.2023, Simulierte Messwerte =
Um die Verarbeitungsfunktion der MWP zu testen, wurde ein von Armin Rohnen erstelltes [[Messwerte erfassen Multi-MCU|Programm zur simulierten Messdatenerfassung]] eingepflegt. Dieses stellt quasi eine Initialisierung der MWP dar. Das Programm sendet kontinuierlich 10 Messwerte und kann über einen Knopf gestartet sowie beendet werden.
Um die Verarbeitungsfunktion der MWP zu testen, wurde ein von Armin Rohnen erstelltes  
Die Initialisierung beginnt mit dem Import der nötigen Python-Programme.
[[Messwerte erfassen Multi-MCU|Programm zur simulierten Messdatenerfassung]] eingepflegt.  
  writeline(app.mwp_platine, "from machine import Timer"); 
Dieses stellt eine Initialisierung der MWP dar. Nach Import der nötigen Python-Programme wird ein  
      % Import der Funktion Timer aus der Python-Bibliothek machine   
Timer definiert, der bestimmt, in welcher Frequenz (in Sekunden) die Messwerte gesendet werden  
  writeline(app.mwp_platine, "from messwerte import messwerte");
sollen.
    % Import der Funktion messwerte aus der Python-Bibliothek messwerte
Das Programm sendet kontinuierlich 10 Messwerte und wird über einen Knopf gestartet sowie
 
beendet
Anschließend wird ein Timer definiert, der bestimmt, in welcher Frequenz (in Sekunden) die Messwerte gesendet werden sollen.
  writeline(app.mwp_platine, "messwert_timer = Timer(mode=Timer.PERIODIC, freq=1, callback=messwerte)");


= Melina Scherf, 06.05.2023, Verbinden =
= Melina Scherf, 06.05.2023, Verbinden =
Die Initialisierung aller vier MCUs ist nun möglich. <br>
[[Datei:Verbindungsroutine.png|thumb|500px|rechts|Abbildung 1: Flussdiagramm - Verbinngsroutine]]
<br>
'''Callback Verbinden Button pushed''' <br>
Es wird durch Betätigen des Verbinden-Buttons in der angelegten Testumgebung eine Callback-Funktion ausgelöst. In dieser wird zunächst überprüft, ob zuvor noch keine Verbindung aufgebaut wurde (die Variable verbindungsstatus den Wert 0 besitzt). Sollte dies der Fall sein, wird der Variable verbindungsstatus der Wert 1 zugewiesen und es kann mit der eigentlichen Verbindung begonnen werden. Dem Benutzer wird dies durch eine grün werdende Lampe sowie einen Informationstext in der allgemeinen Statuszeile angezeigt.
 
  if app.verbindungsstatus == 0
        app.verbindungsstatus = 1; 
        app.Error_Lampe.Color = 'g';
          % .Color: Farbe einer Lampe
          % 'g': Kürzel der Farbe grün 
        app.Allgemeiner_Status.Text = char('MCUs werden initalisiert...');
          % .Text: Text des Labels
          % char(): Umwandlung in ein character array, welches im Label angezeigt werden kann ("Vektor für Buchstaben")
Es wird eine Liste mit allen belegten Ports angelegt und der erste Port ausgewählt. Für diesen Port wird eine allgemeine, unidentifizierte MCU erstellt, inklusive Terminator (Zeilenumbruch), Verbindungsgeschwindigkeit und Verarbeitungsfunktion.
 
  app.ports = serialportlist("available");
      % serialportlist() erstellt eine Liste von Ports
      % "available": definiert, dass nur die belegten Ports in die Liste aufgenommen werden sollen               
  app.port_nummer = 1;                                     
  app.mcu = serialport(app.ports(app.port_nummer), 115200);
      % serialport(port, baudrate): Verbindung zum Port
      % port: Definition, welcher Port angesprochen werden soll (app.ports(app.port_nummer): "port_nummer"stes Element der Liste ports)
      % baudrate: Baudrate der Verbindung (Geschwindigkeit) 115200 Bd
  configureTerminator(app.mcu, "CR/LF");
      % configureTerminator(device, terminator): Definition eines Terminators für eine Property ("Ende der Antwort")
      % device: Property für die Terminator gelten soll (allgemeine MCU app.mcu) 
      % terminator: Definition des Terminators ("CR/LF": Zeilenumbruch)                 
  configureCallback(app.mcu, "terminator", @app.init_mcus);
      % configureCallback(device, "terminator", callbackFcn): Definiert die aufzurufende Funktion bei erkanntem Terminator
      % callbackFcn: aufzurufende Funktion


Um die am ersten Port angelegte MCU zu identifizieren wird mittels eines writeline Befehls die ident()-Funktion importiert und ausgeführt.
Die Initialisierung aller vier MCUs ist möglich. <br>
 
'''Verbinden_ButtonButtonPushed''' <br>
  writeline(app.mcu, "import ident");
Nach Betätigung des Verbinden-Buttons in der Oberfläche, legt dieser Callback eine Liste aller
      % writeline(device, command): schreibt den Command (Text) zum definierten Device (mit anschließendem Terminator)
belegten Ports und eine unidentifizierte MCU inklusive Verarbeitungsgeschwindigkeit, Terminator und
      % command: "import ident" Import des Python-Programms ident                 
Verarbeitungsfunktion für den ersten Port fest. Durch Aufruf der ident()-Funktion wird von der Platine
  writeline(app.mcu, "ident.ident()");
das Identifikationskürzel als Antwort gesendet. Diese Antwort löst die Verarbeitungsfunktion
      % ident.ident(): Aufruf der Funktion ident() aus dem Programm ident
init_mcus() aus. <br>
 
Die zugehörige Python-Funktion sendet das Identifikationskürzel der Platine als Antwort an MATLAB® zurück:
 
ANPASSEN: PYTHON_CODE
 
Der Zeilenumbruch am Ende der Antwort triggert als Terminator den Aufruf der init_mcus()-Funktion. <br>
<br>
'''init_mcus()''' <br>
'''init_mcus()''' <br>
In dieser wird zunächst die gesendete Antwort eingelesen und abgespeichert.
Diese Funktion identifiziert das gesendete Antwortkürzel und weist der identifizierten Platine einen
 
neuen Namen und Verarbeitungsfunktion zu. Anschließend wird mit der Initialisierung der Platinen in
  zeile = readline(app.mcu);
einer separaten Funktion begonnen. <br>
      % readline(device): liest die gesendete Antwort bis zum ersten Terminator       
Um gegebenenfalls die Ansprache des nächsten Portes zu ermöglichen, wird nach abgeschlossener  
  app.zeile_char = char(zeile);
Initialisierung die hochzaehlen()-Funktion aufgerufen. Sollten bereits alle MCUs initialisiert worden
 
sein, wird dies dem Benutzer durch eine Statusmeldung angezeigt. <br>
Mittels einer if-Abfrage wird überprüft, welches der zuvor definierten Kürzel (ssr, bas, mwp) die Antwort enthält und ob diese Platine nicht bereits initialisiert wurde. Die eigentliche Initialisierung wird gestartet, welches dem Benutzer an einer Meldung in der Statusleiste signalisiert wird. (Im folgenden wird dies am Beispiel der SSR dokumentiert. BAS- und MWP-Platine sind analog angelegt). Die zuvor angelegte allgemeine MCU wird nun als ssr_platine abgespeichert und ihr eine neue, SSR-spezifische Verarbeitungsfunktion zugewiesen.  
 
  if contains(app.zeile_char,'ssr') && app.ssr_init == 0
      % contains(string, pattern): sucht im String string nach dem Ausdruck pattern
      % 'ssr': Identifikationskürzel der SSR-Platine nach dem gesucht werden soll
      app.SSR_Status.Text = ('SSR-Platine wird konfiguriert');
      app.ssr_platine = app.mcu;
      configureCallback(app.ssr_platine, "terminator", @app.ssr_verarbeitung)
 
Anschließend wird die, der Übersichtlichkeit halber, separate Initialiserungsfunktion aufgerufen, in der sämtliche Python-Programme importiert und die Schrittmotoren sowie Magnetventile mechanisch initialisiert werden. Nach Abschluss der Initialisierung der Platine kann der Initialisierungsstatus auf den Wert 1 gesetzt werde, sodass eine erneute Initialisierung verhindert wird und dem Benutzer eine entsprechende Nachricht angezeigt werden.
 
  app.ssr_initalisieren();                                             
  app.ssr_init = 1;                                                     
  app.SSR_Status.Text = ('SSR-Platine Initalisierung abgeschlossen');
 
Abschließend wird die Variable hochzaehlen_erlauben auf den Wert 1 gesetzt, um gegebenenfalls die Bearbeitung des nächsten Ports zuzulassen. Diese Variable stellt sicher, dass der aktuelle Port erst nach abgeschlossener Bearbeitung gewechselt werden kann.
Dazu wird am Ende der init_mcus()-Funktion die hochzaehlen()-Funktion aufgerufen. <br>
In dieser wird nun überprüft, ob es noch weitere zu bearbeitende Ports gibt, indem die aktuelle Portnummer mit der Länge der Liste mit allen verfügbaren Ports verglichen wird. Sind noch weitere Ports zu bearbeiten und besitzt die Variable zur Erlaubnis zum Hochzählen den Wert 1, kann der nächste Port angewählt werden.
 
  if app.port_nummer < length(app.ports) && app.next == 1
 
<br>
'''hochzaehlen()''' <br>
'''hochzaehlen()''' <br>
In der hochzaehlen()-Funktion wird nun der nächste Port ausgewählt und erneut eine allgemeine MCU inklusive Terminator (Zeilenumbruch), Verarbeitungsgeschwindigkeit und -funktion erstellt. Durch Aufruf der ident()-Funktion wird erneut die init_mcus()-Funktion aufgerufen.
In dieser Funktion wird für den nächsten Port, sollte es noch ein nicht bearbeiteter vorhanden sein,
 
eine unidentifizierte MCU angelegt und erneut durch den Aufruf der ident()-Funktion die init_mcus()-
  app.port_nummer = app.port_nummer +1;               
Funktion aufgerufen.
  app.mcu = serialport(app.ports(app.port_nummer), 115200);
<br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br>
  configureTerminator(app.mcu, "CR/LF");                 
  configureCallback(app.mcu, "terminator", @app.init_mcus);
  writeline(app.mcu, "import ident");                     
  writeline(app.mcu, "ident.ident()");
 
Sind alle belegten Ports abgearbeitet, also der Initialisierungsstatus aller Platinen auf dem Wert 1, wird dies dem Benutzer durch eine Information in der Statuszeile signalisiert.
 
  if (app.ssr_init == 1 && app.bas_init == 1 && app.mwp_init == 1)
        app.Allgemeiner_Status.Text = char('Alle MCUs initalisert');
 
Dieses Verfahren hat den Vorteil, dass die Platinen in einer unbekannten Reihenfolge durch einmaligen Knopfdruck auf den Verbinden-Button verbunden und initialisiert werden können.


= Melina Scherf, 28.04.2023 =
= Melina Scherf, 28.04.2023 =
Während der Neuprogrammierung der MATLAB® GUI ist so vorzugehen, dass jeder hinzugefügte Codeabschnitt zunächst mit Versuchs-Microcontrollern getestet wird. Dazu wurden Melina Scherf 4 Versuchs-Microcontroller übergeben. <br>
Während der Neuprogrammierung der MATLAB® GUI ist so vorzugehen, dass jeder hinzugefügte Codeabschnitt zunächst mit Versuchs-Microcontrollern getestet wird. Dazu wurden Melina Scherf 4 Versuchs-Microcontroller übergeben. <br>
Es wird bis zur Fertigstellung der neuen GUI durch Madita vom Stein mit einer Testumgebung gearbeitet, in der nach und nach alle für die Programmierung notwendigen Oberflächenelemente angelegt werden. Nach der Fertigstellung werden diese dann in die neue Oberfläche übertragen. <br>
Es wird bis zur Fertigstellung der neuen GUI durch Madita vom Stein mit einer Testumgebung gearbeitet, in der nach und nach alle für die Programmierung notwendigen Oberflächenelemente angelegt werden. Nach der Fertigstellung werden diese dann in die neue Oberfläche übertragen. <br>
Um die Kommunikation zwischen MATLAB® und MicroPython zu ermöglichen, müssen die MCUs initialisiert werden. Dazu wurde mit Armin Rohnen eine Workshop durchgeführt, in welchem das Vorgehen zur Initialisierung vorgestellt wurde. Anschließend wurde von Melina Scherf diese in den neuen Code eingepflegt. Die MCUs heißen im Code nun ssr_platine, bas_platine, mwp_platine, rpi_platine nach zuvor festgelegten Definition der Benennungen. So wird die Ansprache der alten STM32 zukünftig auf unterschiedliche MCUs aufgeteilt werden.
Um die Kommunikation zwischen MATLAB® und MicroPython zu ermöglichen, müssen die MCUs initialisiert werden. Dazu wurde mit Armin Rohnen eine Workshop durchgeführt, in welchem das Vorgehen zur Initialisierung vorgestellt wurde. Anschließend wurde von Melina Scherf diese in den neuen Code eingepflegt. Die MCUs heißen im Code ssr_platine, bas_platine, mwp_platine, rpi_platine nach zuvor festgelegten Definition der Benennungen. So wird die Ansprache der alten STM32 zukünftig auf unterschiedliche MCUs aufgeteilt werden.


= Melina Scherf, 16.04.2023 =
= Melina Scherf, 16.04.2023 =
Als Vereinfachungspotential wurde zum einen die generelle Übersichtlichkeit des Codes festgestellt. Um dies zu verbessern, wird mit größeren Einzügen gearbeitet, um die übergeordneten Funktionen auf einen Blick zu erkennen. Die Reihenfolge der functions wird zudem thematisch sinnvoll gegliedert, vorläufig in:
Als Vereinfachungspotential wurde zum einen die generelle Übersichtlichkeit des Codes festgestellt. Um dies zu verbessern, wird mit größeren Einzügen gearbeitet, um die übergeordneten Funktionen auf einen Blick zu erkennen. Die Reihenfolge der functions wird zudem thematisch sinnvoll gegliedert, vorläufig in: Programme, Regler, Kommunikation mit MCU, Aktoren. <br>
* Programme
* Regler
* Kommunikation mit MCU
* Aktoren
Dazu wurde am Anfang der methods im Code ein Inhaltsverzeichnis und über den jeweiligen Abschnitten Überschriften eingefügt. <br>
Dazu wurde am Anfang der methods im Code ein Inhaltsverzeichnis und über den jeweiligen Abschnitten Überschriften eingefügt. <br>
Das Programm des Mischwasserbezugs besteht im vorhanden Code aus 8 Funktionen, diese sollen zusammengekürzt und (sofern möglich) in einer Funktion zusammengefasst werden.
Das Programm des Mischwasserbezugs besteht im vorhanden Code aus 8 Funktionen, diese sollen zusammengekürzt und (sofern möglich) in einer Funktion zusammengefasst werden.
Zeile 827: Zeile 206:


= Melina Scherf, 31.03.2023 =
= Melina Scherf, 31.03.2023 =
Um den aktuellen Projektteilnehmern einen besseren Überblick zu gewähren, wurde beschlossen die MATLAB® GUI neu zu programmieren. Dies soll dazu beitragen die Lesbarkeit des Codes zu erhöhen.
Bei der MATLAB® GUI handelt es sich um die graphische Oberfläche, die ein Benutzer sieht und bedient. Die eigentliche Funktionsweise der App wird jedoch in dem zugrundeliegenden Programmcode festgelegt. Dieser Code bildet die Schnittstelle zwischen der Oberfläche und der Elektronik der Laborsiebträgermaschine. <br>
Zum Zeitpunkt des Projektbeginns im März 2023 lag bereits eine MATLAB® GUI mit entsprechendem Programmcode vor. [85] <br>
Eine Neugestaltung soll jedoch die Bedienbarkeit intuitiver und einfacher gestalten sowie die Oberfläche dem aktuell Hardwarestand [64] angepasst werden. Der Programmcode sollte ebenso für die neugestaltete Oberfläche neu aufgesetzt werden. Der bestehende Code bot Potentiale zur Verbesserung und Vereinfachung, welches gerade bei der hohen Fluktuation des Projektes sinnvoll erschien. <br>
In diesem Zug sollte die Vorbereitung für den Umbau auf die geplante Multi-MCU ebenfalls angelegt werden.


= Melina Scherf, 24.03.2023 =
= Melina Scherf, 24.03.2023 =

Aktuelle Version vom 1. August 2023, 14:06 Uhr

Madita vom Stein, 27.07.2023 - Abschlussbemerkung MATLAB®-GUI

Abbildung 12: Startseite der alten GUI
Abbildung 11: Startseite der neuen GUI
Abbildung 10: Programme der alten GUI
Abbildung 9: Programme der neuen GUI
Abbildung 8: manueller Modus der alten GUI
Abbildung 7: manueller Modus der neuen GUI
Abbildung 6: Reinigungsprogramm (neue GUI)

Die MATLAB®-GUI ist die graphische Bedieneroberfläche der Laborsiebträgermaschine. Die in der GUI durch den Anwender eingegebenen Befehle, beispielsweise das Schalten eines Ventils, werden über den im Hintergrund laufenden MATLAB®-Programmcode an eine Schnittstelle weitergegeben. Diese Schnittstelle steuert die Multi-MCUs an, die direkt auf die Maschine zugreifen.
Als Anwender gelten Studierende, sowie Lehrende, die im Rahmen der „Geschmackssache Kaffee“ an der Labormaschine arbeiten; also Testversuche fahren oder die Maschine weiterentwickeln. Die MATLAB®-GUI ist demnach nicht für den Endanwender der Maschine gedacht. Das verkaufsfähige Endprodukt soll, wie auf dem Markt üblich, mit Schaltern und Knöpfen ausgestattet sein.

Zum Zeitpunkt des Projektstartes lag bereits eine MATLAB®-App inklusive GUI vor [85]. Statt einer Einarbeitung und Weiterentwicklung in den bestehenden Code, erschien eine vollständige Neuaufsetzung der MATLAB®-App und GUI sinnvoller.

Im Hinblick auf die oben genannten Anwender wurde bei der Zielsetzung die Erleichterung der Arbeit im Labor priorisiert. Da die studentischen Arbeitskräfte zum Großteil einer hohen Fluktuation unterliegen, wurde außerdem auf eine intuitive Bedienbarkeit und eine hohe Übersichtlichkeit geachtet. Dadurch soll das Einfinden in die MATLAB®-GUI erleichtert, und folglich die Einarbeitungszeit verkürzt werden.

Sowohl die alte als auch die neue MATLAB®-GUI ist in Tabs unterteilt. Diese gliedern sich in die Startseite, einen manuellen Modus und einen automatischen Modus für Bezugsprogramme. Die neue MATLAB®-GUI beinhaltet zusätzlich einen Tab für das Reinigungsprogramm, welches im Rahmen der Projektarbeit entstanden ist.
Die bisherige MATLAB®-GUI weist zudem Verbesserungspotenzial auf. So war der gesamte Laptop-Bildschirm durch die GUI ausgefüllt. In der neuen GUI wurde bewusst ein Format von 1720 x 880 Pixeln gewählt, sodass wahlweise am oberen oder unteren Rand der GUI ein im Hintergrund liegendes Programm sichtbar ist. Im Falle der Weiterentwicklung der Systemsoftware könnte dies das Command Window von MATLAB® sein, sodass Fehlermeldungen sofort zur Kenntnis genommen werden.
Ebenfalls neu ist, dass die Tabs nicht die gesamte Oberfläche der GUI einnehmen, sondern es einen immer sichtbaren Bereich gibt. Dieser bringt vier Vorteile mit sich. Erstens wird nicht für jeden Tab ein eigener Button für das Speichern des Messwertepuffers benötigt. Stattdessen gibt es diesen Button ein einziges Mal, aber in dem Bereich, auf den ein Zugriff jederzeit möglich ist. Ein zweiter Vorteil ist, dass die für das Geschmackserlebnis besonders relevanten Messwerte Leitungsdruck [mbar] und Durchflussrate [ml / s] ständig sichtbar sind. Auch der Error-Button, sowie der zugehörige Reset-Error-Button, ist in allen Tabs relevant. Die Verschiebung in den immer sichtbaren Bereich brachte auch hier eine erhöhte Reaktionsgeschwindigkeit auf Probleme mit sich, worin der dritte Vorteil liegt. Bei der Reaktion auf Probleme ist auch der Notaus-Button von Bedeutung. Hier können durch schnelles Handeln Schäden an Menschen und Maschine vermieden werden. Ebenfalls in dem immer sichtbaren Bereich ist der jeweilige Programmstatus der einzelnen Platinen. Das hat den Vorteil, dass immer erkennbar ist, ob diese verbunden sind; nicht nur auf der Startseite.
An der Startseite selbst hat sich kaum etwas verändert. Es gibt hier nach wie vor die Buttons „manueller Modus“, „Verbinden“, sowie „Debug“. Weiterhin gibt es Eingabefelder für Daten wie beispielsweise das Datum, die Kaffeesorte oder den Mahlgrad, die den Messwerten zugeordnet werden. Es ist außerdem einstellbar, wie oft die Daten gesichert werden sollen.
Während der Tab „Programme“ in der alten MATLAB®-GUI neben drei Schalter für Kaffeebezug, Teewasserbezug und Dampfbezug auch noch sehr viele andere Inhalte, die nicht direkt den Programmen zuordbar sind, wie beispielsweise die k-Faktoren der Regler, beinhaltet, ist dieser Tab in der neuen GUI minimalistischer gehalten. Da die Programme bisher gar nicht existieren, gibt es hier lediglich vier Buttons als Platzhalter. Ein Programm wird über diese gestartet und gestoppt. Der aktuelle Programmstatus ist an dem jeweils nebenstehenden Lämpchen erkennbar, wobei „rot“ bedeutet, dass das Programm in dem Moment aktiv ist. Während ein Programm durchläuft, sind Ventilschaltungen und Zustandsparameter in dem manuellen Modus nachverfolgbar.
Ansonsten ist der manuelle Modus primär dazu gedacht, dass Ventile einzeln geschaltet, Parameter einzeln geändert, und dadurch Programme entwickelt und getestet werden können. Das Prozessbild der alten GUI ist sehr detailliert und informativ, dadurch aber leider auch sehr unübersichtlich. Es sind auch die Wege des Brauchwassers hin zur Abtropfschale dargestellt. Dies ist bei Hydraulikplänen unüblich und verbraucht zusätzlichen Platz. Durch die vielen Farben und Formen wird die Aufmerksamkeit des Benutzers immer wieder hin zu anderen Stellen gelenkt. Dadurch, dass die Messwerte recht klein und an wenig intuitiven Stellen dargestellt sind, sind diese schwierig zu finden. Die Schalter für die Grundeinstellungen stehen nicht gesammelt und in keiner sinnvollen Reihenfolge.
In der neuen GUI dagegen sind diese Schalter in schlüssiger Reihenfolge, gesammelt oben links abgebildet. Die Bezeichnungen der Messwerte sind größer und fett gedruckt geschrieben. Die Messwerte selbst sind grau hinterlegt. Die Positionierung der Werte ist im Vergleich zu vorher logisch. Die Mischtemperatur befindet sich zum Beispiel an der Stelle, wo gedrosseltes Kalt- und in der Heizwendel erhitztes Warmwasser zusammentreffen. Die Brühgruppenwerte sind direkt in der angedeuteten Brühgruppe zu finden. Insgesamt ist das neue Prozessbild deutlich ruhiger. Es sind nur die wichtigsten Stränge dargestellt. Die Brauchwasserleitungen sind angedeutet.
Ein Hauptunterschied der neuen zur alten GUI liegt in der Ventildarstellung. Während zuvor durch Lämpchen in den Ventilen signalisiert wurde, ob, beziehungsweise wie, ein Ventil geschaltet ist, wird dies in der neuen GUI durch einen Bildwechsel deutlich. Klickt der Benutzer auf das Ventil im Prozessbild, ändert sich das im MATLAB®-Code hinterlegte Ventilbild und das Ventil wird geschaltet.
Da vor Beginn des Projektstartes noch kein Reinigungsprogramm existierte, gibt es den betreffenden Tab lediglich in der neuen GUI. Hier gibt es einen Button zum Start des Programmes, sowie eine Anzeige zum aktuellen Status. Es ist außerdem eine Beschreibung des Ablaufs und Hinweise dazu eingefügt.
Durch die zuvor angesprochenen Maßnahmen ist die neue MATLAB®-GUI übersichtlicher und intuitiver zu bedienen als die alte GUI. Sie ist außerdem auf dem neusten Stand des Hydraulikplans und bildet somit die Labormaschine treffend ab.















Melina Scherf, 25.07.2023, offene Themen

Der generelle Aufbau des Programmcodes wurde in einzelne Unterüberschriften unterteilt, sodass zukünftigen Bearbeitern die Zugehörigkeit der Funktionen verständlich wird. Diese lauten: Initialisierung und Verarbeitung MCUs, Programm- und Regleraufruf, Regler, Aktorenstellung. Es ist darauf zu achten, dass Programm- und Regleraufruf sowie Regler nur an den Programmcode angepasst wurden, ihre Funktionsweise jedoch nicht verändert wurde.
Von zukünftige Bearbeitende sind noch Verbesserungen vorzunehmen. Eine Statusmeldung am Ende der Initialisierung, dass diese beendet wurde, ist nicht der letzte Eintrag in der Statusleiste. Hier muss eine künstliche Verlangsamung vorgenommen werden. Die Initialisierungsfunktion wird häufiger als 4x aufgerufen. Dies liegt daran, dass durch den Import des ident-Programmes, vor Aufruf der ident()-Funktion, bereits ein Terminator gesendet wird.
Die im Reiter „manueller Modus“ angelegten Schalter sind noch nicht auf Funktionalität überprüft worden. Die Messwerte starten beim letzten Testdurchlauf des Programms automatisch mit der Initialisierung der MWP. Dieses sollte erst durch Betätigung eines Schalters geschehen. Zudem war das Signalwort der einkommenden Messwerte nicht gleichermaßen definiert (M und B!).
Die Abspeicherung der Messwerte in den Messwertpuffer erfolgt nach einer nicht mehr passenden Logik. Da dies Auswirkungen auf die Regler und Programme hat und diese thematisch nicht Teil der Projektgruppe SoSe2023 waren, wurde dies nicht angepasst. Die Anzeige der Messwerte ist noch fehlerhaft oder kein entsprechendes Anzeigelabel mehr in der Oberfläche vorhanden (Messwert 11-15). Hier sollte die Sinnhaftigkeit dieser Messwerte überprüft werden.
Es sollte zudem überprüft werden, ob es während einer Verarbeitungsroutine der Messwerte durch eine neu eingelesene Antwort zu Fehlern kommt. In der Praxis ist dies nie aufgetreten, der Code bietet jedoch die Option.
Die Schaltung der Heizung ist aktuell fehlerhaft. Der Aufruf muss als PWM-Signal übermittelt werden. Die Zuordnung der Ventile erwies sich ebenso als fehlerhaft, sodass manche Ventile nicht oder falsch angesteuert wurden. Die angepasste Ventilschaltung, insbesondere der Icon-Wechsel, bietet Potentiale zur Verbesserung und Vereinfachung. Zusätzlich müssen die geänderten Stellungsaufrufe in den Programm- und Regleraufruf eingepflegt werden.
Der ResetError-Button sowie der Notaus-Knopf haben aktuell noch keine Funktion. Außerdem wurde die Funktionen zum Durchrollieren der Antworten [85] entfernt, da die neue MCU nur eine Statuszeile je Platine und eine allgemeine besitzt.
Aufgrund der Zerstörung der Platinen, bedarf es einer ausführlicheren Übergabe, sodass das erstellte Reinigungsprogramm aus Zeitmangel nicht implementiert wurde. Dieses muss eingefügt und nochmals getestet werden. Aus denselben Gründen wurde ein automatischer Kaffee- und Teewasserbezug nicht realisiert. Diese Bezüge werden jedoch ähnlich dem Reinigungsprogramm ablaufen, womit eine Orientierung daran möglich ist.


Melina Scherf, 23.07.2023, Ventilschaltung automatischer Wechsel

Es soll bei der Magnetventilschaltung in MATLAB® verhindert werden, dass mit jedem Funktionsaufruf der Icon-Wechsel angelegt werden muss und bei zukünftigen automatischen Programmabläufen die Schaltung der Ventile auf der Oberfläche zu beobachten ist. Dazu wurde der Icon-Wechsel der Funktion zur Ventilschaltung hinzugefügt. Im manuellen Modus wird anhand der Statusflag das Bild gewechselt. Im automatischen Modus werden alle Icons der in der Übergabe enthaltenden Ventile zur geöffneten Position gewechselt, alle anderen zur geschlossenen. Somit wird auch der Aufruf vereinfacht und ist im automatischen und manuellen Modus identisch.

  app.ventile_stellen("'Yxx'");


Melina Scherf, 14.06.2023, Ventilschaltung (Python)

Der MicroPython-Code für die Ventilschaltung ab August 2023 wurde erstellt und auf der Seite zum Schalten Magnetventile SSR-Platine Multi-MCU erklärt.


Melina Scherf, 07.06.2023, Ventilschaltung (MATLAB)

Um die Schaltung der Aktoren übersichtlicher zu gestalten, sollen direkt in den Programmen (automatischer Modus) oder bei Wertänderung (manueller Modus) Funktionen aufgerufen werden.
Somit wurde je eine Funktion für die Heizung, Pumpe und das Dosierventil erstellt, die zukünftigen an allen Stellen – automatischer und manueller Modus - aufgerufen werden soll, die einer Stellung bedürfen. Diese Funktion sind bereits im Januar 2023 vorhanden gewesen. Anders verhält es sich mit der Ventilschaltung, diese wurde vollständig neu programmiert.
Die Schaltung der Ventile erfolgte im Januar 2023 über die Festlegung der Sollwerte:

    app.ventileSollIntern=[0 1 0 1 0 0 0 0 0 0]; 

Dieser Vektor wird anschließend im SOLL/IST-Vergleich verarbeitet.
Dies ist in der Handhabung sehr umständlich, da zu einem die Zuordnung der Ventile schwerfällt und zum anderen die Position der Ventile im Vektor nicht mehr zum aktuellen Stand der Maschine passt, was zukünftig verhindert werden soll. Aktuelle Schaltung: [Y01, Y03, Y04, Y05, Y13, Y06, Y07, Y08, Y09, Y00] Daher wurde die neue Funktion ventile_stellen() programmiert, die in der Lage ist eine unbekannte Anzahl an Eingaben zu verarbeiten. Die doppelten Anführungszeichen werden benötigt, da bei der Übertragung an Python eines gelöscht wird (Indikator String).

   Aufruf:  app.ventile_stellen("‘Y01‘", "‘Y13‘", "‘Y07‘");

Im automatischen Modus werden alle Ventile, die in dieser Funktion genannt werden, geöffnet, alle nicht genannten geschlossen. Eine Anwendung dieser Funktionsweise auf den manuellen Modus ist jedoch nicht möglich, da sonst bei Schaltung eines Ventils (Drücken auf Ventilicon) zeitgleich alle anderen Ventile mitgeschaltet werden würden. Die Funktion ist jedoch in der Lage zwischen automatischem und manuellem Modus zu unterscheiden. Im manuellen Modus werden dahingehend die übergebenen geschlossenen Ventile geöffnet und andersherum. Theoretisch würde es im manuellen Modus reichen nur einen Wert zu übergeben, denn manuell ist es bisher nur möglich, ein Ventil gleichzeitig zu schalten. Um aber zukünftigen Komplikationen aus dem Weg zu gehen und für zukünftige Bearbeiter eine bessere Übersichtlichkeit und Anpassungsmöglichkeit zu garantieren, wurde sich für dafür entschieden, einen Mehrfach-Aufruf trotzdem anzulegen.

Madita vom Stein, 06.06.2023

Beschreibung Prozessbild manueller Modus der GUI

Abbildung 5: Prozessbild manueller Modus der GUI

Auf dem Prozessbild sind die wesentlichen Zusammenhänge der im Mai 2023 aktuellen Labormaschine dargestellt.

Das Magnetventil Y01 ist das Ventil für den Festwasseranschluss.
Es wird eine Fluid-O-tech Pumpe verwendet. Parallel gibt es einen steuerbaren Bypass, der über ein Drosselventil mit Schrittmotor hergestellt wird.
Über das Magnetventil Y03 (Entschichtungsventil) wird der Boiler durch Umpumpen entschichtet oder durch Abpumpen entleert. Schmutzwasser kann über Y05 (Entwässerungsventil) abgeführt werden und über Y04 (Boilerbefüllung) wird der Boiler befüllt.
Der Kaffee- bzw. Teewasserbezug wird über Y06 (Bezugsventil) geschaltet. Es führt ein ungedrosselter Wasserstrang durch die Wasserwendel im Boiler zum Mischer. Ein weiterer Wasserstrang, der durch ein Dosierventil gedrosselt wird, führt ebenfalls zum Mischer. Der Mischer selbst ist derzeit als T-Stück realisiert.
Das 3/2-Wegeventil Y07 (Mischventil) führt im nicht-geschalteten Zustand in die Abtropfwanne.
Das Magnetventil Y09 (Umschaltventil) schaltet zwischen Kaffeebezug und Teewasserbezug um. Es steht im nicht-geschalteten Zustand auf Kaffeebezug.
Vor der Brühgruppe befindet sich eine Drossel mit Schrittmotor.
Über das Ventil Y08 (Rückspülventil) wird die halbautomatisierte Rückspülreinigung der Brühgruppe realisiert.
Der Dampfhahn ist als 3/2-Wege-Magnetventil Y13 ausgeführt. Im nicht-geschalteten Zustand wird das Kondenswasser zwischen Dampfhahn und -lanze in die Abtropfschale abgeleitet.
Der Stahlboiler der Labormaschine weist 3,6 Liter Gesamtvolumen auf und wird auf 2,4 Liter befüllt. Mit einem 1800 Watt leistungsgeregeltem Heizelement wurden 12 Minuten Aufheizzeit ermittelt.

Melina Scherf, 26.05.2023, Ventilschaltung

Die Schaltung der Ventile im automatischen Modus wurde angepasst. Im Januar 2023 wurde eine Abfrage der IST- und SOLL-Stellwerte der Ventile durchgeführt und bei detektierten Abweichungen ein Vektor an die STM32 geschickt, die die Ventile entsprechend geschaltet hat. Der Vergleich bleibt vorläufig bestehen, welcher bei abweichenden Werten einer neu eingeführten Statusflag ab August 2023 eine Funktion "Yxx__on" bzw. "Yxx_off" direkt aufgerufen. Die Zuordnung der Pins zu den jeweiligen Ventilen erfolgt bereits in der Initialisierungsfunktion der SSR. Je nach Stellung des Ventils wird das Icon in der Oberfläche im Reiter „manueller Modus“ angepasst.

Melina Scherf, 24.05.2023, Initialisierung BAS, SSR, MWP; Aktorenstellung: Pumpe, Heizung, Dosierventil

Abbildung 4

Es erfolgte die erstmalige Zusammenführung der Elektronik mit der Software.
Initialisierung
Im Zuge dessen wurden die Initialisierungen auf den neu geschriebenen Python-Code angepasst. Auf der SSR werden zusätzlich die Heizung und Ventile initialisiert. Letztere werden alle geschlossen, um einen gesicherten Zustand herzustellen. Die Initialisierung der Pumpe findet auf der BAS statt. Die zuvor verwendete MWP-Initialisierung der simulierten Messwerte wurde zum Import der realen Messwerterfassung geändert. [Abb. 4]
Aktorenstellung
Die Schaltung der Aktoren erfolgt durch writeline-Befehle, welche von MATLAB® an Python geschickt werden. Diese wurden im Code auf den aktuellen Python-Code angepasst und an die jeweils vorgesehenen Platinen gesendet.
Bei der Einarbeitung ist jedoch aufgefallen, dass die Stellung der Aktoren einiges an Einarbeitungszeit bedarf, welche durch Vereinfachung verkürzt werden soll. Die Stellung erfolgte Stand Januar 2023 im manuellen sowie automatischen Modus über eine Änderung der Soll-Wert. Am Ende des gerade ablaufenden Programmes wurde ein Soll-Ist-Vergleich aufgerufen, welcher alle Aktoren bei mindestens einer festgestellten Abweichung stellt. [85]
Um einen unübersichtlichen, großen Befehl zur Stellung aller Aktoren zu vermeiden, wurde der Soll-Ist-Vergleich im automatischen Modus beibehalten, jedoch wird bei festgestellter Abweichung eines Aktors dieser sofort gestellt. Der Vergleich wird vorerst beibehalten, da ein Direkt-Aufruf in den Programmen viele Konsequenzen nach sich ziehen würde, die in der Praxis getestet werden müssen. Da der Schwerpunkt dieser Projektarbeit zunächst auf der Implementierung der Multi-MCU lag, bleibt dies ein offenes ToDo für zukünftige Projektgruppen.
Im manuellen Modus wurde jedoch direkt in die Callbacks bei Wertänderung die Neustellung einprogrammiert und erfolgt Stand August 2023 nicht mehr über einen Soll-Ist-Vergleich.

Melina Scherf, 22.05.2023, neue GUI

Abbildung 3: Flussdiagramm - Bedienbarkeit der Schalter im Reiter "Manueller Modus"

Der Programmcode wurde in die von Madita vom Stein erstellte GUI importiert.

Sobald der Bediener die App startet, werden im Hintergrund alle nötigen Kalibrierkurven und die Eingaben im Reiter „Start“ vor letzter Schließung der App geladen. Im Reiter „manueller Modus“ werden für alle Ventile die Start-Icons im Zustand „geschlossen“ eingefügt, sodass die Stellung der Ventile graphisch angezeigt wird. Es wurde bei Mausklick auf das Bild im Reiter „Manueller Modus“ im manuellen Modus der Wechsel des Icons und die Negierung (Umkehrung) der Stellung des Ventils realisiert, welches durch eine Flag detektiert wird.
Zudem werden die Schalter im Reiter „Manueller Modus“ ausgegraut und sind somit zu diesem Zeitpunkt nicht bedienbar. Dies garantiert, dass keine Funktionen abgerufen werden können, die entweder noch nicht initialisiert sind oder überwacht werden müssen. Nach abgeschlossener Initialisierung werden die Knöpfe im Reiter „manueller Modus“ in der GUI nacheinander sichtbar und bedienbar geschaltet, sobald es die sichere Bedienung der Maschine zulässt. [Abb. 3]
Bei Beendigung der App wird die in der Datensicherung erwähnte Datei „last_data“ erstellt, welche die editierbaren Eingaben der Oberfläche enthält, die bei Neustart der App geladen werden.
















Melina Scherf, 20.05.2023, Verarbeitung BAS, SSR

Abbildung 2: Verarbeitungsfunktionen der Platinen

Die Bestellung der Platinen erfolgte schneller als geplant, somit wurde statt des vorläufigen Konzeptes mit vier Platinen (SSR, BAS, MWP, RPI) bereits im Sommersemester 2023 das geplante Konzept mit drei Platinen (SSR, BAS, MWP) eingeführt. Die RPI-Platine entfällt, sodass deren Funktionen zur Schrittmotorsteuerung auf die BAS- und SSR-Platine verteilt werden. In der gesendeten Antwort wird nach den Signalwörtern der Schrittmotoren („endDrossel“, „endBypass“, „endDosier“) gesucht, welche am Ende einer Schrittmotor-Stellung übermittelt werden. Werden diese erkannt, werden die Schrittmotoren stromlos geschaltet.















Melina Scherf, 18.05.2023, Messwerte anzeigen

Die Messwerte werden kontinuierlich auf der Oberfläche angezeigt und etwa jede Sekunde aktualisiert.

Melina Scherf, 16.05.2023, Datensicherung

Es erfolgt eine kontinuierliche Sicherung der ermittelten Messdaten. Der Zeitabstand der Datensicherung wird im Eingabefeld eingegeben und ist mit 120 Sekunden vorbelegt. Die Datensicherung umfasst die letzten xx Sekunden der erfassten Messdaten. Bei jedem Schließen der GUI wird ebenfalls eine Datensicherung vorgenommen. Diese Datensicherung ist unter dem Dateinamen „last_data.mat“ zu finden.
Zusätzlich ist eine manuelle Datensicherung durchführbar. Diese legt die Daten in einer anderen Datei ab. Dabei wird der Dateiname aus Datum und Uhrzeit gebildet, sodass die Daten wieder einem Ereignis zuordenbar sind, die Dateinamen eindeutig bleiben und es zu keinen Überschreibungen von erfassten Messdaten kommt. Der Dateiname hat das Format „YYYYMMDD_Thhmmss.mat“ (ISO-Datum und Zeitangabe ohne Zwischenzeichen).
Als Meta-Daten werden alle editierbaren Eingaben des Start-Reiters und eine Messpunktliste abgespeichert. Die Amat-Datei verfügt über die Messdatenmatrix und einen Zeitvektor.

Melina Scherf, 15.05.2023, Messwertverarbeitung

In der Verarbeitungsfunktion der Messwerte wird der Zeitstempel in Sekunden der jeweiligen Messung in einer neuen Zeile der Matrix abgespeichert. Die Messwerte werden in dieselbe Zeile in den Messwertpuffer gespeichert und umgerechnet.
Sollte der Messwertpuffer die zuvor definierte Länge überschreiten, wird sowohl dieser als auch die Zeitstempelmatrix gekürzt.
Anschließend werden die Messwerte auf der Oberfläche angezeigt. Letztendlich wird eine erste Datensicherung (bei erster Messung) oder eine automatische Datensicherung (wenn der Zeitabstand den auf der Oberfläche editierbaren Wert überschreitet) ausgelöst.

Melina Scherf, 14.05.2023, Verarbeitungsfunktion BAS (Messwerte)

Analog zur MWP wurde ebenso die Verarbeitungsfunktion der BAS erstellt. Einziger Unterschied ist, dass einkommende Messwerte der BAS-Platine an einem "F!" zu erkennen sind.
Die simulierte Messwerterfassung/Initialisierung wurde in gleicher Weise wie für die MWP für die BAS-Platine erstellt. Um die Funktion in der Praxis zu testen, wurde je die letzte Zeile des von Armin Rohnen erstellten Programm zur simulierten Messdatenerfassung angepasst, sodass die passende Anzahl der Messwerte wie im Real-Betrieb gesendet werden.
MWP:

print('M!',T_Boiler, T_Eingang, T_Mischer, P_Boiler, Leitwert, T_Bruehgruppe, P_Bruehgruppe) 

BAS:

print('F!', Fuellstand , Durchfluss, Pulse)

Melina Scherf, 13.05.2023, Verarbeitungsfunktion MWP

In der MATLAB® GUI wurde die Verarbeitungsfunktion der Messwert-Platine erstellt. Dabei handelt es sich um die Funktion, die bei gesendetem Terminator der MWP aufgerufen wird. Diese unterscheidet einkommende Messwerte (Erkennungszeichen "M!") von Fehlern. Der Benutzer ist in der Lage anhand der Error-Lampe sicherzustellen, ob es zu einem Fehler gekommen ist, diese würde in diesem Fall rot leuchten. Werden Messwerte erkannt wird die messwerte_verarbeiten()-Funktion zur Verarbeitung der Messwerte aufgerufen und die Error-Lampe leuchtet grün.

Melina Scherf, 07.05.2023, Simulierte Messwerte

Um die Verarbeitungsfunktion der MWP zu testen, wurde ein von Armin Rohnen erstelltes Programm zur simulierten Messdatenerfassung eingepflegt. Dieses stellt eine Initialisierung der MWP dar. Nach Import der nötigen Python-Programme wird ein Timer definiert, der bestimmt, in welcher Frequenz (in Sekunden) die Messwerte gesendet werden sollen. Das Programm sendet kontinuierlich 10 Messwerte und wird über einen Knopf gestartet sowie beendet

Melina Scherf, 06.05.2023, Verbinden

Abbildung 1: Flussdiagramm - Verbinngsroutine

Die Initialisierung aller vier MCUs ist möglich.
Verbinden_ButtonButtonPushed
Nach Betätigung des Verbinden-Buttons in der Oberfläche, legt dieser Callback eine Liste aller belegten Ports und eine unidentifizierte MCU inklusive Verarbeitungsgeschwindigkeit, Terminator und Verarbeitungsfunktion für den ersten Port fest. Durch Aufruf der ident()-Funktion wird von der Platine das Identifikationskürzel als Antwort gesendet. Diese Antwort löst die Verarbeitungsfunktion init_mcus() aus.
init_mcus()
Diese Funktion identifiziert das gesendete Antwortkürzel und weist der identifizierten Platine einen neuen Namen und Verarbeitungsfunktion zu. Anschließend wird mit der Initialisierung der Platinen in einer separaten Funktion begonnen.
Um gegebenenfalls die Ansprache des nächsten Portes zu ermöglichen, wird nach abgeschlossener Initialisierung die hochzaehlen()-Funktion aufgerufen. Sollten bereits alle MCUs initialisiert worden sein, wird dies dem Benutzer durch eine Statusmeldung angezeigt.
hochzaehlen()
In dieser Funktion wird für den nächsten Port, sollte es noch ein nicht bearbeiteter vorhanden sein, eine unidentifizierte MCU angelegt und erneut durch den Aufruf der ident()-Funktion die init_mcus()- Funktion aufgerufen.


















Melina Scherf, 28.04.2023

Während der Neuprogrammierung der MATLAB® GUI ist so vorzugehen, dass jeder hinzugefügte Codeabschnitt zunächst mit Versuchs-Microcontrollern getestet wird. Dazu wurden Melina Scherf 4 Versuchs-Microcontroller übergeben.
Es wird bis zur Fertigstellung der neuen GUI durch Madita vom Stein mit einer Testumgebung gearbeitet, in der nach und nach alle für die Programmierung notwendigen Oberflächenelemente angelegt werden. Nach der Fertigstellung werden diese dann in die neue Oberfläche übertragen.
Um die Kommunikation zwischen MATLAB® und MicroPython zu ermöglichen, müssen die MCUs initialisiert werden. Dazu wurde mit Armin Rohnen eine Workshop durchgeführt, in welchem das Vorgehen zur Initialisierung vorgestellt wurde. Anschließend wurde von Melina Scherf diese in den neuen Code eingepflegt. Die MCUs heißen im Code ssr_platine, bas_platine, mwp_platine, rpi_platine nach zuvor festgelegten Definition der Benennungen. So wird die Ansprache der alten STM32 zukünftig auf unterschiedliche MCUs aufgeteilt werden.

Melina Scherf, 16.04.2023

Als Vereinfachungspotential wurde zum einen die generelle Übersichtlichkeit des Codes festgestellt. Um dies zu verbessern, wird mit größeren Einzügen gearbeitet, um die übergeordneten Funktionen auf einen Blick zu erkennen. Die Reihenfolge der functions wird zudem thematisch sinnvoll gegliedert, vorläufig in: Programme, Regler, Kommunikation mit MCU, Aktoren.
Dazu wurde am Anfang der methods im Code ein Inhaltsverzeichnis und über den jeweiligen Abschnitten Überschriften eingefügt.
Das Programm des Mischwasserbezugs besteht im vorhanden Code aus 8 Funktionen, diese sollen zusammengekürzt und (sofern möglich) in einer Funktion zusammengefasst werden.

Melina Scherf, 01.04.2023

Die Neuprogrammierung der MATLAB® GUI wird von Madita vom Stein und Melina Scherf durchgeführt.
Dabei wird Madita vom Stein die graphische Oberfläche der App erstellen. Es soll versucht werden eine übersichtlichere und ansprechendere Ansicht insbesondere des manuellen Modus' zu erarbeiten.
Melina Scherf wird sich in den bereits bestehenden Code einarbeiten und Vereinfachungs- und Verbesserungspotentiale identifizieren. Diese sollen in die neue MATLAB® GUI einfließen.

Melina Scherf, 31.03.2023

Bei der MATLAB® GUI handelt es sich um die graphische Oberfläche, die ein Benutzer sieht und bedient. Die eigentliche Funktionsweise der App wird jedoch in dem zugrundeliegenden Programmcode festgelegt. Dieser Code bildet die Schnittstelle zwischen der Oberfläche und der Elektronik der Laborsiebträgermaschine.
Zum Zeitpunkt des Projektbeginns im März 2023 lag bereits eine MATLAB® GUI mit entsprechendem Programmcode vor. [85]
Eine Neugestaltung soll jedoch die Bedienbarkeit intuitiver und einfacher gestalten sowie die Oberfläche dem aktuell Hardwarestand [64] angepasst werden. Der Programmcode sollte ebenso für die neugestaltete Oberfläche neu aufgesetzt werden. Der bestehende Code bot Potentiale zur Verbesserung und Vereinfachung, welches gerade bei der hohen Fluktuation des Projektes sinnvoll erschien.
In diesem Zug sollte die Vorbereitung für den Umbau auf die geplante Multi-MCU ebenfalls angelegt werden.

Melina Scherf, 24.03.2023

Ein Einführungsworkshop wurde durch Armin Rohnen durchgeführt. Dieser diente dazu, den Projektteilnehmern einen ersten Einblick in die Programmierung von MATLAB® in Kombination mit MicroPython zu geben.
Es wurde die generelle Funktion des MATLAB® App Designers vorgestellt und dafür eine erste Testoberfläche erstellt, welche einen Raspberry Pi initialisiert und eine Lampe per Schalter an- und ausschaltet.
Der dabei entstandene Code wurde von Melina Scherf kommentiert, um den anderen Projektteilnehmern, die zuvor noch nicht mit (Micro)Python gearbeitet hatten, eine eigenständige Nacharbeitung zu ermöglichen

Armin Rohnen, 16.02.2023

Für die Inbetriebnahme der Multi-MCU-Elektronik muss der Programmcode der MATLAB®-GUI entsprechend angepasst werden. Die bisherige Datenverarbeitung der STM32-MCU wird dabei auf drei Datenverarbeitungen aufgeteilt. Die angeschlossenen MCUs müssen dabei eindeutig identifiziert werden.