Webserver lange Antwortzeiten

Hallo,
ich habe mit diesem Code einen kleinen Webserver realisiert welcher die Werte eines Sensors als XML ausgibt.

#include <DHT.h>
#include <Wire.h>
#include <SPI.h>
#include <Ethernet.h>

#define DHTPIN         8      // Data pin for the HUMID module
#define DHTTYPE        DHT22  // Sensor used on the HUMID module

// Ethernet Shield MAC address, use value on back of shield (MAC from EG Shield).
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xF3, 0x5B}; 

// IP address, will depend on your local network.
IPAddress ip(192,168,0,160);

// Initialize the Ethernet server library, use port 80 for HTTP.
EthernetServer server(80);

// String for reading from client
String request = String(100);
String parsedRequest = "";


DHT dht(DHTPIN, DHTTYPE);

float og_t01;
float og_h01;

void setup() 
{ 
  // start the HUMID module:
  dht.begin();
  delay(2000);

  // Start the Ethernet connection and the server.
  Ethernet.begin(mac, ip);
  server.begin();
}


void loop() 
{
  // Listen for incoming clients.
  EthernetClient client = server.available();
  
  if (client) 
  {
    // An http request ends with a blank line.
    boolean currentLineIsBlank = true;
 
    while (client.connected()) 
    {
      if (client.available()) 
      {
        char c = client.read();
        
        // Read http request.
        if (request.length() < 100) 
        {
          request += c; 
        } 
      
        // If you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply.
        if (c == '\n' && currentLineIsBlank) 
        {     
          if (request.startsWith("GET /?format=")) 
          {
            parsedRequest = request.substring(request.indexOf('format=')+1, request.indexOf("HTTP")-1);
          }
          
          og_h01 = dht.readHumidity();
          og_t01 = dht.readTemperature();   
          
          if( parsedRequest == "XML" )
          {
             sendXmlResponse(client, og_t01, og_h01);
          }
          
          break;
        }
        
        if (c == '\n') 
        {
          // Character is a new line.
          currentLineIsBlank = true;
        } 
        else if (c != '\r') 
        {
          // Character is not a new line or a carriage return.
          currentLineIsBlank = false;
        }
        
      }
      
    }
    
    // Give the web browser time to receive the data.
    delay(1);
    
    // Close the connection:
    client.stop();
  }
  
  // Reset the request.
  request = "";
  parsedRequest = "";
}

void sendXmlResponse(EthernetClient client, float og_t01, float og_h01)
{
    Serial.println("Sending XML response.");
    
    // Send a standard http response header.
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/xml");
    client.println("Connnection: close");
    client.println();
    
    // Send XML body.
    client.println("<?xml version=\"1.0\"?>");
    client.println("<xml>");
    client.print("<wall24-og-log-01>");
    client.print("<temp>");
    client.print(og_t01);
    client.print("</temp>");
    client.print("<hum>");
    client.print(og_h01);
    client.print("</hum>");
    client.println("</wall24-og-log-01>");            
    client.println("</xml>");
}

Der Code läuft soweit. Nur jede zweite/dritte Anfrage sehr lange (größer 10 Sekunden) bis eine Antwort vom Server kommt. Sehr Ihr da einen grundsätzlichen Fehler im Code oder kennt jemand solch ein Problem?

Vielen Dank für Eure Hilfe

Ich würde

  1. die Serial - Testausgabe ansehen ( kommt die auch verzögert ?)
  2. evtl. weitere Testausgaben einbauen um die Verzögerung zu erkennen
  3. Prüfen, on da evtl. ein Reset passiert, z.B. eine Testausgabe in void setup() einbauen.
  4. String Objekte rausschmeissen und durch char Arrays ersetzen ( falls das mit dem reset stimmt )
  5. All die konstanten Texte direkt aus dem Flash ausgeben ( s. F-Makro ), um weiter RAM zu sparen.
     client.println(F("HTTP/1.1 200 OK"));

sunnyraven:
Der Code läuft soweit.

"Bis hierhin ist soweit alles OK" sagte der Mann, als er vom Hochhaus fiel und an der ersten Etage vorbeikam.

Dein Code verwendet String-Objekte:

// String for reading from client
String request = String(100);
String parsedRequest = "";

Als erstes würde ich prüfen: Arduino Software Version 1.0.5?

String-Objekte sind in früheren Versionen der Arduino Software (1.0.1, 1.0.2, 1.0.3, 1.0.4) fehlerhaft implementiert und Sketche mit String-Objekten laufen in Softwareversionen vor 1.0.5 NICHT IN ALLEN FÄLLEN DAUERHAFT FEHLERFREI, obwohl der Sketch an sich fehlerfrei programmiert ist!

Als zweites würde ich prüfen, ob noch genügend RAM-Speicher frei ist. Mal die Funktion

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

einbauen und den Wert der freien RAM-Speicherstellen vielleicht über Serial zur Kontrolle an verschiedenen Stellen ausgeben lassen.

String-Objekte verbrauchen tendenziell deutlich mehr Speicherplatz als die üblichen C-Strings (char Arrays). Außerdem verbrätst Du auch reichlich RAM-Speicher dadurch, dass Du für print-Ausgaben nicht das F-Makro verwendest. Dann kann es auf einem UNO schnell eng mit RAM-Speicher werden.

Hallo,

Du benutzt request.indexOf('format=')+1, so als ob es Dir die Position von "format=" liefern würde. Es sucht aber nur nach einem Character, nicht nach einem String, hier also nur nach dem 'f'. Liegt es vielleicht daran?

Gruß,
Ralf

Vielen Dank für Eure Hilfe!

Was habe ich nun alles getan.

Als erstes würde ich prüfen: Arduino Software Version 1.0.5?

Guter Hinweis ich bin auf 1.0.5

  1. die Serial - Testausgabe ansehen ( kommt die auch verzögert ?)
  2. evtl. weitere Testausgaben einbauen um die Verzögerung zu erkennen
  3. Prüfen, on da evtl. ein Reset passiert, z.B. eine Testausgabe in void setup() einbauen.

Diesen Hinweis habe ich auch befolgt und den Seriellen Monitor etwas gesprächiger gemacht.
Dabei und unter Zuhilfenahme von Wireshark habe ich den eigentlichen Fehler in meinem Python Script gefunden. Also eigentlich war der Arduino nicht dran schuld! Aber ich mache an dieser Stelle auch weiter, sonst lerne ich nie sauberen Code für Arduino zu schreiben.

  1. All die konstanten Texte direkt aus dem Flash ausgeben ( s. F-Makro ), um weiter RAM zu sparen.

Habe ich dann auch gemacht und dadurch wurde die Sache sichtbar beschleunigt Wahnsinn!

Als zweites würde ich prüfen, ob noch genügend RAM-Speicher frei ist. Mal die Funktion

So runde 900 Byte sind noch frei und der Wert bleibt auch von Abfrage zu Abfrage konstant.

Du benutzt request.indexOf('format=')+1, so als ob es Dir die Position von "format=" liefern würde. Es sucht aber nur nach einem Character, nicht nach einem String, hier also nur nach dem 'f'. Liegt es vielleicht daran?

Das +1 sagt doch das die Zeichen rechts von format= gelesen werden sollen!? Das kann ich eh noch ändern da ich den Code aus einem Beispiel habe welches verschiedene Formate unterstützt.

String-Objekte verbrauchen tendenziell deutlich mehr Speicherplatz als die üblichen C-Strings (char Arrays). Außerdem verbrätst Du auch reichlich RAM-Speicher dadurch, dass Du für print-Ausgaben nicht das F-Makro verwendest. Dann kann es auf einem UNO schnell eng mit RAM-Speicher werden.

Habt Ihr eine gute Seite oder ein kurzes Beispiel zum Thema C-Strings (char Arrays)?

sunnyraven:
Das +1 sagt doch das die Zeichen rechts von format= gelesen werden sollen!? Das kann ich eh noch ändern da ich den Code aus einem Beispiel habe welches verschiedene Formate unterstützt.

Einfache Anführungs-Striche ist aber ein char! Strings müssen in Anführungszeichen (") gesetzt werden. Weiß nicht wieso das der Compiler durchgehen lässt.

Habt Ihr eine gute Seite oder ein kurzes Beispiel zum Thema C-Strings (char Arrays)?

http://en.wikibooks.org/wiki/C_Programming/Strings