Go Down

Topic: Endliche automat einmal ausführen (Read 303 times) previous topic - next topic

Cazzz

Guten Abend liebe Gemeinde,

Ich bin noch recht neu in der arduino Welt.

Versuche mich dennoch zur Zeit an ein Projekt, der Getränke über 5 (oder mehr) Peristaltische pumpen das Getränk mischt (gleichzeitig).

Dabei benutze ich das von der Firma Nextion entwickelte HMI Display, womit ich schon ein klasse Menü hinzaubern konnte.

Damit soll also die Getränke Auswahl gesteuert werden, welches Getränk als Produkt entstehen soll (zb Pumpe 1 lässt orangen Saft ins Glas laufen, parallel soll Pumpe 2 den Wodka oder anderes laufen lassen).

Soweit zur Theorie.

Habe das ganze vor mit dem Rasperry pi 4 über node red parallel zu steuern.

Man hat also die Möglichkeit Getränke am Gerät selbst auszuwählen und parallel über ein Web interface mit zb einem tablet das ganze fernzusteuern.

Ich hatte mir bei dem vor haben das ganze als Schritt Kette vorgestellt wie in dem beispiel und nebenbei erwähnt super erklärten post:

Link

Da wenn die Schritt Kette abläuft ich aber auch das ganze abbrechen möchte (und auch andere Befehle ausführen möchte) , kann ich die delay nicht benutzen

Nun zu meinem Problem und Anlegen:

Habe die Schritt Kette aus dem beispiel erfolgreich über serial an das node red einbinden können, Problem dabei ist aber nun wenn die Schritt Kette abläuft hängt er in der Schleife fest und ich kann zb die gleiche oder andere Aktion nicht mehr durch führen.

Gibt es eine andere Möglichkeit die switch case Schritt Kette nur einmal ausführen zu lassen? Zb als eigenes Objekt immer auf zu rufen (zb void blabla() ;)

Ich hoffe ihr könnt mir helfen, bin heute leider nicht daheim daher kann ich euch noch keinen Code posten.

Mfg cazzz

Tommy56

Ich werde aus Deiner Beschreibung nicht schlau. Also warten wir mal, bis Du den Code posten kannst.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

HotSystems

Möglich ist vieles, aber ohne Sketch ist keine Hilfe möglich.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Cazzz

Versuche es mal anhand des unendlichen Automaten zu zeigen.

Code: [Select]
// Ampel Belegung der Ausgaenge
const byte RotPin = 2;
const byte GelbPin = 3;
const byte GruenPin = 4;
//
const boolean ein = HIGH;
const boolean aus = LOW;
//
const int ZEITROTPHASE = 3000;
const int ZEITGELBPHASE = 1000;
unsigned long ampelMillis;
unsigned long ampelIntervall;
//
enum ZUSTAENDE {ROT, ROTGELB, GRUEN, GELB};
byte zustand = ROT;

void setup() {
  // Definiert die Pins als Ausgang
  pinMode(RotPin, OUTPUT);
  pinMode(GelbPin, OUTPUT);
  pinMode(GruenPin, OUTPUT);
}

void loop() {
  // Ampelschaltung
 if (noderedvar==("ON")){    // Wenn ich in node red interface den Button drücke übergibt er die Variable ON
  if (millis() - ampelMillis >= ampelIntervall) {
    switch (zustand) {
      case ROT:
        digitalWrite(RotPin, HIGH);
        digitalWrite(GelbPin, LOW);
        digitalWrite(GruenPin, LOW);
        zustand = ROTGELB;
        ampelMillis = millis();
        ampelIntervall = ZEITROTPHASE;
        break;
      case ROTGELB:
        digitalWrite(RotPin, HIGH);
        digitalWrite(GelbPin, HIGH);
        digitalWrite(GruenPin, LOW);
        zustand = GRUEN;
        ampelMillis = millis();
        ampelIntervall = ZEITGELBPHASE;
        break;
      case GRUEN:
        digitalWrite(RotPin, LOW);
        digitalWrite(GelbPin, LOW);
        digitalWrite(GruenPin, HIGH);
        zustand = GELB;
        ampelMillis = millis();
        ampelIntervall = ZEITROTPHASE;
        break;
      case GELB:
        digitalWrite(RotPin, LOW);
        digitalWrite(GelbPin, HIGH);
        digitalWrite(GruenPin, LOW);
        zustand = ROT;
        ampelMillis = millis();
        ampelIntervall = ZEITGELBPHASE;
        break;
    }
  }
}



So hab ich mir das vorgestellt, so nun wie kriege ich es hin dass er aus dem switch case raus geht, mit dem beispiel wiederholt sich das ganze ja immer, also die Ampeln, möchte es aber nun einmal
Wie realisiere ich das?

Peter-CAD-HST

Moin Cazzz

Die Startbedingung für Deinen Automaten ist immer die folgende Bedingung:

noderedvar==("ON")

Ich schlage Dir die folgende Modifikation vor:

if (noderedvar==("ON"))  zustand = ROT;

Gruss Peter

und bleib gesund
- keep calm and carry on - mind the gap - beware of sharks! -

MicroBahner

#5
Mar 26, 2020, 09:05 am Last Edit: Mar 26, 2020, 09:06 am by MicroBahner
Versuche es mal anhand des unendlichen Automaten zu zeigen.
Auch das it ein 'endlicher' Automat. Denn er hat nur eine endliche Anzahl von Zuständen.

So hab ich mir das vorgestellt, so nun wie kriege ich es hin dass er aus dem switch case raus geht, mit dem beispiel wiederholt sich das ganze ja immer, also die Ampeln, möchte es aber nun einmal
Z.B. indem Du einen weiteren Zustand 'STOP' definierst. Nach dem letzten Schritt gehst Du nun in den Zustand STOP. Und dort machst Du nichts anderes, als auf ein Ereignis zu warten, um den Ablauf wieder zu starten. Natürlich darfst Du nicht 'blockierend' auf das Ereignis warten. Solange es noch nicht eingetreten ist, geht's ganz normal hinter dem Switch weiter. Du musst ja nicht aus dem switch rausgehen. Es reicht ja, wenn in dem neuen Zustand STOP nichts weiter passiert.
Gruß, Franz-Peter

DrDiettrich

Im Grunde handelt es sich um eine Zeit- bzw. Ereignissteuerung, wann welche Pumpe ein und wieder ausgeschaltet werden soll. Diese Zeitpunkte und Aktionen werden pro Rezept vorgegeben, am einfachsten in einem Array. Dann wird in loop() auf das Erreichen des nächsten Schaltpunkts gewartet, die zugehörige Aktion (Pumpe ein/aus) ausgeführt, und das Warten auf den nächsten Zeitpunkt eingestellt. Zuletzt wird die Abfrage gestoppt wenn das letzte Element des Arrays abgearbeitet ist, dann wird stattdessen auf die nächste Bestellung gewartet.

Der zugehörige Automat hat also nur zwei Zustände: Array abarbeiten und auf Bestellung warten.

michael_x

Quote
Der zugehörige Automat hat also nur zwei Zustände
Je weniger Zustände ein Automat hat, um so mehr Automaten braucht man. Immerhin bleibt es eine endliche Anzahl Automaten ;)

Für die eigentliche Problemstellung "Die Schrittketten müssen jederzeit abbrechbar sein" ist die Aufteilung in mehrere Automaten aber sinnvoll. Bleibt zu entscheiden / überlegen, ob das STOP - Ereignis den "inneren" Rezept-Automaten im aktuellen Zustand lässt oder auf "kein Rezept gewählt" zurücksetzt.
(Oder der übergeordnete Automat kennt 3 Zustände: BETRIEB - PAUSE - STOP)

DrDiettrich

Ich komme mit obigem Automaten als einzigem aus. Wenn Du mehr brauchst, machst Du irgendwas falsch.

Auch erscheint es mir ziemlich unsinnig, das Mischen von Getränken vorzeitig unkontrolliert abzubrechen - dann laufen ggf. mehrere Pumpen weiter!

michael_x

Wer überall einen Endlichen Automaten sieht, sieht auch hier einen:
Quote from: DrDiettrich
eine Zeit- bzw. Ereignissteuerung, wann welche Pumpe ein und wieder ausgeschaltet werden soll. Diese Zeitpunkte und Aktionen werden pro Rezept vorgegeben
Wenn du sagst, das ist kein Zustandsautomat sondern eine "Zeit- bzw. Ereignissteuerung", soll es mir auch recht sein.

DrDiettrich

Wenn sich während des Ablaufs "Rezept" kein Zustand ändert, dann ist da auch kein Automat.

michael_x

Quote
Wenn sich während des Ablaufs "Rezept" kein Zustand ändert, dann ist da auch kein Automat.
Klar.

Wenn ein Rezept aus mehr als einem Schritt besteht (oder man es so formulieren möchte), kann man dies schön in einer Zustandsvariablen verwalten. Gehe mal davon aus, dass mindestens die Ventile zu unterschiedlichen Zeiten schalten.

Ein Cocktailmixer-Arduino ist auf jeden Fall eindrucksvoller, wenn man erkennen kann, wieviel Mühe er sich macht bis das Ganze fertig ist. :)

DrDiettrich

Der Stand der Rezeptur wird mit einem Array-Index verwaltet, der einfach weitergezählt wird. Die restliche Verarbeitung ist für jeden Eintrag gleich. Dieser Zustand wird nur verlassen, wenn der Index die Array-Größe übersteigt.

Go Up