Switch statt multiple loops?

Hallo,
ich schreibe grad an einer Steuerung für mein Zimmer mit Relaisschaltungen, Sensoren, usw. Das Problem ist, wie kann ich quasi gleichzeitig die Gui und den Rest ausführen? Erstmal gegooglet und auf diese Seite gestoßen(http://arduino.cc/en/Tutorial/MultipleBlinks). Soweit ich das verstanden habe, muss man delays einbauen, damit auch sichergestellt wird, dass alle Schleifen auch wirklich laufen.
Dann ein paar Stunden später beim Müsli machen komme ich auf die Idee stattdessen switch-Befehle zu verwenden, wie in dem Beispiel unten. Meine Frage nun, was haltet ihr davon? Gibt es irgendwelche No-Goes, die ich begangen habe? Ich bin leider nicht so der C-profi.

mit multiple Loops(Scheduler.h)

#include UTouch
#include Scheduler

int x, y;
UTouch touch(6,5,4,3,2);

void setup(){}


void loop(){   
     SendData();
     while(!Serial.available()){
       delay(10);
     }
     char c = Serial.getData();
}

void loop2(){
     ReceiveData();
     while(!touch.dataAvailable()){
       delay(10);
     }
     x= UTouch.getX();
     y= UTouch.getY();
  
}

void SendData(){}
void ReceiveData(){}

mit switch

#include UTouch

int loop1=0;
int loop2=0;
int x, y;
UTouch touch(6,5,4,3,2);

void setup(){}


void loop(){
  
  switch(loop1){
   case 0:
     SendData();
     loop1++;
   case 1: 
     while(!Serial.available()){
      break;
     }
    loop1++;
   case 2:
     char c = Serial.available();
     loop1=0;
     break;
   deafult:
     loop2=0;
  }
  
  switch(loop2){
     case 0:
     ReceiveData();
     loop2++;
   case 1: 
     while(!touch.dataAvailable()){
      break;
     }
    loop2++;
   case 2:
     x= UTouch.getX();
     y= UTouch.getY();
     loop2=0;
     break;
   deafult:
     loop2=0;
  } 
}

void SendData(){}
void ReceiveData(){}

Delay = böse ]:smiley:

Ich habe noch nicht rumrissen, worum es Dir tatsächlich geht. Kannste das nochmal verdeutlichen?

Es gibt Stellen in meinem richtigen Code wie

while(!touch.dataReady){}
int x = touch.getX()

da wird dann gewartet bis der touchscreen berührt wir, das heißt es wird auch nicht im Hintergrund z.B. die Zeit synchronisiert oder Messdaten empfangen oder Steckdosen an und ausgeschaltet. Das will ich umgehen, indem immer anstatt gewartet wird, anderer Code ausgeführt wird. Und damit der Arduino weis wo er aufgehört hat, will ich einen switch dafür benutzen.

Wenn du diesen Scheduler verwenden willst, hast du das wichtigste vergessen:

   Scheduler.startLoop(loop2);

Aber klassischerweise laufen alle Aktionen quasi parallel, wenn man kein delay() verwendet.
Hochtrabend "kooperatives multitasking" genannt:
Jede Funktion macht nur (max.) 1 Aktion, bzw. erkennt normalerweise, dass nichts zu tun ist, und beendet sich sofort wieder.

So wie du es wohl mit deiner switch Lösung vorhast, wobei da ein paar Ungereimtheiten drin sind:

  • ohne break; wird der folgende case mit ausgeführt

  • Serial.available() liefert die Anzahl Zeichen, nicht das Zeichen selbst.

  • Variablennamen und Funktionsnamen sollten unterschiedlich sein.

  • Diese Sequenz macht nichts, sieht aber gefährlich aus:

     while(!touch.dataAvailable()){
      break;
     }
  • gefährlich, weil while meist so schlecht wie delay ist, da etwas längere Zeit hängen kann
  • hier Unsinn, weil entweder dataAvailable() == false ist und die while Schleife mit break verlassen wird, oder die while Schleife beendet wird.

Aber prinzipiell ist ein switch schon gut, um sich zu merken, wo in einer Steuerungssequenz man grade ist.

  • ohne break; wird der folgende case mit ausgeführt

Das war durchaus so beabsichtigt. Wenn hier das touchscreen berührt wird soll sofort die position gespeichert werden

  • Serial.available() liefert die Anzahl Zeichen, nicht das Zeichen selbst.
  • Variablennamen und Funktionsnamen sollten unterschiedlich sein.

Das ist hier nur ein Beispiel zur Verdeutlichung meiner Idee. Ich hab die Methodennamen nicht alle im kopf, va. wenn ich damit sonst nichts zu tun habe.

  • hier Unsinn, weil entweder dataAvailable() == false ist und die while Schleife mit break verlassen wird, oder die while Schleife beendet wird.

Da habe ich nicht genau überlegt. Wie lautet denn der Syntax, wenn ich mit dem break den switch verlassen will?

MrSkuff:

  • ohne break; wird der folgende case mit ausgeführt

Das war durchaus so beabsichtigt. Wenn hier das touchscreen berührt wird soll sofort die position gespeichert werden

OK, aber wofür dann der extra case ?

Die Variableint loop1brauchst du doch nur, um bei einem neuen loop-Aufruf in einem Zwischenzustand weiterzumachen, wo du vorher aufgehört hast. Und ohne break; hörst du immer mit loop1=0; auf.

Generell solltest du alle while durch ein if ersetzen. Es reicht, in einem Durchlauf nur 1 Zeichen einzulesen: wenn noch mehr erwartet wird, kommt das eben in einem der nächsten Durchläufe.
Hier (Umwandlung char* in char - #3 by Serenifly - Deutsch - Arduino Forum) hat Serenifly ein schönes Beispiel, ( denke dir Serial statt Wire). Am Ende von loop kannst du z.B. eine beliebige andere Funktion anfügen, die gleichzeitig mit der demo-Funktion "Text seriell einlesen" ausgeführt würde...

void loop()
{
   char* SerialData = readString(); // reads max 1 char, returns NULL if input not complete
   if ( SerialData )  Bearbeiten(SerialData); 
   TouchScreenInput();
   SendData(); // falls was zu senden ist
 } 

void TouchScreenInput() 
{
  if (!touch.dataAvailable()) return;  // keine Eingabe, sofort fertig

   int  x= UTouch.getX();
   int  y= UTouch.getY();

  // hier könnte man evtl. eine switch Variable verwenden, um eine Menüführung zu realisieren
  
}

Jup. Ich sehe nicht wozu man da extra einen Scheduler braucht. Das läuft bei mir genauso mit Abfrage von Serial und Touchscreen hintereinander in loop(). Je nachdem in welchem Menü man ist, wird dann noch die Uhr oder Temperatur angezeigt.

MrSkuff:
Wenn hier das touchscreen berührt wird soll sofort die position gespeichert werden

definiere "sofort"!

Wenn du das in normalen seriellen bzw "kooperativem" Multitasking programmierst, dann liegen deine loop() durchläufe im Bereich weniger ms. Ich komme bei komplexen Programmen selten über 20ms. Selbst 100ms sind für einen Microkontroller eine Ewigkeit. Für den Menschen ist das aber noch "sofort".

Das kann z.B. so aussehen: (als Pseudocode)

void loop(){
  Tastenlesen();
  AnzeigeAkutaliesieren();
  Relaisansteuern();
}
void Tastenlesen(){
  if Tastegedrückt{
     verarbeiten;
  } else return;
}
void AnzeigeAkutaliesieren(){
  if Wertegeändert{
    neue Werte schreiben;
  else return;
}
void Relaisansteuern(){
  if neue Ausgangswerte;
  else return;
}

Also, dann hau ich jetzt mal meine Kommentar raus.

OK, aber wofür dann der extra case ?

Ich hab das nur schnell hingetippt, damit man das Prinzip versteht, ich drücke mich nicht immer verständlich genug aus.

Generell solltest du alle while durch ein if ersetzen

Werde ich berücksichtigen beim coden.

Jup. Ich sehe nicht wozu man da extra einen Scheduler braucht. Das läuft bei mir genauso mit Abfrage von Serial und Touchscreen hintereinander in loop(). Je nachdem in welchem Menü man ist, wird dann noch die Uhr oder Temperatur angezeigt.

Das ist nur ein Beispiel zum verstehen vom Prinzip. Es geht bei mir darum:
Wenn sowas wie: if(touch.dataAvailable()){...} mitten im Code vorkommt und wenn dataAvailable==false ist, dann wird der Code vor if(touch.dataAvailable()){...} bei dem einfachen hintereinanderfügen in eine Loop nochmals ausgeführt. Das soll nicht passieren.

Wenn du das in normalen seriellen bzw "kooperativem" Multitasking programmierst, dann liegen deine loop() durchläufe im Bereich weniger ms. Ich komme bei komplexen Programmen selten über 20ms. Selbst 100ms sind für einen Microkontroller eine Ewigkeit. Für den Menschen ist das aber noch "sofort".

dann ist aber auch egal, ob zuerst dieser codeblock ausgeführt wird oder ein anderer

Danke für die Kommentare, Verbesserungen und Denkanstöße

MrSkuff:
Es geht bei mir darum:
Wenn sowas wie: if(touch.dataAvailable()){...} mitten im Code vorkommt und wenn dataAvailable==false ist, dann wird der Code vor if(touch.dataAvailable()){...} bei dem einfachen hintereinanderfügen in eine Loop nochmals ausgeführt. Das soll nicht passieren.

Man kann das um Statusvariablen und/oder Rückgabewerte erweitern, so dass Code-Teile nur ausgeführt werden wenn woanders was gemacht wurde.