Revolutionsumbau 2.0 freestyle – Sensoren

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()