State machine beenden

hallo zusammen,
ich habe folgendes Problem, ich lese aus einem RFID-Sensor 2 Telegramme.
ein 11 und 18 Bytes langes Telegramm, wobei ich nur das erste benötige.
Deswegen kontrolliere ich die länge meiner Liste auf 11 Bytes, wenn es der Fall ist will ich die State machine verlassen und die Elemente der Liste ausgeben.
nur es verlässt halt nie die Schleife von der State Machine, auch wenn die Bedingung zum Verlassen erfüllt ist(Negieren eines Flags )
PS:Alle verwendeten Variablen sind schon deklariert.
kann mir mal Jemand erklären warum.
danke für jede Hilfe.

hier das Programm

byte RFID::Read_Block()
   { 
  RFID_Serialport.begin(115200);
  Senden(RB_Nutzbytesanzahl,RB_Nutzbyte1, RB_Nutzbyte2);
  digitalWrite(Send_Recievepin, LOW);
  int count=0;
  
do{
 switch(state)
  {
     case ack:
     startbyte=Serial.read();
     if (startbyte==0xAA){

     state= response;
      }
     else {
     state=ack;
     }
     break;
     
      case response:
      Serial.println("response");
      delayMicroseconds(1000); 
      myList.add(startbyte);
      do{        
        myList.add(Serial.read());            
        }while (Serial.available()>0);
         listlaenge= myList.size();
         Serial.println("listlaenge"); 
         Serial.println(listlaenge);  
         byte empf[listlaenge];
         for (int h = 0; h < listlaenge; h++) {
        empf[h] = myList.get(h);
        Serial.println(empf[h], HEX);     
      }
      if (listlaenge== 11 ){
      Serial.println("if condition to quit"); 
      arrayfull= false;
      state=ack;
      }
      else {
        Serial.println("else condition to continue"); 
      state=ack;
      }
      break;
   }
  }while(arrayfull= true);              // Programm kompiliert nicht darüber hinaus
  
    arrayfull= false;
    count=0;
    Serial.println("Die Elemente des gewünschten Telegramms"); 
    for (int h = 0; h < listlaenge; h++) {
    Serial.println(empf[h], HEX);     
   }        
 }

arrayfull= true
arrayfull == true

Oder einfach nur:
}while(arrayfull);

Denn (Merksatz):
Überflüssiger Kram erhöht nur die Fehlerwahrscheinlichkeit.

Schleifen in Statemachines?
Also blockierende Automaten?

Naja...
Ob das wohl eine gute Idee ist?

Versuche mal while(arrayfull == true); oder einfach while(arrayfull);

Das ist generell nicht gut. Sowas kann immer nur mit einem Delay am Anfang gehen weil die serielle Schnittstelle sehr langsam ist. Selbst bei relativ hohen Baudraten brauchst du mehrere Dutzend µs pro Byte. Sonst liest man ein Byte, available() wird 0 und man verlässt die Schleife

Besser ist es man fragt ab ob was im Eingangspuffer ist und wenn nicht dreht man Runden in loop(). Wenn man gar nichts empfangen will kann man auch einen Zustand "nichts tun" einführen

Wieso aus einer State Machine ausbrechen?
Wenn man eine State Machine programmiert hat ist man immer in einer State machine drinn. Wie gesagt auch das nichtstun bzw auf Eingaben warten ist ein status der state machine.

Grüße Uwe

combie:
arrayfull= true
arrayfull == true

Oder einfach nur:
}while(arrayfull);

Denn (Merksatz):
Überflüssiger Kram erhöht nur die Fehlerwahrscheinlichkeit.

Schleifen in Statemachines?
Also blockierende Automaten?

Naja...
Ob das wohl eine gute Idee ist?

danke es hat geklappt, dummer Fehler von mir

ich will dass die State machine nur läuft wenn Daten im Seriellen Datenpuffer sind, deswegen die Schleife.

nun klapt es, aber ich bekomme nicht die werte aus der Liste in meinem Array (empf[]) übertragen.
es befinden sich nur Nullen.
ausserdem hätte ich es gerne dass, mein Sensor bzw. mein Programm immer bereit zum Auslesen anderer Tags beit ist.
ich habe den Eindruck dass die State machine nur einmal durchlaufen wird obwohl das betreffende Programm in der Void Loop() ist ausgeführt,
hier die Ausgabe

⸮aah⸮response
listlaenge
11
AA
B
B
68
A
0
0
0
0
96
5D
if condition to quit
Die Elemente des gewuenschten Telegramms
0
0
0
0
0
0
0
0
0
0
0
⸮aah⸮response
listlaenge
18
AA
B
B
68
A
0
0
0
0
96
5D
AA
7
7
68
16
1D
6C
else condition to continue

pispa:
ich will dass die State machine nur läuft wenn Daten im Seriellen Datenpuffer sind, deswegen die Schleife.

Mach dir bitte den zeitlichen Ablauf bei der seriellen Übertragung klar! Ein Byte braucht 1 / Baudate * 10 Sekunden. Egal wie hoch du die Baudrate machst, der µC ist viel schneller

Die Daten kommen langsam Byte für Byte an. Du kannst dich also nie drauf verlassen dass da so viele Daten im Puffer sind dass alles in einer while Schleife ausgelesen werden kann. Das geht nur weil du da ein Delay von 1ms am Anfang hast, und das ist für 18 Bytes zu wenig

Es ist kein Problem zwischen den Bytes einfach loop() durchlaufen zu lassen und eventuell da noch andere Dinge zu tun

ich habe es jz um eine paar zustände erweirten sodass, dass alles in der State machine steht.
nun kommt springt das Programm nicht im "Fillin" zustand trotz erfüllt Bedingung.
warum das denn?

hier die Änderungen

byte RFID::Read_Block()
 { 
 switch(state)
  { 
    case senden:
    RFID_Serialport.begin(115200);
    Senden(RB_Nutzbytesanzahl,RB_Nutzbyte1, RB_Nutzbyte2);
    state= wait;
    break;
    
    case wait:
    digitalWrite(Send_Recievepin, LOW);
    if (Serial.available()>0)
    state= ack;
    else 
    state= wait;
    break;
        
     case ack:
     startbyte=Serial.read();
     if (startbyte==0xAA){

     state= response;
      }
     else {
     state=ack;
     }
     break;
     
      case response:
      Serial.println("response");
      delayMicroseconds(1500); 
      myList.add(startbyte);
      do{        
        myList.add(Serial.read());            
        }while (Serial.available()>0);
         listlaenge= myList.size();
         Serial.println("listlaenge"); 
         Serial.println(listlaenge);  
         byte empf[listlaenge];
         for (int h = 0; h < listlaenge; h++) {
        empf[h] = myList.get(h);
        Serial.println(empf[h], HEX);     
      }
      if (listlaenge== 11 ){
      Serial.println("if condition to quit"); 
      state=fillin;
      }
      else {
        Serial.println("else condition to continue"); 
      state=senden;
      }
      break;

      case fillin:
     Serial.println("Die Elemente des gewuenschten Telegramms"); 
    for (int h = 0; h < listlaenge; h++) {
    delayMicroseconds(1000);   
    Serial.println(empf[h], HEX); 
    }
     state=senden; 
     break;
   }       
 }

hier die Ausgabe

⸮aah⸮response
listlaenge
11
AA
B
B
68
A
0
0
0
0
96
5D
if condition to quit

pispa:
danke es hat geklappt, dummer Fehler von mir

Schön!
Das ist schon mal ein Anfang.
Der, mein, erster Tipp, war wichtig für dein akutes Problem.

pispa:
ich will dass die State machine nur läuft wenn Daten im Seriellen Datenpuffer sind, deswegen die Schleife.

Der, mein, zweiter Tipp(eigentlich eher Rhetorische Frage), wird dein gesamtes restliches (hobby?) Programmiererleben auf links krempeln und dir ein intuitives erfolgreiches Arbeiten ermöglichen.
Damit steht dir der Weg zu einem Genie offen! :o

Der andere Weg: (wird auch von vielen gegangen, führt aber oft in die Verzweiflung)

pispa:
ich will dass die State machine nur läuft wenn Daten im Seriellen Datenpuffer sind, deswegen die Schleife.

Das ist ein Irrtum!
bzw. eigentlich schon recht, aber du gehst von irrigen Voraussetzungen aus.

Tipp:
Wiederhole nur Dinge, welche sich festigen sollen.
Das nennt man u.a. Selbstsuggestion.
Vermeide Wiederholungen von irrigen Annahmen!

um eine paar zustände erweirte

Wirf die Schleifen da raus!

Du hast eine Schleife: loop()
Da müssen schon super gute Gründe für eine weitere Schleife kommen!
Und die sehe ich bei dir null-komma-gar-nicht

ich habe nur eine schleife drin, und Zwar die SWITCH schleife, oder was meinst du

do{
myList.add(Serial.read());
}while (Serial.available()>0);

for (int h = 0; h < listlaenge; h++) {
delayMicroseconds(1000);
Serial.println(empf, HEX);
}[/quote]
Beide Schleifen scheinen mir flüssiger als Wasser zu sein!
Und eine dritte findet sich da auch noch....
Das delay ? Welchen Sinn das hat?
Außerdem vermischt du da Eingabe-Verarbeitung-Ausgabe zu einem Monolithen.
> Zwar die SWITCH schleife,
Switch ist keine Schleife.
Schleifen wiederholen etwas.
Switch kann (und will) das nicht leisten.
Hmmmm .......
Leider sehe ich keinen gesamt Zusammenhang.
Selbst mit viel gutem Willen, und viel Fantasie, bekomme ich so keinen testbaren Code zusammen.

combie:
Beide Schleifen scheinen mir flüssiger als Wasser zu sein!
Und eine dritte findet sich da auch noch....

Das delay ? Welchen Sinn das hat?

Außerdem vermischt du da Eingabe-Verarbeitung-Ausgabe zu einem Monolithen.
Switch ist keine Schleife.
Schleifen wiederholen etwas.
Switch kann (und will) das nicht leisten.

Hmmmm .......
Leider sehe ich keinen gesamt Zusammenhang.
Selbst mit viel gutem Willen, und viel Fantasie, bekomme ich so keinen testbaren Code zusammen.

die erste schleife ist dafür da, dass alle Daten die im seriellen Dattenpuffer sind auszulen.
die zweite dient nur dem Anzeigen.

es mag kompliziert sein da durchzublicken, aber so bekomme ich auch zum Ziel.

pispa:
die erste schleife ist dafür da, dass alle Daten die im seriellen Dattenpuffer sind auszulen.
die zweite dient nur dem Anzeigen.

Da ist es wieder!

Erinnere dich an meinen Tipp:

Wiederhole nur Dinge, welche sich festigen sollen.
Das nennt man u.a. Selbstsuggestion.
Vermeide Wiederholungen von irrigen Annahmen!

pispa:
es mag kompliziert sein da durchzublicken, aber so bekomme ich auch zum Ziel.

Tja...
Warum einfach, wenn es auch kompliziert geht.

--
Ich schätze mal, dass ich an dieser Stelle aufgeben muss.
Denn es ist mir heute zu anstrengend, gegen Widerstände anzurennen.

Hallo pispa,

du solltest erstmal Abstand von deinem falschen Annahmen nehmen. Serenifly hat die Behandlung der seriellen schon auf den Punkt gebracht. combie hat dir den Weg aus der do-while gezeigt. Jetzt musst du den Ablauf verstehen.

Gegenfrage die dich vielleicht auf deinen Denkfehler aufmerksam macht. Stehst du den ganzen Tag am Briefkasten und wartest bis ihn jemand mit Post füllt? Hoffentlich nicht. Ich gehe nur nachschauen wenn ich vermute da könnte etwas drin sein. In der Zwischenzeit mache ich hoffentlich sinnvollere Dinge.

Deine Statemaschine.
Alle delay raus, wird für nichts benötigt. Das bremst nur den Ablauf aus.
Dein case "response" ist dein aktueller Zustand. Dort wird in switch immer wieder "hingesprungen" solange der case Zustand nicht geändert wird.

Ich würde den "read" nennen. Darin if (serial.available > 0) abfragen, wenn positiv serial.read() ausführen. Vorher macht das keinen Sinn. Buffer auf gewünschtes Ergebnis prüfen, wenn okay, case Zustand entsprechend ändern. Ansonsten bleibt case unverändert damit ein weiteres eingetroffenes Zeichen an der Seriellen beim nächsten Aufruf von switch verarbeitet werden kann. Deine Schleife ist also bis zur Bufferverarbeitung

loop > switch > case: read
loop > switch > case: read
loop > switch > case: read
... ohne Pause

Das bedeutet im case: read bzw. deinem response wird in keinem Fall! eine weitere Schleife benötigt.

Alles klar?

Hier mal eine sehr grobe Einlese-Routine ohne Zustandsmaschine:

void loop()
{
   if (readSerial())
   {
      //Auswertung
   }
}

bool readSerial()
{
    if (Serial.available() > 0)
    {
        //einlesen mit read()

        if(fertig)
          return true;
    }

   return false;
}

Die Lese-Funktion wird ständig aufgerufen und meldet wenn sie fertig ist (z.B. X Bytes eingelesen oder Endzeichen gefunden). Wenn sie noch nicht fertig ist kehrt sie wieder zurück um man kann in loop() noch andere Dinge tun. Wenn true kommt wertet man aus was da ist.

Ich verwende da im fertigen Code zwar eine while-Schleife in readSerial() statt dem if, aber i.d.R. ist da nur ein Byte im Puffer. Wenn mehr drin sind hat loop() länger gebraucht.