ESP32 nach Deep Sleep verschluckt TCP Nachrichten

Hallo,
nach langer Forenabstinenz melde ich mich mal wieder hier, weil ich einfach nicht weiter komme.
Mein Projekt: zu einem vorhandenen Webserver (auf ESP32) mit Klimaanzeige fürs Gewächshaus möchte ich Akkubetriebene Bodenfeuchtesensoren ergänzen. Diese sollen mit dem ESP32-C3 Super Mini laufen. Alle 60min die Bodenfeuchte messen, und den Wert über TCP an den ESP32 senden, auf dem der Webserver läuft.

Ich habe Elektronikerfahrung (beruflich), auch schon viel programmiert (Hobby), bin aber, was die ganze WiFi-thematik angeht, völlig blank. Mir sind die ganzen Protokolle (TCP, UDP, HTTP ...) nur dem Namen nach geläufig, wie das funktioniert, ist mir völlig nebulös.

Ich habe es auch schon mit ESP-Now probiert, habe aber ESP-Now und meinen Webserver nicht zusammen zum laufen gebracht, daher nun der Versuch mit TCP-Messages.

Meine Problemstellung isoliert:
Wenn ich den Client zu Testzwecken mit delay laufen lasse, funktioniert die Übertragung.
Wenn ich den Client aber in Deep Sleep schicke (identischer Code, bis auf die Deep Sleep Anweisung), dann kommt nur gelegentlich eine Nachricht durch.

Hier der Client-Code:


/*
 * This ESP32 code is based on esp32io.com
 * For more detail (instruction and wiring diagram), visit https://esp32io.com/tutorials/communication-between-two-esp32
 */

#include <WiFi.h>


const char* ssid = "xxxxx";                                      
const char* password = "xxxxxxxxxxx";  

const char* serverAddress = "192.168.0.120";  // CHANGE TO ESP32#2'S IP ADDRESS
const int serverPort = 4080;

const uint64_t MIN = 60e6;        // 60*10^6 usek = 1 Minute
uint64_t SleepTime = 0.25 * MIN;  //  DeepSleep Dauer us (max 60 min)


WiFiClient TCPclient;
RTC_DATA_ATTR int counter = 0;

void setup() {
  Serial.begin(115200);
  delay(2000);
  Serial.println("\nStart Client...");

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // connect to TCP server (Arduino #2)
  if (TCPclient.connect(serverAddress, serverPort)) {
    Serial.println("Connected to TCP server");
  } else {
    Serial.println("Failed to connect to TCP server");
  }
  esp_sleep_enable_timer_wakeup(SleepTime);
}

void loop() {
  // connect to TCP server (Arduino #2)
  if (TCPclient.connect(serverAddress, serverPort)) {
    Serial.println("Connected to TCP server");
  } else {
    Serial.println("Failed to connect to TCP server");
  }
  char buffer[10];  // Sendebuffer
  sprintf(buffer, "Hallo %04d", counter++);
  TCPclient.write_P(buffer, 10);
  TCPclient.flush();
  Serial.print("sent String: ");
  Serial.println(buffer);

  delay(1000);
  esp_deep_sleep_start(); //auskommentieren für Test ohne Deepsleep

  delay(5000);
}

Und hier der dazugehörige Test-Server Code:

/*
 * This ESP32 code is based on esp32io.com
 * For more detail (instruction and wiring diagram), visit https://esp32io.com/tutorials/communication-between-two-esp32
 */

// ESP32 #2: TCP SERVER
#include <WiFi.h>


const char* ssid = "xxxxxxxxxxxx";                                            
const char* password = "xxxxxxxxxx";  


WiFiServer TCPserver(4080);

void setup() {
  delay(2000);
  Serial.begin(115200);
  Serial.println("\nStart Server...");

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // Print your local IP address:
  Serial.print("TCP Server IP address: ");
  Serial.println(WiFi.localIP());
  // Start listening for a TCP client (from ESP32 #1)
  TCPserver.begin();
}

void loop() {
  // Wait for a TCP client from ESP32 #1:
  WiFiClient client = TCPserver.available();

  if (client) {
    delay(100); // warten, bis alle Zeichen gesendet wurden
    // Read the command from the TCP client:
    String X = client.readString();
    Serial.print("ESP32 #2: - Received: ");
    Serial.println(X);
    

  }
  //delay(500);
    client.stop();
}

Wenn ich den Client ohne DeepSleep laufen lasse, kommt jede Nachricht an:


13:16:37.323 -> Start Server...
13:16:38.381 -> Connecting to WiFi...
13:16:39.364 -> Connecting to WiFi...
13:16:40.408 -> Connecting to WiFi...
13:16:40.408 -> Connected to WiFi
13:16:40.408 -> TCP Server IP address: 192.168.0.120
13:16:43.255 -> ESP32 #2: - Received: 
13:16:44.356 -> ESP32 #2: - Received: Hallo 0000
13:16:49.560 -> ESP32 #2: - Received: Hallo 0001
13:16:55.518 -> ESP32 #2: - Received: Hallo 0002
13:17:01.637 -> ESP32 #2: - Received: Hallo 0003
13:17:07.696 -> ESP32 #2: - Received: Hallo 0004
13:17:13.718 -> ESP32 #2: - Received: Hallo 0005
13:17:20.064 -> ESP32 #2: - Received: Hallo 0006
13:17:26.010 -> ESP32 #2: - Received: Hallo 0007
13:17:32.040 -> ESP32 #2: - Received: Hallo 0008
13:17:38.048 -> ESP32 #2: - Received: Hallo 0009
13:17:44.114 -> ESP32 #2: - Received: Hallo 0010
13:17:50.427 -> ESP32 #2: - Received: Hallo 0011
13:17:56.366 -> ESP32 #2: - Received: Hallo 0012
13:18:02.401 -> ESP32 #2: - Received: Hallo 0013
13:18:08.440 -> ESP32 #2: - Received: Hallo 0014
13:18:14.479 -> ESP32 #2: - Received: Hallo 0015

Wenn ich mit DeepSleep arbeite, gibt es große Lücken, in denen der empfangene String leer ist:

12:57:49.908 -> Start Server...
12:57:50.986 -> Connecting to WiFi...
12:57:50.986 -> Connected to WiFi
12:57:50.986 -> TCP Server IP address: 192.168.0.120
12:58:00.020 -> ESP32 #2: - Received: 
12:58:19.240 -> ESP32 #2: - Received: 
12:58:20.381 -> ESP32 #2: - Received: Hallo 0001
12:58:38.553 -> ESP32 #2: - Received: 
12:59:00.626 -> ESP32 #2: - Received: 
12:59:03.532 -> ESP32 #2: - Received: 
12:59:22.816 -> ESP32 #2: - Received: 
12:59:23.873 -> ESP32 #2: - Received: Hallo 0004
12:59:41.954 -> ESP32 #2: - Received: 
13:00:01.304 -> ESP32 #2: - Received: 
13:00:02.410 -> ESP32 #2: - Received: Hallo 0006
13:00:20.724 -> ESP32 #2: - Received: 
13:00:43.104 -> ESP32 #2: - Received: 
13:00:44.240 -> ESP32 #2: - Received: Hallo 0008
13:01:02.278 -> ESP32 #2: - Received: 
13:01:03.393 -> ESP32 #2: - Received: Hallo 0009
13:01:21.567 -> ESP32 #2: - Received: 
13:01:22.642 -> ESP32 #2: - Received: Hallo 0010
13:01:41.038 -> ESP32 #2: - Received: 
13:01:42.151 -> ESP32 #2: - Received: 
13:02:01.562 -> ESP32 #2: - Received: 
13:02:02.609 -> ESP32 #2: - Received: Hallo 0012

Hat jemand eine Idee, woran das liegt?

Das Einzige was mir so beim drüber schauen auffällt ist, dass dein buffer[10] zu klein ist, weil sprintf(buffer, "Hallo %04d", counter++); 10 Zeichen kopiert, dann aber kein Platz mehr für den Abschluss des char arrays ('\0') ist.

Von daher sollte buffer[11] definiert werden.

darf ich da mal nachfragen:
Wenn es einen ESP32 mit einem Webserver gibt (?), warum willst du dann nicht mit einem Webclient einen HTTP Request schicken?

Wenn du wirklich einen Webserver hättest, wäre die Auswertung eines als Parameter übertragenen Wertes sehr einfach.

In deinem "Test-Server Code" sehe ich aber keinen Webserver.

Zur Begriffsbestimmung UDP, TCP, HTTP könnte ich dir meine Seite empfehlen:
https://werner.rothschopf.net/microcontroller/202403_esp_arduino_data_transmission_en.htm

lies da bitte mal drüber und dann schreib uns was du auf deinem "ESP Webserver" wirklich laufen hast.

Danke.
Ich habe einen Quick-and-dirty Workaround:

Ich sende einfach jeden Wert dreimal. Damit verliere ich unter einem Prozent der Werte, das reicht für meine Zwecke.

Hallo,
ich denke auch es hat mit der angegeben Stringlänge etwas zu tun und das client.readString() verschluckt sich. Bei mir sieht das so aus.

// ---------------- TCP recive -----------------
void TCP_recive() {
  int packSize = 0;
char buffer[50];
  WiFiClient client = TCPserver.available();
  if (client) {
    Serial.print(F("Connect to client :"));
    Serial.println(client.remoteIP());
  
    // Daten einlesen
    buffer[0] = 0; // buffer reset
    int i = 0;
    while (client.connected()) {

      while (client.available()) {
        char s = client.read();
        buffer[i] = s;
        i++;
        buffer[i] = 0;
      }
    }

    packSize = strlen(buffer);
    Serial.printf("Received %d bytes\n", packSize);
    Serial.println(buffer);

    delay(1);
    // close the connection:
    client.stop();
    Serial.println(F("Client disconnected"));
  }
}

mehrfach senden musst Du eigentlich bei TCP nicht. In TCP ist ein Protokoll enthält das sicherstellt das die Daten angekommen sind. Das ist bei UDP nicht der Fall. Also entweder ist in den Nutzdaten nichts enthalten oder der client geht zu früh pennen, aber da hast Du schon eine Sekunde drin das sollte reichen.
Kennst Du das tool "Packet Sender" für den PC das könnte dir helfen das Problem weiter einzukreisen.

Gruß Heinz

Eher packetsender.

Gruß Tommy

Hallo @Tommy56
danke für den Hinweis , ist geändert

Gruß Heinz

Mir ist da noch was aufgefallen. Mit deep sleep wird ja jedes mal das Setup durchlaufen. Damit auch obiger Teil. Wenn Du mit delay alle 5 sec sendest dann passiert das auch laufend , also immer 2 mal . Allerdings wir mit deepsleep vorher die Wifi Verbindung neu aufgebaut, ansonsten eben nicht und damit war die alte Verbindung abgebaut.
Eigentlich sollte man jedoch die Verbindung auch abbauen bevor man eine neue aufbaut. Damit sollte nach dem senden und einer Wartezeit ein
client.stop()
rein.
Das sieht bei bir dann so aus.

// -------------- send TCP -------------------------
void sendTCP() {
  Serial.printf("connecting to %s %d \n", host, hostPort);
  WiFiClient client;
  if (!client.connect(host, hostPort)) {
    Serial.println("connection failed");
    //delay(1000);
    return;
  }
  Serial.println(F("sending data to server"));
  Serial.printf("%4d;%4.2f;%4.2f;%4.2f;%4.2f\n", devAdress, temp, hum, pres, Vcc);
  client.printf("%4d;%4.2f;%4.2f;%4.2f;%4.2f", devAdress, temp, hum, pres, Vcc);
  Serial.println(F("closing connection"));
  delay(100);
  client.stop();
}

anschließend warte ich mit delay noch eine Sekunde und gehe dann in den deep sleep.

Gruß Heinz

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.