Da wir nun endlich den Prüfungsaufbau vollständig modifizieren können, beseitigen wir die größte Schwachstelle des Systems:
Die Trennung des induktiven und kapazitiven Sensors!!!
Das alte Modell

Ablauf:
- Der Zylinder m1 blockiert die Rutsche
- Wenn ein Würfel am kapazitiven Sensor „s_rutsche“ (blau) ankommt, wird m1 eingefahren und der Würfel rutscht herunter
- Der Würfel erreicht den induktiven Sensor „s_metall“ (silber)
- Auswertung findest statt: Handelt es sich um ein Metallwürfel, bekommt man ein 1 Signal, bei einem Plastikwürfel eine 0.
Schwachstelle: Woher sollte man nun wissen, ob der Würfel überhaupt unter dem Sensor „s_metall“ liegt, sich auf der Rutsche verkeilte oder gar nicht los rutschte? GING NICHT!
Abhilfe: Man ließ eine Zeit ablaufen. Nach Ablauf musste entweder eine 1 an „s_metall“ stehen oder es wurde vermutet, dass es sich um einen Plastikwürfel handelt…
Das NEUE Modell

ENDLICH bekommen wir die Sensorwerte parallel! Dies bedeutet nun folgenden Ablauf:
- Der Zylinder „m1“ ist immer eingefahren
- Ein Würfel kann frei die Rampe herunterrutschen
- Sensor „s_rutsche“ (blau) bekommt ein 1 Signal, fährt Zylinder „m1“ aus und sperrt weitere Würfel
- In genau diesem Moment, wenn „s_rutsche“ eine 1 hat, können wir den Sensor „s_metall“ verlässlich auswerten! Hat dieser jetzt eine 1, ist es Metall und bei einer 0 ganz sicher Plastik!
Der Vorgang der Sortierung hat sich zum alten Modell nicht geändert, aber der Quelltext für diese Änderung!
class AutomatikSeri(Thread):
"""Thread fuer den Automatikbetrieb."""
def __init__(self, rpi):
"""Instanziiert den Automatik-Thread."""
super().__init__()
self.evt_ende = Event()
self.daemon = True
self.rpi = rpi
self.metall = False
def run(self):
"""Wird durchgehend ausgefuehrt, wenn Anlage im Automatikbetrieb.
Diese Funktion lauft durchgehend und Regelt die Ablaeufe fuer den
Automatikbetrieb. Die wait() Funktionen bekommen immer das Exit-Event
self.evt_ende uebergeben, damit diese beim Beenden vom Automatikbetrieb
abgebrochen werden. Da als Wert >0 zurueckgegeben wird, brechen wir
die Verarbeitung an der Stelle ab. Die while-Schleife wird dann
verlassen.
Ungewoehnlich ist evtl. das sich das Programm DAUERHAFT in dieser
Schleife aufhaelt. Die automatische Prozessbildaktualisierung von
RevPiModIO synchronisiert im Hinterhund staendig unsere Inputs und
Outputs. Und ein Blockieren des Programms verhindern wir damit, dass
diese Funktion als Thread ausgefuehrt wird.
"""
# Lampe h_start Einschalten
self.rpi.io.h_start.value = True
# Automatikbetrieb auf virtuellem Device setzen
self.rpi.io.aktivauto.value = True
# Automatisch Grundstellung herstellen
funccatalog.band.grundstellung()
funccatalog.zylinder.grundstellung()
while not self.evt_ende.is_set():
# Warten, bis ein Wuerfel am Sensor s_rutsche erkannt wird
ec = self.rpi.io.s_rutsche.wait(
exitevent=self.evt_ende, okvalue=True
)
if ec > 0:
break
# Zylinder m1 ausfahren
funccatalog.zylinder.set_m1(True)
# Kleines delay für den Metallsensor
ec = self.rpi.io.s_metall.wait(
exitevent=self.evt_ende,
okvalue=True, timeout=100
)
if ec > 0:
print("kunststoff erkannt")
self.metall = False
else:
print("metall erkannt")
self.metall = True
# Prüfen ob Magazine voll sind
if self.checkmagazinvoll():
self.aufhaldefahren()
# Zylinder m1 einfahren
funccatalog.zylinder.set_m1(False)
continue
print("motor los")
funccatalog.band.set_lahm_rechts()
# Warten bis Würfel bei Magazin 1 angekommen ist
ec = self.rpi.io.s_magazin1.wait(
exitevent=self.evt_ende,
timeout=7000
)
if ec <= 0 and self.metall:
# Warten bis Würfel bei Magazin 2 angekommen ist
ec = self.rpi.io.s_magazin2.wait(
exitevent=self.evt_ende,
timeout=3000
)
print("motor aus")
funccatalog.band.grundstellung()
if ec == 1:
# exitevent ausgelöst
break
elif ec == 2:
# timeout überschritten
funccatalog.anlage.stoerung = True
break
# Auf Motorstopp warten
ec = self.rpi.io.fu_motoran.wait(
exitevent=self.evt_ende,
timeout=1000
)
if ec == 1:
# exitevent ausgelöst
break
elif ec == 2:
# timeout überschritten
funccatalog.anlage.stoerung = True
break
if self.metall:
# Zylinder m3 ausfahren und warten auf Endlage
print("auswerfen")
funccatalog.zylinder.set_m3(True)
ec = self.rpi.io.m_m3_ausgefahren.wait(exitevent=self.evt_ende)
if ec > 0:
break
# Magazinzähler Metall erhöhen
self.rpi.io.magazin2.value += 1
# Zylinder m3 einfahren
funccatalog.zylinder.set_m3(False)
else:
# Zylinder m2 ausfahren und warten auf Endlage
print("auswerfen")
funccatalog.zylinder.set_m2(True)
ec = self.rpi.io.m_m2_ausgefahren.wait(exitevent=self.evt_ende)
if ec > 0:
break
# Magazinzähler Kunststoff erhöhen
self.rpi.io.magazin1.value += 1
# Zylinder m2 einfahren
funccatalog.zylinder.set_m2(False)
# Zylinder m1 einfahren
funccatalog.zylinder.set_m1(False)
# Grundstellung einnehmen
funccatalog.band.grundstellung()
if self.evt_ende.is_set():
funccatalog.zylinder.grundstellung()
# Lampen ausschalten
self.rpi.io.h_start.value = False
# Automatikbetrieb auf virtuellem Device zurücknehmen
self.rpi.io.aktivauto.value = False
def aufhaldefahren(self):
"""Faehrt Wuerfel auf die Halde."""
print("magazin voll - auswerfen")
funccatalog.band.set_schnell_rechts()
self.evt_ende.wait(3)
funccatalog.band.grundstellung()
def checkmagazinvoll(self):
"""Prueft ob eines der Magazine voll ist.
@return True, wenn eines der Magazine voll ist"""
return (
self.metall and self.rpi.io.warn_mag2full.value or
not self.metall and self.rpi.io.warn_mag1full.value
)
def stop(self):
"""Beendet den Automatikbetrieb."""
self.evt_ende.set()
