TCP/IP Verbindung spinnt

Ich habe mehrere Arduinos im Netzwerk die über einen selbstgeschriebenen serverdienst angesteuert werden und infomationen hin und hersenden. Ab und an werden die Verbindungen zu den Arduinos getrennt und wieder aufgebaut. Leider passiert es dann öfter das der Server die Arduinos nichtmehr online bekommt. Um genau zu sein wird diese zeile trotz aktiver verbindung nicht erfüllt. "while (client.connected()) " . Die Serversoftware konnte ich als fehlerquelle Ausschließen. Die Arduinos sind trozdem anpingbar aber stellen besagte TCP verbindung nicht mehr her. Als Fix habe ich bis jetzt nur ein Hardware Reset oder neu booten durch strom an/aus gefunden. Bei mehreren Arduinos wird das schnell sehr nerfig.
Hat jemand ne idee was ich falsch mache?
MFG Penner 42

#include <Ethernet.h>                                                             // Ethernetshield-Bibliothek einbinden
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN A5                                                                // Hier wird angegeben, an welchem Pin die WS2812 LEDs bzw. NeoPixel angeschlossen sind
#define NUMPIXELS 8                                                               // Hier wird die Anzahl der angeschlossenen WS2812 LEDs bzw. NeoPixel angegeben
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

byte mac[] = {0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };                               // (frei ausgedachte) MAC Adresse des Ethernet Shield
IPAddress ip(xxx,xxx,xxx,xxx);                                                     // IP des ARDUINO im lokalen Netzwerk angeben. 
EthernetServer server(80);                                                        // Ethernet Library als Server initialisieren Port Einstellung (Standard 80)
MFRC522 mfrc522(SN_PIN, RST_PIN);                                                 // Instanz des MFRC522 erzeugen   
int t_anzeige = 0;                                                                // Anzeigentimer
int richtung = 0;                                                                 
int offline = 0;


    void setup() 
    {
      Ethernet.begin(mac, ip);                                                    // Ethernet Verbindung und Server starten
      server.begin();
      Serial.begin(9600);
      Serial.print("Server gestartet. IP: ");
      Serial.println(Ethernet.localIP());
      pixels.begin();                                                             // Initialisierung der NeoPixel
    }

  void(* resetFunc) (void) = 0;//declare reset function at address 0

  void loop() 
  {
        EthernetClient client = server.available();                                 // server.available() schaut, ob ein Client verfügbar ist und Daten an den Server schicken möchte. Gibt dann eine Client-Objekt zurück,sonst false
        if (client)        // <<-- Hier ist der knackpunkt                        // Wenn es einen Client gibt, dann...
        {
        Serial.print("Neuer Client : ");
        Serial.println(client);
        // Solange Client verbunden 
          while (client.connected())                                                //Funktioniert sporadisch nicht
            {
        //hier wird mit dem server Kommuniziert
            }  
              delay(1);                                                           // Kleine Pause
              client.stop();                                                      // Verbindung schliessen
              Serial.println("Verbindung mit Client beendet.");
              Serial.println("");
         }   
         offlineanzeige();  
    }                                                                             // Ende Loop

    void offlineanzeige()
    {
    pixels.setPixelColor(1, pixels.Color(255,0,0));                             // Der Pixel aus, Vorgang abgeschlossen
    pixels.show();                                                              // Durchführen der Pixel-Ansteuerung 
    Serial.print("Arduino offline "); 
    Serial.println(Ethernet.localIP());
    delay(250);  
    }

test.ino (3.32 KB)

Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

#include <Ethernet.h>                                                             // Ethernetshield-Bibliothek einbinden
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN A5                                                                // Hier wird angegeben, an welchem Pin die WS2812 LEDs bzw. NeoPixel angeschlossen sind
#define NUMPIXELS 8                                                               // Hier wird die Anzahl der angeschlossenen WS2812 LEDs bzw. NeoPixel angegeben
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

byte mac[] = {0, 0, 0, 0, 0, 0 };                               // (frei ausgedachte) MAC Adresse des Ethernet Shield
IPAddress ip(0,0,0,0);                                                  // IP des ARDUINO im lokalen Netzwerk angeben.
EthernetServer server(80);                                                        // Ethernet Library als Server initialisieren Port Einstellung (Standard 80)


void setup()
{
  Ethernet.begin(mac, ip);                                                    // Ethernet Verbindung und Server starten
  server.begin();
  Serial.begin(9600);
  Serial.print("Server gestartet. IP: ");
  Serial.println(Ethernet.localIP());
  pixels.begin();                                                             // Initialisierung der NeoPixel
}


void loop()
{
  EthernetClient client = server.available();                                 // server.available() schaut, ob ein Client verfügbar ist und Daten an den Server schicken möchte. Gibt dann eine Client-Objekt zurück,sonst false
  if (client)                                                                 // Wenn es einen Client gibt, dann...
  {
    Serial.print("Neuer Client : ");
    Serial.println(client);
    // Solange Client verbunden
    while (client.connected())                                                //Funktioniert sporadisch nicht
    {
      //hier wird mit dem server Kommuniziert
    }
    delay(1);                                                           // Kleine Pause
    client.stop();                                                      // Verbindung schliessen
    Serial.println("Verbindung mit Client beendet.");
    Serial.println("");
  }
  offlineanzeige();
}                                                                             // Ende Loop

void offlineanzeige()
{
  pixels.setPixelColor(1, pixels.Color(255, 0, 0));                           // Der Pixel aus, Vorgang abgeschlossen
  pixels.show();                                                              // Durchführen der Pixel-Ansteuerung
  Serial.print("Arduino offline ");
  Serial.println(Ethernet.localIP());
  delay(250);
}

mobile version

der Sketch macht nix.

//hier wird mit dem server Kommuniziert

tja, was?

wo genau steigt dein Sketch aus?

Folgendermaßen
Ich lasse die arduinos laufen. Wenn die verbindung abbricht ist es in unregelmäßigen abständen so das diese sich nicht wieder mit dem server verbinden obwohl sie online sind. (Ping auf den arduino funktioniert.)
Das Sketch kommt in dem fall nicht über "if (client) " hinaus. (Im seriellen steht nie neuer client)
Ich kann mit meinem Serverscript machen was ich möchte aber es funktioniert nur wieder wenn ich den arduino hardware resete.

Entweder Du gibst uns einen kompilierfähigen Code, der den Fehler reproduzieren kann oder es wird Dir wohl keiner helfen können.

Ansonsten ist die Aussage " oder die Kette oben bei den Editorsymbolen" sinnfrei, wenn Du nicht angibst ob Server oder Client. Ich vermute Client aber es ist nicht eindeutig.

Gruß Tommy

okay hier der komplette code
Ist dazu gedacht je nach empfangendem zeichen ein Relais Anzusteuern.
Der Fehler tritt nicht immer auf und der Compiler wirft auch kein error aus. Aber manchmal baucht er die TCP verbindung ums verrecken nicht wieder auf.

#include <Ethernet.h>                                                             // Ethernetshield-Bibliothek einbinden
#define SN_PIN 8                                                                  // I2C-Bus Datenleitung
#define RST_PIN 9                                                                 // I2C-Bus Datenleitung

byte mac[] = {0xDF, 0xAD, 0x00, 0xE0, 0xE0, 0xCC };                               // (frei ausgedachte) MAC Adresse des Ethernet Shield
IPAddress ip(192,168,xxx,xxx);                                                     // IP des ARDUINO im lokalen Netzwerk angeben. 
EthernetServer server(80);                                                        // Ethernet Library als Server initialisieren Port Einstellung (Standard 80)
char buffer[20] = "";                                                             // Speicherbereich für Datenkonvertierung ????
// ##########Anlegen der benötigten Variablen##############
String terminal = "70";                                                            // Festlegen der EINDEUTIGEN! Terminal-Nummer, darf nur 1x in jedem Netzwerk vergeben sein!
String empf="";
int offline = 0;
int resettimer = 0;
int empw=0;

    void setup() 
    {
    pinMode (7, OUTPUT); 
    pinMode (8, OUTPUT); 
    pinMode (9, OUTPUT); 
    
      Ethernet.begin(mac, ip);                                                    // Ethernet Verbindung und Server starten
      server.begin();
      Serial.begin(9600);
      Serial.print("Server gestartet. IP: ");
      Serial.println(Ethernet.localIP());
    }

  void(* resetFunc) (void) = 0;//declare reset function at address 0

  void loop() 
  {
    digitalWrite (7, LOW);
    digitalWrite (8, LOW);
    digitalWrite (9, LOW);
        EthernetClient client = server.available();                                 // server.available() schaut, ob ein Client verfügbar ist und Daten an den Server schicken möchte. Gibt dann eine Client-Objekt zurück,sonst false
        if (client)     // <<-- Hier gehts  manchmal nich weiter                 // Wenn es einen Client gibt, dann...
        {
        Serial.print("Neuer Client : ");
        Serial.println(client);
        // Solange Client verbunden 
          while (client.connected()) 
            {
             delay(100); 
            // client.available() gibt die Anzahl der Zeichen zurück, die zum Lesen
            // verfügbar sind
                  resettimer = resettimer +1;
                  if (resettimer ==600)// alle 10 minuten
                    {
                    Serial.print("ping");
                    Serial.println();
                    client.print("ping");
                    empw=0;
                    do
                      {
                      delay(100);
                      empw++;
                      empf=client.read();
                      if (empf=="99")
                        {
                        empw=53;
                        }
                      }
                    while(empw < 50);
                      if (empf=="99")
                      {
                      //ping ist ok
                      Serial.println("ping ok");
                      }
                      if (empf!="99") //ping ist falsch
                      {
                      Serial.println("ping error");
                      resetFunc(); //call reset 
                      }
                    resettimer =0;
                    }
                    
                        empf=client.read();
                        if (empf!="-1"){
                        Serial.println("empf: "+empf);
                        }
                          if ((empf=="103")||(empf=="104")||(empf=="105"))
                          {
              if (empf=="103"){
              //g
              client.print("b");
            digitalWrite (7, HIGH);
                          delay (5000);
                          digitalWrite (7, LOW);  
                         Serial.println("Relais 1");
              }
          if (empf=="104"){
              //h
              client.print("b")  ; 
            digitalWrite (6, HIGH);
                          delay (5000);
                          digitalWrite (8, LOW); 
              }
          if (empf=="105"){
              //i
            digitalWrite (5, HIGH);
                          delay (5000);
                          digitalWrite (9, LOW);
                          client.print("b") ;  
              }
                          }

                  // Ende des Blocks Netzwerk online
            }
                  delay(1);                                                           // Kleine Pause
              client.stop();                                                      // Verbindung schliessen
              Serial.println("Verbindung mit Client beendet.");
              Serial.println("");
         }   
         offlineanzeige();  
    }                                                                             // Ende Loop
        
   void offlineanzeige()
    {
    offline = 1;  
    Serial.print("Client offline "); 
    Serial.println(Ethernet.localIP());
    delay(250);  
    }

client.read(); liefert 1 Zeichen (char) zurück und kann damit niemals = “99” (3 Zeichen!) sein.

Du solltest anfangen, Dir ein paar Grundlagen anzueignen.

Delay in Netzwerkprogrammen ist auch kontraproduktiv. Schau Dir mal BlinkWithoutDelay für Zeitsteuerungen an und verstehe es. Dabei kann Dir die Nachtwächtererklärung helfen.

Das es zeitweilig funktioniert, würde ich eher als Zufall bezeichen.

Gruß Tommy

Tommy56:
client.read(); liefert 1 Zeichen (char) zurück und kann damit niemals = “99” (3 Zeichen!) sein.

Client.read liefert mir nen Char zurück den ich als zahl entsprechend ASCII Tabelle verarbeiten kann.
Das Funktioniert in der Praxis sehr gut. (99 enspricht dem kleinem c).

Die delay anweisungen warten entweder auf eine server antwort oder sorgen dafür das mein Ping abstand eigehalten wird. Funktioniert auch seit monaten gut.

Lediglich der teil spinnt manchmal (unten) und verhindert ab und an das eine TCP verbindung zustande kommt. Der ist übrigens vor allen delay anweisungen womit ich eine schuld dieser ausschließen würde.

        EthernetClient client = server.available();                                 // server.available() schaut, ob ein Client verfügbar ist und Daten an den Server schicken möchte. Gibt dann eine Client-Objekt zurück,sonst false
        if (client)     // <<-- Hier gehts  manchmal nich weiter                 // Wenn es einen Client gibt, dann...
        {
        Serial.print("Neuer Client : ");
        Serial.println(client);
        // Solange Client verbunden
          while (client.connected())

penner42:
Das Funktioniert in der Praxis sehr gut. (99 enspricht dem kleinem c).

Aber nicht "99". Das siond 3 Zeichen mit den Codes 0x39, 0x239, 0x00. Aber das wirst Du auch noch merken, dass Deine Interpretation falsch ist.

Du hast ja die Probleme. nicht wir. Wenn Du also meinst, dass Du es besser weißt: Viel Spaß weiterhin.

Gruß Tommy

(99 enspricht dem kleinem c).

Völlig richtig, aber “99” ist die Adresse eines festen Textes und damit etwas ganz anderes. Wenn du Warnungen nicht ignorierst, sagt dir das sogar der Compiler.

Wenn du es per tcp als binary sendest funktionierts. Wenn du mir nicht glaubst teste es doch selbst. Ich sehe ja ein das man das sicher besser machen kann aber um diese anweisung gehts überhaubt nicht da das Skech das richtig erkennt und ausführt.
Mich würde freuen wenn wir uns die sache mit dem client anschauen könnten. Die funktioniert leider nicht immer und ich bezweifel ernsthaft das client.read(); daran schuld ist.

michael_x:
Völlig richtig, aber "99" ist die Adresse eines festen Textes und damit etwas ganz anderes. Wenn du Warnungen nicht ignorierst, sagt dir das sogar der Compiler.

Ok ich schaue mal wie ich das besser machen kann.
Ps.:Mein Compiler wirft keine Warnung aus. (Ver.:1.8.10)

drück mal strg-T in der IDE und formatiere deinen Code.

was ist empw?

und vor einem Crosspost, hättest zumindest hier bescheid geben können.
German forum: https://forum.arduino.cc/index.php?topic=668948.msg
English https://forum.arduino.cc/index.php?topic=669059.msg0#new

Moin,

also ich hab mir den Code mal angesehen; mehr auch nicht.

Er kompiliert fehlerfrei und ohne Warnungen, ist aber nicht lesbar.
noiasca sagte es ja schon, STRG-T.

Den Hinweis von Tommy56 so zu beantworten, halte ich für gewagt.

String empf = "";

if (empf == "99")

Ist nunmal kein Byte.
während

empf = client.read();

nur ein Byte übergibt.

Das der Code so funktioniert kann ich mir beim besten Willen nicht vorstellen.

Andererseits deklarierst und kommentierst Du:

char buffer[20] = "";     // Speicherbereich für Datenkonvertierung ????

      // client.available() gibt die Anzahl der Zeichen zurück, die zum Lesen
      // verfügbar sind

Warum machst Du das dann nicht?
Sag nicht, das Du ja nur ein Zeichen empfängst.

Und davon abgesehen noch was anderes:
die if's ab Zeile 83 sind doppelt gemoppelt. Ich hätte es als case gemacht.
die ganzen delays bringen Dir definitiv keine 10 Minuten in Zeile 49
Du deklarierst nur 3 PIN (7-9), verwendest aber 5-9 von denen Du 7-9 bei jedem Loop auf Low ziehst. Was willst Du damit anstellen?

Er kompiliert fehlerfrei und ohne Warnungen

Oh ja, sorry. Ich hatte den Datentyp

String empf="";

übersehen.
Meine Standardantwort
Arduino String Objekte sind nie erforderlich und machen eher Ärger als dass sie wirklich helfen
wurde mal wieder bestätigt.

String empf = "99"; hat nun wirklich absolut nichts mit einem kleinen 'c' zu tun.

michael_x:
String empf = "99"; hat nun wirklich absolut nichts mit einem kleinen 'c' zu tun.

Das hatte ich schon in #7 vergeblich versucht ihm beizubringen. Evtl. glaubt er ja Dir.

Gruß Tommy

Ich habe nochmal drübergeschaut und die formatierung mit Strg+t geradegezogen.
Ich habe auch nochmal geschaut

empf = client.read();
          if (empf == "99")

Habe ich so gemacht weil die empfangenden zeichen mir auch so im seriellen monitor ausgegeben werden. Ich habs probiert wenn ich die zahlen durch die kleinen Buchstaben ersetzen dann funktionierts aber nicht.
Ach ja und könntet ihr mir villeicht bei meinem ürsprünglichem problem mit dem wiederverbinden helfen da das mit den empfangenden zeichen bei mir funktioniert. (und ich wüsste im moment nicht wie das besser gehen sollte aber es läuft ja auch)
Ps.:An alle die sagen es ist nicht gemacht wie vorgesehen. Ihr habt recht!
An alle die sagen das kann nicht funktionieren. Ihr könnt es nicht getestet haben…

#include <Ethernet.h>                                                             // Ethernetshield-Bibliothek einbinden

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xDF };                               // (frei ausgedachte) MAC Adresse des Ethernet Shield
IPAddress ip(192,168,178,56);                                                     // IP des ARDUINO im lokalen Netzwerk angeben. 
EthernetServer server(80);                                                        // Ethernet Library als Server initialisieren Port Einstellung (Standard 80)                                                       // Festlegen der EINDEUTIGEN! Terminal-Nummer, darf nur 1x in jedem Netzwerk vergeben sein!
String empf = "";
int offline = 0;
int resettimer = 0;
int empw = 0;

void setup()
{
  pinMode (7, OUTPUT);
  pinMode (8, OUTPUT);
  pinMode (9, OUTPUT);

      Ethernet.begin(mac, ip);                                                    // Ethernet Verbindung und Server starten
      server.begin();
      Serial.begin(9600);
      Serial.print("Server gestartet. IP: ");
      Serial.println(Ethernet.localIP());
}

void(* resetFunc) (void) = 0;//declare reset function at address 0

void loop()
{
  digitalWrite (7, LOW);
  digitalWrite (8, LOW);
  digitalWrite (9, LOW);
          EthernetClient client = server.available();                                 // server.available() schaut, ob ein Client verfügbar ist und Daten an den Server schicken möchte. Gibt dann eine Client-Objekt zurück,sonst false
        if (client)                                                                 // Wenn es einen Client gibt, dann...
        {
        Serial.print("Neuer Client : ");
        Serial.println(client);
        // Solange Client verbunden 
          while (client.connected()) 
    {
      delay(100);
      // client.available() gibt die Anzahl der Zeichen zurück, die zum Lesen
      // verfügbar sind
      resettimer = resettimer + 1;
      if (resettimer == 600) // alle 10 minuten
      {
        Serial.print("ping");
        Serial.println();
        client.print("ping");
        empw = 0;
        do
        {
          delay(100);
          empw++;
          empf = client.read();
          if (empf == "99")
          {
            empw = 53;
          }
        }
        while (empw < 50);
        if (empf == "99")
        {
          //ping ist ok
          Serial.println("ping ok");
        }
        if (empf != "99") //ping ist falsch
        {
          Serial.println("ping error");
          resetFunc(); //call reset
        }
        resettimer = 0;
      }

      empf = client.read();
      if (empf != "-1") {
        Serial.println("empf: " + empf);
      }
      if ((empf == "103") || (empf == "104") || (empf == "105"))
      {
        if (empf == "103") {
          //g
          client.print("g");
          digitalWrite (7, HIGH);
          delay (5000);
          digitalWrite (7, LOW);
          Serial.println("Relais 1");
        }
        if (empf == "104") {
          //h
          client.print("h")  ;
          digitalWrite (8, HIGH);
          delay (5000);
          digitalWrite (8, LOW);
        }
        if (empf == "105") {
          //i
          digitalWrite (9, HIGH);
          delay (5000);
          digitalWrite (9, LOW);
          client.print("i") ;
        }
      }

      // Ende des Blocks Netzwerk online
    }
    delay(1);                                                           // Kleine Pause
    client.stop();                                                      // Verbindung schliessen
    Serial.println("Verbindung mit Client beendet.");
    Serial.println("");
  }
  offlineanzeige();
}                                                                             // Ende Loop

void offlineanzeige()
{
  offline = 1;
  Serial.print("Client offline ");
  Serial.println(Ethernet.localIP());
  delay(250);
}

An alle die sagen das kann nicht funktionieren. Ihr könnt es nicht getestet haben...

Wenn du sagst, bei dir kommt

ping
ping ok

auf Serial raus, kann ich dir nicht weiter helfen.

String empf; // Problem 1
void setup() {
   Serial.begin (9600);
}

void loop ( ) {
   if ( Serial.available () ) {
      empf = Serial.read ();
      if ( empf == "99")  // Problem 2
         Serial.println ("Das kommt nie");
      else
         Serial.println (empf);
    }
}

Wie erreichst du, dass dieser Sketch die Ausgabe "Das kommt nie" erzeugt ?

Warum sollte ich sagen das das funkioniert wenn es das nicht täte?
Screenshot im anhang.