Lan Kommunikation nach 40 Sek nicht mehr möglich

Hallo Freunde,

ich habe derzeit ein Problem dem ich nicht " auf die Spur " komme:

Es wurde mit einem MEGA+EthernetShield eine Ethernet-(W)-Lan Kommunikation von einer Html-Seite auf einem Browser (IE8) zum ARDUINO aufgebaut.
Die Verbindung über einen Http-Request zum Eth.Shield und zurücksenden einer Html-Seite funktioniert nach dem Start des Programms und über
ca. 40 Sek. lang einwandfrei.

Wird eimal für ca. 40 sec. kein Request von der Html-Seite gesendet, dann wird ungefähr nach dieser Zeit vom ARDUINO keine Request vom Browser mehr angenommen.
Wird jedoch in dieser Zeitspanne immer wieder einmal eine Request gesendet, funktioniert die Verbindung immer.

Dach einem Neustart des Programms funktioniert immer alles wieder ganz normal.
Ich habe bereits jede Menge Versuche gestartet um den Fehler zu finden bisher jedoch vergeblich.
Über ein spezielles Programm lasse ich mir die abgesendeten Requests vom Browser aufzeigen.
Auch der Request den vom ARDUINO nicht mehr angenommen wird vom Browser gesendet.

Wer könnte hier helfen? Wer hat bereit ähnliche Probleme einmal gehabt?

Liebe Grüsse
Rainer

Hier nun einige Daten zur HW + SW :
Neues MEDGA-Bord R3 + EthernetShield R3,
Programmierumgebung ; MSWin 7 mit aktueller Arduino 1.0.1 Umgebung

..und hier das Kernstück meiner Software:..
Vorab werden selbstv. Client + Server ordungsgemäß intialisiert
und die SW unten läuft im Loop.

//Wartet auf  Http- Request vom Browser
   EthernetClient client = server.available();
   
   while ((client) && (client.connected())) 
   {   
       if (client.available()) {
          char c = client.read();
          digitalWrite(LED_GELB,HIGH);
          
          if (GetString.length() < 60) {GetString += c;}
          
          if ((c == '\r')&&(!GETrow)){
             if(GetString.indexOf("GET /") >=0){GETrow=true;}
          }
          
          if (c == '\n'){ 
              while (client.available()>0) {c = client.read();} 
              HttpEnd=true;
              break; 
          }
       } 
   } 
 
 
  if (HttpEnd) {
  
     //Serial.println(GetString);   //empfangener String
            
       if(GetString.indexOf("HTML=CFG") >0) {
         CFG_Seite(client);  // sendet Web-Seite zum Browser
       }
           
       if(GetString.indexOf("callback") >0) {
         SZW_Seite(client);
       }
           
       if(GetString.indexOf("SDC=ja") >0) {
         SDC_Status_EEPROM = 99;
         EEPROM.write(1,99);
         CFG_Seite(client);
        }
          
        if(GetString.indexOf("SDC=nein") >0) {
          SDC_Status_EEPROM = 0;
          EEPROM.write(1,0);
          CFG_Seite(client);
        }
           
        if(GetString.indexOf("PZYK") >0) {
           String sub_string = GetString.substring(11,14);
           int zykwert = 12;
           if (sub_string == "030") {zykwert = 3;}
           if (sub_string == "060") {zykwert = 6;}
           if (sub_string == "120") {zykwert = 12;}
           EEPROM.write(2,zykwert);
           CFG_Seite(client);
        }

        GetString = "";
        GETrow  = false;
        HttpEnd = false;   
        digitalWrite(LED_GELB,LOW);
        ControlTime = Task4_Start+1;
  }

Bitte poste den ganzen Sketch, Ausschnitte sagen leider meistens überhaupt nichts aus. Vor allem in diesem Fall, denn Dein Ausschnitt zeigt den Teil des Programms, der bei einer aktiven Verbindung durchlaufen wird, aber dort scheint nach Deiner Aussage das Problem nicht zu stecken.

Gerne stelle ich hier den kompletten Sketch z.V. - der ist jedoch etwas "länger" :fearful:
Komprimiert (als zip) ist er gut 7 kB gross.
Ich bin sehr auf eine Antwort gespannt.

Du hast eine sehr spezielle Art des Programmaufbaus, die für Deine Probleme verantwortlich ist. Task 4 wird immer wieder gestartet, wenn eine Verbindung reingekommen ist. Passiert das aber nicht, ist Task4_Ende nach ca. 40s erreicht und von dort an wird keiner der if-Blöcke mehr ausgeführt, somit macht der Arduino nichts mehr, reagiert auch nicht mehr auf eingehende Requests.

Du solltest Dir diesen zeitgesteuerten Ablaufplan nochmals überdenken. Alles, was nicht wirklich zeitgesteuert sein muss, würde ich von den entsprechenden Events abhängig machen und nicht von der Zeit (z.B. der NTP-Request ist dann zu Ende, wenn die Antwort des Zeitservers eingegangen ist und nicht nach 5 Sekunden).

Hallo pylon,

erst einmal herzlichen Dank für deine Mühe den Skript durchzusehen.
Nun zu deinen Anmerkungen:
1.Selbstverständlich ist das so programmiert wir du es vorschlägst : falls (z.B.) die NTP-Zeit ankommt geht es sofort zum nächsten Task. (-> ControlTime = Task2_Start;)
2.Selbstverständlich wird auch nach am Ende von Task4, nach einigen Sek. (siehe unten) wieder der Task4 gestartet.
Ausführlicher:
Task4 wird nach der Prog.-Zykluszeit (nehmen wir einmal ca. 60 sec.) unterbrochen und der gesamt Programablauf neu gestartet.
Es wird Task1 nur durchlaufen falls auch NTP-benötig wird (->99), falls nicht geht es sofort weiter zu Task2.
Hier im Task2 werden neue Werte von einem (eHZ) Zähler geholt, bei Synchr. Fehler das kann schon mal 2-3 sec dauern.
Anschließend wird im Task3 falls notwendig (->99) die Zählerdaten auf die SD-Karte geschrieben, sonst geht es sofort weiter zu Task4.

Falls ein Request in der Zwischenzeit (Task1-3) ankommt, wird dieser gepuffert und dann in Task4 ausgelesen und interpretiert.
Das funktioniert in den ersten ca. 40 Sek einwandfrei - und funktioniert innerhalb von Task4 oder auch davor in Task1-3.

Der Zeitbedarf für Task1-3 sind max 5 sec. - die restliche Zeit, also 55 Sek läuft der Loop in Task4 - alle anderen IFs sind FALSE.
Auch wenn ich bewußt genau innerhalb vom Loop 4 den Request setze, wird der Request nach ca. 30-40 Sek nicht mehr angenommen ...

das ist das Problem!

Inzwischen habe ich im Netz ein ähnliches Problem gefunden:
Ethernet fails connecting after a while ..... http://forum.freetronics.com/viewtopic.php?f=4&t=176&start=30
Ich werde mir das einmal ansehen.

Ich habe mein Programm auch auf den 'nackten' Ethernet-Loop reduziert = es passiert trotzdem.

Ich habe das Rücksetzen der Control-Zeit gefunden. Dein Programm-Aufbau ist so komplex, dass wahrscheinlich sogar Du die Übersicht verlierst, was wann genau gemacht wird. Selbst wenn Dein Programm funktionieren würde, wäre es nur ca. 40s in jeder Minute auf Empfang, findest Du das nicht auch sehr benutzerfeindlich?

Hast Du die seriellen Ausgabe mal aufgezeichnet? Falls ja, kannst Du das hier posten?

Nochmals Danke für die Durchsicht.
Leider sehe ich keinen anderen Weg, auch mit Interrupts nicht, eine gewisse Zeit dem Auslesen der Zählerdaten zu spendieren.
Also ... die Übersicht verliere ich nicht.
Deine Aussage hilft mir in dieser Form, jedoch nicht weiter - es ist eine pauschale Kritik, die nichts mit dem Problem zu tun hat.
Und noch etwas, das Program bzw. die HW ist "immer auf Empfang" da der Ethernetcontroller in seinem Stack den nächsten
Request zwischen speichert.

Okay- es war eine Versuch hier Hilfe zu bekommen - abermacht nichts.

Hast Du die seriellen Ausgabe mal aufgezeichnet? Falls ja, kannst Du das hier posten?

Ging diese Frage vergessen?

Du solltest unsere Kommentare nicht als persönlichen Angriff verstehen. Bei Deinem Programmaufbau sind Race Conditions deutlich wahrscheinlicher, als wenn Du das z.B. mit einer State Machine gelöst hättest.

Meine Standardlitanei: der Arduinio ist zu schwach als Webserver.

Verdacht hier: RAM reicht nicht weil zuviel Platz durch die Strings verbraucht wird. Google mal nach PROGMEM und schau Dir das F Makro an, also statt ...print("bla"); bessser ....print(F("bla"));

Eine ganz kurze Erklärung habe ich auch in meinem Blog Persistence of Vision | Blinkenlight

Keine Ahnung ob das Stringproblem wirklich die Ursache ist, aber solange dieses Problem da ist würde ich gar nicht erst nach anderen suchen.

Hallo Udo,

danke für deinen Hinweis.
Das ist jedoch (beim Mega) nicht der Fall. RAM ist ausreichend vorhanden.
Diese wird auch nach jedem Compilerlauf von mir überprüft.
Ferner habe ich das mit PROGMEM bereits versucht.
Ich habe auch schom einmal alle Debug-Info-Strings schon einmal geschlöscht - kein positiver Effekt.

Das ist jedoch (beim Mega) nicht der Fall. RAM ist ausreichend vorhanden.
Diese wird auch nach jedem Compilerlauf von mir überprüft.

Wie überprüfst Du das? Der Compiler kann doch maximal wissen was statisch allokiert wird. Was dynamisch allokiert wird kann der Compiler ja wohl eher nicht herausbekommen. Also was genau tust Du um das zu überprüfen?

Richtig - ich habe auch an den nach dem Compilierlauf freien RAM gedacht.
So sind zunächst, bei allen vorh. Strings, immer noch ca. 3,2 kB RAM frei.
Sollte der RAM während der Laufzeit volllaufen, würde sich die Zeit bis zum Problem,
bei mehr freiem RAM ändern - tut es aber nicht.

Trotzdem Danke für den Hinweis . Ich werde auch das im Auge behalten.

Rainer_R:
Richtig - ich habe auch an den nach dem Compilierlauf freien RAM gedacht.
So sind zunächst, bei allen vorh. Strings, immer noch ca. 3,2 kB RAM frei.
Sollte der RAM während der Laufzeit volllaufen, würde sich die Zeit bis zum Problem,
bei mehr freiem RAM ändern - tut es aber nicht.

Trotzdem Danke für den Hinweis . Ich werde auch das im Auge behalten.

Von welchem RAM redest Du? Dem Flash-RAM in dem das Programm liegt, oder den SRAM der die Variablen zur Laufzeit enthält? Anders als ein PC gibt es beim ATMEGA zwei verschieden RAM-Arten. Was der Compiler nach dem compilieren ausgibt, ist die Größe Deines Programms im Flash-RAM. Das hat nix mit dem SRAM zu tun. Flash hat der Mega 128 oder 256kb, je nach Prozessor. Beide haben aber nur 4k SRAM.
Auf welche Art und Weise prüfst Du denn den freien RAM?
Leider kenne ich Deinen Sketch nicht und im Thread hängt er leider nicht an.

Danke - der Unterschied ist mir schon bekannt.
Ich rede daher nicht von dem Flash-RAM = Programm-RAM sondern nur von dem SRAM - hier sind also zum Prog-Start noch 3,2 KB frei.
Das zeigt mir diese Fkt.:

int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

Meine HTML-Strings benötigen ca. 2 KB - müsste doch eigentlich reichen :fearful:
Ich werde trotzdem einmal die HTML-Strings über PROGMEM ist das Flash-RAM Speichern und zur Laufzeit
aus einem Buffer senden. Mal sehen ....

mkl0815:
Von welchem RAM redest Du? Dem Flash-RAM in dem das Programm liegt, oder den SRAM der die Variablen zur Laufzeit enthält? Anders als ein PC gibt es beim ATMEGA zwei verschieden RAM-Arten. Was der Compiler nach dem compilieren ausgibt, ist die Größe Deines Programms im Flash-RAM. Das hat nix mit dem SRAM zu tun. Flash hat der Mega 128 oder 256kb, je nach Prozessor. Beide haben aber nur 4k SRAM.
Auf welche Art und Weise prüfst Du denn den freien RAM?
Leider kenne ich Deinen Sketch nicht und im Thread hängt er leider nicht an.

Der ATmega2560 auf dem Arduino MEGA2560 hat 8 Kbyte SRAM. Alternativ kann ein Speicherbaustein mit einem Multiplexer den internen SRAM auf 64kByte erweitern. http://ruggedcircuits.com/html/megaram.html
Grüße Uwe