Grenzen der Verschachtelten Wenn-Funkton

Hallo Zusammen,

Gibt es denn Grenzen für eine Verschachtelte Wenn-Funktion ?

Denn ich habe hier einen Sketch der IR-Befehle sendet wenn ich auf meine iPhone-Applikation einen entsprechenden Knopf drücke.

            }
          if(readString.indexOf("r17") > -1) {
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55AEA15,32); // receiver treble -
            delay(10);}
            
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55AC03F,32); // receiver treble -
            delay(10);}
            
            
            }
          else if(readString.indexOf("r18") > -1) {
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55AEA15,32); // receiver treble +
            delay(10);}
            
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55A40BF,32); // receiver treble +
            delay(10);}
            
            
            }
          else if(readString.indexOf("r19") > -1) {
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55A21DE, 32); // receiver taste ok
            delay(10);}
            
            
            }
          else if(readString.indexOf("r20") > -1) {
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55A01FE,32); // receiver taste hoch
            delay(10);}
            
            
            }
          else if(readString.indexOf("r21") > -1) {
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55A817E,32); // receiver taste runter
            delay(10);}
            
            
            }
          else if(readString.indexOf("r22") > -1) {
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55AC13E, 32); // receiver taste links
            delay(10);}
            
            
            }
          else if(readString.indexOf("r23") > -1) {
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55A41BE, 32); // receiver taste rechts
            delay(10);}
            
            
            }
          else if(readString.indexOf("r24") > -1) {
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55ABA45, 32); // receiver return
            delay(10);}
            
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55A906F, 32); // receiver return
            delay(10);}
            
            
            }
          else if(readString.indexOf("r25") > -1) {
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55AD926, 32); // receiver setup home mue
            delay(10);}
            
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55A6B94, 32); // receiver setup home mue
            delay(10);}
            
            
            }
          else if(readString.indexOf("r26") > -1) {
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55A3AC5, 32); // receiver BD
            delay(10);}
            
            for (int i = 0; i < 3; i++) {
            irsend.sendNEC(0xA55A03FC, 32); // receiver BD
            delay(10);}
            
            
           
            
           
         
           }
            


          //clear string for next read
          readString="";
          
          

          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    
    // close the connection:
       
    client.stop();
  }  
}

um es posten zu können habe ich einige Verschachtelungen herausgenommen die aber bis auf den gesendeten Code gleich sind

Die Grenze liegt wohl eher in readString ....

michael_x:
Die Grenze liegt wohl eher in readString ....

Hab ich auch schon geändert. Habe etliche Nullen An die Zahl von readString gehängt aber das kommt auf das gleiche raus.

Oder wie meinen Sie das ?

geforce1994:
Gibt es denn Grenzen für eine Verschachtelte Wenn-Funktion ?

Die Grenzen sind immer:
a) der begrenzte RAM-Speicher und
b) der begrenzte Flash-Programmspeicher

Wenn Du in Deinen if-Zweigen immer wieder praktisch denselben Code ausführst, der sich nur in wenigen Parametern unterscheidet, bist Du sowohl vom Flash- wie auch RAM-Speicherverbrauch irgendwann besser dran, aus einer Schleife heraus eine Funktion mit Parametern aufzurufen statt ellenlange if-Zweige zusammenzuschreiben mit praktisch identischem Bearbeitungscode darin.

Versteh ich nicht ? Könnten sie mir Konkrete Beispiele nennen wie ich mein Sketch abändern müsste ?

geforce1994:
Versteh ich nicht ? Könnten sie mir Konkrete Beispiele nennen wie ich mein Sketch abändern müsste ?

Eigentlich sind wir hier im Forum alle per Du.

Anyway, ich habe mal einen Sketch gemacht und zeige da mal ein paar Dinge, die vielleicht helfen können, die Komplexität mit den vielen if-Zweigen und überhaupt in den Griff zu bekommen.

void irsendOneCode(unsigned long code)
// diese Funktion sendet einen Code mit abschließend 10 ms delay
{
  for (int i = 0; i < 3; i++) {
    irsend.sendNEC(code,32); // receiver treble -
  // Kommentarstriche in der nächsten Zeile entfernen für Serial-Debug
//  Serial.println(code,HEX);
  delay(10);}
}

void irsendTwoCodes(long code1, long code2)
// diese Funktion ruft für jeden der beiden Codes die Funktion irsendOneCode auf
{
  irsendOneCode(code1);
  irsendOneCode(code2);
}

void tuWas(char* readString)
{
  if (readString[0]!='r') return; // kein Anfang mit 'r' ==> return
  int was=atoi(&readString[1]);  // Zahl nach dem 'r' in Variable was einlesen
  switch (was) // Und abhängig von der Variablen irgendwas senden
  {
    case 17: irsendTwoCodes(0xA55AEA15,0xA55AC03F);break;
    case 18: irsendTwoCodes(0xA55AEA15,0xA55A40BF);break;
    case 19: irsendOneCode(0xA55A21DE); break;
    case 20: irsendOneCode(0xA55A01FE); break;
    case 21: irsendOneCode(0xA55A817E); break;
    case 22: irsendOneCode(0xA55AC13E); break;
    case 23: irsendOneCode(0xA55A41BE); break;
    case 24: irsendTwoCodes(0xA55ABA45,0xA55A906F); break;
    case 25: irsendTwoCodes(0xA55AD926,0xA55A6B94); break;
    default: Serial.println(F("Code not defined")); // Sollte nicht vorkommen
  }
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}


char readString[11]; // char Array für String von max. 10 Zeichen Länge

void loop() {
  // hier jetzt eigentlich den String in das char-Array ein lesen,
  // aber ich bilde stattdessen einen Zufalls-String zwischen "r17" und "r25"
  sprintf(readString,"r%02d",random(17,26));
  // und rufe mit dem so "empfangenen" String die tuWas-Funktion auf
  tuWas(readString);
}

Mein erster Ratschlag wäre, komplett auf String-Objekte im Programm zu verzichten und nur C-Strings (char-Arrays) zu verarbeiten. Alle Library-Funktionen arbeiten mit char-Arrays und darüber hinaus sind String-Objekte in Arduino fehlerhaft implementiert, so dass es nach kürzerer oder längerer Programmlaufzeit zu Programmabstürzen kommen kann, wenn String-Objekte unter Arduino verwendet werden.

Der zweite Ratschlag von mir ist, RAM-Speicher zu sparen und nur möglichst wenig String-Konstanten zu verwenden. Statt im Code lauter Strings wie "r17", "r18", "r19", "r20" stehen zu haben, von denen jede einzelne 4 Bytes des kostbaren RAM-Speichers benötigt, schaue ich einfach in der tuWas-Funktion als erstes nach, ob der String mit 'r' anfängt und lese die nachfolgende Zahl in einen Integer-Wert "was" ein. Danach folgt eine switch-case Abfrage, in der nicht auf Strings, sondern auf Integer-Werte verglichen wird, was deutlich RAM-Speicher spart.

Last but not least scheint es so zu sein, daß zu jedem Kommando immer entweder ein oder zwei Codes je dreimal gesendet werden soll, mit anschließend 10 ms Pause. Wenn das bei hundert verschiedenen Codes gemacht werden soll und es quasi nur zwei Varianten gibt (ein Code oder zwei Codes senden), dann schreibt man sich natürlich am besten eine Funktion zum Senden von einem bzw. zwei Codes und ruft diese nur mit passendem Parameter auf, statt immer mehrere Zeilen Codes hinzuschreiben.

Eigentlich sind wir hier im Forum alle per Du.

Fühlst Du Dich dann auch so alt? :wink: :wink:

Viele Funktionen (als Maschienencode übersetzt) speichern Werte in Stack ab um bei Beendigung wieder auf der richtigen Programmstelle weiterzumachen. Darum kann mann nicht unendlich verschachteln. Indicativ 20 bis 30 Verschachtelungen würde ich denken, daß sie ohne Probleme funktionieren. Die Verbesserungen die jurs vorgeeschlagen hat sind sicher gut umzusetzen und in Zukunft auch zu beherzigen.

Der Stack ist ein reservierter RAMteil wo der Prozessor daten (zb Rücksprungadressen) ablegt, um sie später wieder zu lesen.
Grüße Uwe

hi,

erstmal:
ich schreib eine lange wurst als antwort, beim senden ist das forum weg :fearful:
passiert das bei euch auch so oft in den letzten wochen?

zweitmal:
uwe, ich glaube, mich zu erinnern, daß der stack kein reservierter bereich ist, sondern das ende des RAM.
und daß rücksprungadressen dann immer "vorn" drangesetzt werden und umgekehrt auch von "vorn" wieder gelesen und gelöscht werden, bis am ende des programms kein stack mehr da ist. dadurch braucht man keine zeiger auf einzelne rücksprung-adressen, sondern immer nur auf den beginn des stacks.

gruß stefan (der, der die antwort vor dem senden brav kopiert, woraufhin alles funktioniert. bis er wieder drauf vergißt.)

Eisebaer:
und daß rücksprungadressen dann immer "vorn" drangesetzt werden und umgekehrt auch von "vorn" wieder gelesen und gelöscht werden, bis am ende des programms kein stack mehr da ist. dadurch braucht man keine zeiger auf einzelne rücksprung-adressen, sondern immer nur auf den beginn des stacks.

So kenne ich das auch FIFO halt - frist in first out, habe vor langer zeit mal einen 8051 in ASM programmiert.

Eisebaer:
hi,

erstmal:
ich schreib eine lange wurst als antwort, beim senden ist das forum weg :fearful:
passiert das bei euch auch so oft in den letzten wochen?

Als vielschreiber kann ich Dir sagen daß es mir eigentlich nicht passiert ist.

Eisebaer:
zweitmal:
uwe, ich glaube, mich zu erinnern, daß der stack kein reservierter bereich ist, sondern das ende des RAM.
und daß rücksprungadressen dann immer "vorn" drangesetzt werden und umgekehrt auch von "vorn" wieder gelesen und gelöscht werden, bis am ende des programms kein stack mehr da ist. dadurch braucht man keine zeiger auf einzelne rücksprung-adressen, sondern immer nur auf den beginn des stacks.

gruß stefan (der, der die antwort vor dem senden brav kopiert, woraufhin alles funktioniert. bis er wieder drauf vergißt.)

Ich weiß jetzt nicht wie es beim ATmega aussieht aber beim 6510 war der Adresspointer des Staks 8 Bit lang und darum war der Stack auf 256 Byte begrenzt.
nachgelesen auf http://www.atmel.com/Images/doc8161.pdf 6.5 Stack Pointer
Beim ATmega328 ist er 16 Bite lang und kann darum theoretisch 64kByte RAM adressieren. Darumist der Stack nur durch das vorhandere RAm und dessen anderweitige nutzung begrenzt.

Grüße Uwe

hi,

So kenne ich das auch FIFO halt

nein, eben nicht. stack ist LIFO. wer zuletzt kommt, mahlt zuerst.

gruß stefan

Ausser den Rücksprungadressen sind übrigens noch alle lokalen Variablen einer Funktion auf dem Stack, aber eigentlich egal:

Wenn der Stack die statischen/globalen Variablen kaputt macht ( oder umgekehrt ) ist alles zu spät !

Die "Verschachtelte Wenn-Funktion" des OP , belastet den Stack nicht sonderlich, denn sie ist eher eine elende
if ... else if ... else if ... Kette.

geforce sollte besser sein String Objekt durch ein char [] ersetzen.
Ich fürchte, "r17" ... "r26" steht immer an der geichen Stelle in readString und das Ganze ist also nur eine Quälerei des armen Arduino :wink:


Und vor "langen Würsten" schützt sich das Forum effektiv durch zeitweises Verschwinden. Das kann ich bestätigen.

Danke für die bisherige Hilfe jedoch komme ich einfach nicht weiter :~

wäre jemand so nett mir dabei zu helfen meinen Sketch so abzuändern das dieser Befehle von meiner App entgegen nimmt und dann den jeweiligen case ausführt.

nach betätigen eines Buttons in meiner App sendet diese einen Befehl der wie folgt aussieht /?b=1

Wie muss ich den Sketch abändern oder neu schreiben so dass dann ein case ausgeführt wird ?

LG Nico

Wenn wir annehmen, der client sendet eine der drei Anforderungen
"..... /?b=1"
"..... /?b=2"
"..... /?b=3"
Dann kann dein server das mit etwas wie in diesem Code-Schnipsel auswerten:

   char inbuf[80];
   EthernetClient client = server.available();
   if (client == true) {
      char* ip = inbuf;
      // read bytes from the incoming client 
      while ( client.available() )  // einfachste Form, einzeilige Anforderung des Client in einem Block 
         *ip++ = client.read();       // mit ausreichend Speicherplatz
      *ip = 0;    // Endekennung
      ip = strstr(inbuf,"/?b=") ;  // suche den erwarteten Parameter 
      if (ip)  {
         // Zeile richtig empfangen
         ip += 4; // zeigt jetzt hinter das '='
         switch (*ip) {    // *ip sollte eines der definierten KommandoZeichen sein
         case '1' : 
            DoFunction1();
            break;
         case '2' : 
            DoFunction2();
            break;
         case '3' : 
            DoFunction3();
            break;
         }
      }
   }

Auf Feinheiten / Fehlerprüfung im Dialog zwischen deinem EthernetServer und einem Client hab ich hier verzichtet...
Die jeweils aufgerufenen Funktionen DoFunction1() usw. fehlen natürlich auch.

Wenn dazu weitere Fragen auftauchen, wäre es schön, wenn du deinen aktuellen Stand des Problems hier nochmal postest. Mit möglichst genauer Beschreibung des aktuellen Problems. ( Das hier oben sollte "einen von drei cases ausführen", Problem also gelöst :wink: )

Super Danke soweit funktioniert es auch wie ich das möchte :slight_smile: nun ist die frage wie realisiere ich dies wenn hinter dem = eine 2 oder 3 stellige zahl steht ?
weil ich möchte ja IR Codes versenden und wenn man mal die Fernbedienung durchzählt gibt es da einige Befehle :stuck_out_tongue:

Habe eben auch gemerkt dass der Arduino nun viel träger ist. Wenn ich die URL im Browser eingebe schaltet er mit einer Verzögerung von 1 sec jedoch in der app herrscht eine Verzugszeit von bis 3 Sekunden. Woran kann das liegen ?