Go Down

Topic: Server/Client Problem... (Read 900 times) previous topic - next topic

derRobert

#5
Nov 12, 2012, 07:20 am Last Edit: Nov 12, 2012, 07:22 am by derRobert Reason: 1
wie man das sieht?
Mit einem codeschnippsel und der Erklärung aus dem Playground.
Beides steht im Post über dir!

Wie wir darauf kommen?
Bittere Erfahrung!!!

Wenn der RAM voll ist dann macht der Arduino nicht mehr was du ihm mit deinem Programm sagst sondern völlig undefinierte Dinge. Daher ist es Ratsam zu allererst ab zu klären wie es um den Speicher steht.

Und die Menge an Serial.print und Client.print in deinem Code, Ist sehr Speicherhungrig


Und hier habe ich ebend noch was gefunden:


Using Flash Memory for string storage.
Ab Arduino IDE Version 1.0 wurde die F()-Syntax eingeführt. 
Mit ihr kann man Strings im Flash-Speicher anstatt im RAM ablegen.
Beispiel:
Code: [Select]
Serial.println(F("This string will be stored in flash memory"));

Ähnlich funktioniert auch
Code: [Select]
#include <avr/pgmspace.h>
printf_P(PSTR("This string will be stored in flash memory"));

Dazu ist aber das Include der obengenannte Bibiothek notwendig.

http://www.arduino.cc/playground/Main/Printf

Grüße Uwe

pylon

Quote
Was meinst damit ?


Tragen wir mal Deinen loop() zeitlich zusammen:

Code: [Select]
  sensors.requestTemperatures();
  float temp1 = sensors.getTempC(sensor1);                      // Temperatur von Sensor 1 ermitteln
  float temp2 = sensors.getTempC(sensor2);                      // Temperatur von Sensor 2 ermitteln


Zwei OneWire-Temperatursensoren abrufen: ca. 1.5s

Code: [Select]
  Daten_senden(temp1, temp2);                                 // Temperaturdaten an Server übertragen


Je nach Reaktionsgeschwindigkeit des Servers unterschiedlich, aber schon die serielle Ausgabe braucht ca. 0.2s, also dürften 0.5s nicht falsch liegen.

Code: [Select]
  delay(700);

Weitere 0.7s

Code: [Select]
    delay(1000);

Mindestens eine weitere Sekunde.

Code: [Select]
long Interval  = 5;                                        // Upload-Interval in Minuten
  delay(Interval);


Hier stimmt zum Glück der Kommentar nicht, sonst wäre spätestens hier Dein Code gestorben

Dann wird getestet, ob eine Verbindung reingekommen ist, die es zu behandeln gilt. Insgesamt gehen fast 4 Sekunden verloren, bevor ein neuer Test ansteht. Mit kleinen Änderungen und dem entfernen sämtlicher unnötiger delay()s ist das schnell auf wenige Millisekunde runter.

Quote
Aber wie kommt Ihr darauf das der Ram voll läuft ?
Woran sieht man das ?


Du verwendest über 700 Zeichen konstante Strings, die Du einfach durch das F()-Makro in den Programm-Speicher (Flash) verschieben kannst. Ansonsten werden die 700 Bytes konstant im RAM belegt. Bei 2kB Gesamtspeicher darf man hier durchaus von Speicherverschwendung ausgehen.

Dann verwendest Du die String-Klasse, die erstens den Speicher fragmentiert und zweiten an einem Memory-Leak bei der Freigabe von dynamisch alloziertem Speicher leidet. Beides zusammen führt zum dringenden Rat: Verwende die ganze String-Klasse nie in einem Sketch, der über ein Hello-World-Beispiel hinausgeht.

Cetax

Hallo ihr beiden,
danke für die tolle Erklärung.
Hoffe ich habe verstanden was ihr meint.
Ich werde mich mal daran machen, den Code zu säubern und so zu optimieren.
Vielen Dank.

*greatz*

 CeTax

www dot blinkmann dot de

mkl0815

Ich verstehe ehrlich gesagt den Sinn hinter dem Ganzen nicht. Wenn Dein Arduino eh schon in eine Datenbank mit einem PHP-fähigen Webserver logged, warum holst Du Dir die Daten nicht von dort? Während der Arduino in Richtung Datenbank schreibt, ist er eh beschäftigt und kann keine weiteren Anfragen verarbeiten. Deine Daten können also NIE aktueller sein, als das was in der DB steht. Der dortige Webserver hat sicher mehr Ressourcen, um das Loggen des Arduino UND das Ausliefern einer Webseite mit den aktuellsten Daten zu verkraften.
Das Prinzip dahinter ist KISS (Keep It Simple and Stupid)
Bei gleichzeitig Client und Server die zeitnah reagieren sollen, müßtest Du die Kommunikation "multipexen" also nicht innerhalb einer Funktion Daten senden und an einer anderen Stelle Webserver spielen, sondern alles "quasi" parallel in der loop() abhandeln. der WIZnet 5100 kann glaub ich 2 TCP-Verbindungen gleichzeitig, ich weiss aber nicht, ob die LIB das kann. Das Prinzip wäre so ähnlich wie "Blink without delay".
Oder noch anders.
Webserver und Webclient sind, sagen wir mal Objekte die "selbst wissen" wo im Ablauf (Senden, Empfangen, Verarbeiten etc.) sie gerade stehen. Z.B. durch einen internen Status. Jedes dieser "Objekte" hat sowas wie eine "next_step()" Funktion, die man aufrufen kann und wo dieses Objekt den nächsten Schritt macht. Z.B. ein Byte Senden oder Empfangen, die aktuelle Temperatur auslesen, was auch immer. Aber immer nur einen kleinen Schritt, danach kehrt die Funktion wieder zurück. Somit blockiert jede Funktion immer nur für ein par Millisekunden den Ablauf. In Pseudocode würde das in etwa so aussehen:

Code: [Select]

void setup() {
   ...

   //neues Webserver Objekt erzeugen
   Webserver server = Webserver;
   
   //Objekt initialisieren (lausche auf Port 80)
   server.init(80);


   //neues Webclient Objekt erzeugen
   Webclient client = Webclient;
   
   //Objekt initialisieren (sende an IP mit Port )
   client.init("192.168.0.1",80);

   ...

}

void loop() {
   //Webserver einen schritt machen lassen
   server.next_step();
   
   //Client einen Schritt machen lassen
   client.next_step();

  //anderer NICHT BLOCKIERENDER kurzer Code
 
}


Das ganze geht in Richtung "kooperatives" Multitasking.

Go Up