NodeMCU UDP Paket senden + deepsleep
Hallo zusammen,
ich suche schon lange Zeit den Fehler in meinem Programm und habe mich jetzt entschlossen nach Hilfe zu fragen. Vorab, ich bin Programmierlaie! Verbesserungen sind dringend erwünscht.
Ziel des Programms:
Temperatur und Luftfeuchte aus einem DHT22 auslesen und diese Daten mit einer festen ID per UDP an Broadcast senden. Ein Pythonscript soll später die Daten aufnehmen und weiter verarbeiten.
Problem:
Auch ohne deepsleep funktioniert das Senden nur unregelmäßig. Laut serieller Konsole wird das Paket jedes mal erfolgreich gesendet (Rückgabewert endPacket() ). Im Wireshark ist davon allerdings nur manchmal ein Paket zu sehen. Auch an eine direkte IP statt dem Broadcast treten diese Probleme auf.
Vielleicht kann hier mal jemand drüber sehen und sieht einen Fehler:
Code:
#include <ESP8266WiFi.h> //ESP8266 Core WiFi Library (you most likely already have this in your sketch)
#include <WiFiUdp.h>
#include <DHT.h>
#define DHTPIN 0
#define DHTTYPE DHT22
//Init DHT-Sensor
DHT dht(DHTPIN, DHTTYPE);
//set IPs
IPAddress IPudp (255, 255, 255, 255);
IPAddress IPlocal (192, 168, 10, 201);
IPAddress IPdns (192, 168, 10, 1);
IPAddress IPgateway (192, 168, 10, 1);
IPAddress IPsubnetmask (255, 255, 255, 0);
//*******DeviceID-config************************
char UnitID[] = "id_1";
//******************************************
unsigned int receiveUdpPort = 5006;
unsigned int sendUdpPort = 5005;
char ssid[] = ("Hier steht die SSID");
char passphrase[] = ("hier ist das Passwort");
char charTemp[10];
char charHum[10];
int sendingStat;
WiFiUDP udp;
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n\nSerial connection started");
WiFi.mode (WIFI_STA);
WiFi.config (IPlocal, IPdns, IPgateway, IPsubnetmask);
WiFi.begin(ssid, passphrase);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
Serial.print(WiFi.status());
}
WiFi.printDiag(Serial);
Serial.print(WiFi.status());
pinMode(12, OUTPUT);
}
void loop() {
Serial.printf("Now listening at IP %s, UDP port %d\n\n", WiFi.localIP().toString().c_str(), receiveUdpPort);
digitalWrite(12, HIGH);
delay(3500);
float hum = dht.readHumidity();
float temp = dht.readTemperature();
digitalWrite(12, LOW);
dtostrf(temp,5,2,charTemp);
dtostrf(hum,5,2,charHum);
if (isnan(hum) || isnan(temp)) {
Serial.println("Sensorfehler!");
udp.beginPacket(IPudp,sendUdpPort);
udp.write(UnitID);
udp.write(" Sensorfehler\n");
udp.endPacket();
}
else {
long rssi = WiFi.RSSI();
Serial.println("Sending Sensordata");
if (!udp.begin(receiveUdpPort)) {
Serial.println("UDP Socketerror");
}
Serial.printf("Now sending UDP on port %d \n", sendUdpPort);
udp.beginPacket(IPudp,sendUdpPort);
udp.write(UnitID);
udp.write(" ");
udp.write(charTemp);
udp.write(" ");
udp.write(charHum);
udp.write(" ");
udp.write(rssi);
sendingStat == udp.endPacket();
yield();
if(sendingStat = 1) {
Serial.println("UDP Packet successful send");
}
else {
Serial.println("UDP Packet not send");
}
Serial.println("Wait..");
delay(500);
Serial.print(" UDP Destination IP: :");
Serial.println(IPudp);
Serial.print(" UDP Port: ");
Serial.println(sendUdpPort);
Serial.print(" Device ID: ");
Serial.println(UnitID);
Serial.print(" Temperatur: ");
Serial.println(charTemp);
Serial.print(" Relative Luftfeuchte: ");
Serial.println(charHum);
Serial.print(" Daempfung: ");
Serial.println(rssi);
WiFi.disconnect();
delay(500);
Serial.println("ESP goes to deepsleep");
ESP.deepSleep(15e6);
}
}
Vielen Dank & Gruß
Liste der Anhänge anzeigen (Anzahl: 2)
Danke Moppi für deine Mühe. Mein Code ist genau an diesem Beispiel angelehnt. Um aber nicht doch irgend etwas vermurkst zu haben, habe ich diesen noch mal verwendet und habe dabei alles was mit dem Empfang zu tun hat, raus geschmissen.
Sieht dann so aus:
Code:
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char* ssid = "SSID";
const char* password = "password";
WiFiUDP Udp;
unsigned int localUdpPort = 4210; // local port to listen on
char incomingPacket[255]; // buffer for incoming packets
char replyPacket[] = "Hi there! Got the message :-)"; // a reply string to send back
IPAddress IPudp (255, 255, 255, 255); // <--- wird benötigt, da jetzt kein RemoteIp mehr abgefragt werden kann
unsigned int sendUdpPort = 5005; // <---- wird benötigt, da jetzt kein RemotePort mehr abgefragt werden kann
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(" connected");
Udp.begin(localUdpPort);
Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}
void loop()
{
Udp.beginPacket(IPudp, sendUdpPort);
Udp.write(replyPacket);
Udp.endPacket();
delay(5000);
}
Zitat:
Daher willst Du das Paket mit was Anderem empfangen, als einem nodeMCU z.b. oder?
Richtig, daher sollte das auf meinem Laptop, später auf dem Server, sichtbar sein.
Zitat:
Wenn ich richtig gelesen habe, kommen nicht alle Pakete an? Also kommen welche an. Wenn welche ankommen, funktioniert auch der Versand. Mal anders gefragt, woher weißt Du, dass nicht alle ankommen, vielleicht wurden nicht so viele verschickt, wie Du glaubst?
Richtig, es kommen nicht alle an. Das sehe ich daran, dass der serielle Monitor des Arduino mir brav mitteilt, das ein Paket erfolgreich verschickt wurde (bei meinem Code aus dem ersten Beitrag). Im Netzwerksniffer Wireshark, sowie per Terminalbefehl "netcat -ul 5005" kommen diese Pakete aber nur spradisch an. Laut angehängtem Code sollten das alle 5sek(+Durchlaufzeit) sein. Am NodeMCU sehe ich auch die blaue LED im richtigen Intervall aufleuchten. Das WiFi.disconnect() war eine Idee, dem Accesspoint mitzuteilen, dass die Verbindung beendet wird um nach der Schlafzeit diese wieder korrekt aufzubauen. Auch das yield() ist nur ein Versuch dem Prozessor Zeit zu geben, Hintergrundprozesse wie das Senden, beenden zu können.
Anhang 33789
Hier sieht man die Zeitabstände von Paket zu Paket.
- - - Aktualisiert - - -
Neue Erkenntnis:
Ich habe soeben mal drei Pakete unmittelbar hintereinander geschickt:
Code:
udp.beginPacket(IPudp,sendUdpPort1);
udp.write(UnitID);
udp.write(" ");
udp.write("10000");
udp.write(" ");
udp.write("44.4");
udp.write(" ");
udp.write(rssi);
sendingStat == udp.endPacket();
udp.beginPacket(IPudp,sendUdpPort2);
udp.write(UnitID);
udp.write(" ");
udp.write("20000");
udp.write(" ");
udp.write("44.4");
udp.write(" ");
udp.write(rssi);
udp.endPacket();
udp.beginPacket(IPudp,sendUdpPort3);
udp.write(UnitID);
udp.write(" ");
udp.write("30000");
udp.write(" ");
udp.write("44.4");
udp.write(" ");
udp.write(rssi);
udp.endPacket();
Demnach ist zu erkennen, dass das erste Paket fast nie ankommt, aber häufig Paket 2+3. Aber auch bei Paket2+3 sind manchmal 2-3 Codeschleifen (ca.9sek/loop) durchlaufen, ohne das diese ankommen.
Hier sieht man anhand des Ports, welche Pakete ankommen:
Anhang 33791