PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : NodeMCU UDP Paket senden + deepsleep



d2x
13.11.2018, 18:50
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:

#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ß

HaWe
13.11.2018, 20:40
edit:
hier ist was zu UDP samt fertigem Sketch:
https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/udp-examples.html

Moppi
13.11.2018, 21:40
UDP-Pakete senden geht eigentlich sehr einfach, aber das Empfangen nicht so sehr. Da muss man auch auf die Paketreihenfolge achten, das Paket, welches zuerst ankommt muss nicht das sein, was zuerst verschickt wurde. Wenn die Verbindung einwandfrei ist, müssten aber wenigstens alle Pakete ankommen. Habe selber mal einen UDP-Server in Java geschrieben und das dann so gehandhabt, dass ich wenigstens eine eigene Paketnummer (fortlaufend) in den Daten mitgeschickt habe, weil manchmal kommt es eben doch auf die Reihenfolge an.

MfG

d2x
14.11.2018, 14:53
Vielen Dank für eure Antworten.
Zum Beitrag von HaWe:
Leider basiert dieses Beispiel auf die (ich glaube es nannte sich) POST GET Methode und ich möchte auf jeden Fall ein UDP-Paket senden.
Zum Beitrag von Moppi:
Die Nachteile zum TCP sind mir bekannt. Eine Reihenfolge ist bei nur einem Paket nicht so dramatisch :p
Da ich die Pakete an Broadcast, also an alle sende, müsste ich diese ja immer mit Wireshark sehen. Ich sehe aber nur hin und wieder eines und die meisten Pakete sind entweder nie gesendet oder ich sehe diese einfach nur nicht. Ich bin leider kein Netzwerkprofi....

Edit: Oh ich sehe gerade HaWe hat seine Antwort bearbeitet :cool:
Anhand dieser Beispiele ist mein Quellcode bereits aufgebaut. Leider bringt mich das auch nicht weiter.
Trotzdem vielen Dank :p

Ich habe inzwischen einen weiteren NodeMCU probiert, dort zeigt sich gleiches Verhalten.

Moppi
14.11.2018, 15:27
@d2x
Ja ich habe mir das gedacht, weiß aber nicht, wie man Dir anders helfen soll. War eine Motivation, dran zu glauben dass UDP eigentlich sehr gut funktioniert und einfach zu handhaben ist. Auf Tools die irgendwas sniffen sollen, würde ich mich nicht verlassen. Das ist aber meine persönliche Meinung. Ich würde eine Netzwerkverbindung bauen, die nachweislich funktioniert. Das betrifft auch die Nähe zum Router bei WLAN. Wenn ich dann das Versenden hinbekommen habe, würde ich eine Empfangsroutine bauen und schauen, dass ich das empfange, was versendet wurde. Wenn Du per Broadcast sendest können es eh alle empfangen. Daher würde ich als nächstes Wert auf den Empfänger legen und mich darum kümmern, dass das dort gelesen werden kann, denn dass es nicht ankommt, ist eher unwahrscheinlich; es sei denn, Deine Netzwerkadressen stimmen irgendwo nicht.

Zur Vorsicht würde ich auch erst einmal nichts mit Deep Sleep machen, solang meine Netzwerkkommunikation nicht funktioniert. Immer eins nach dem andern.

Der Link von HaWe sieht doch schon gut aus. POST und GET von HTML her hat nichts mit UDP-Paketen zu tun. Das Beispiel behandelt UDP-Pakete.

Also: Warum bringt Dich das nicht weiter? :confused:

dort zeigt sich gleiches Verhalten ... liegt wohl am Code ;)

MfG

d2x
15.11.2018, 09:23
... liegt wohl am Code
Würde ich ja auch behaupten... Und da ich nicht genau verstehe wo das Problem ist, habe ich ihn oben gepostet :)
Als Empfänger habe ich bereits meinen Laptop eingesetzt und habe dazu netcat (Linux) benutzt: "netcat -ul 5005". Die Pakete werden identisch mit Wireshark angezeigt. D.h. es werden viele Pakete nicht angezeigt.
Die Distanz zum WLAN AP beträgt im übrigen 2m. Auch einen halben Meter daneben ändert sich nichts.
Deepsleep und DHT22 habe ich bereits komplett aus dem Code eliminiert -> keine Änderung.
Wenn mir jemand sagen könnte ob der Code Fehler beinhaltet, wäre ich dankbar.


Danke und Gruß

Moppi
15.11.2018, 10:48
HaWe hatte doch den Link - ich denke der Code von der Seite wird funktionieren (sollte also fehlerfrei sein). Damit würde ich es versuchen, wenn meins nicht funktioniert. Dort ist ja auch der UDP-Empfang drin. Und zum Probieren meine ich, kann man UDP-Pakete auch an sich selber schicken (mit Fragezeichen, das würde ich auch versuchen). Du sagst auch: Pythonscript soll das weiter verarbeiten. Daher willst Du das Paket mit was Anderem empfangen, als einem nodeMCU z.b. oder?

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?
Jedesmal machst Du anscheinend ein: WiFi.disconnect(); Ist das richtig? Was passiert, wenn Du mehrere Pakete verschickst, ohne WiFi.disconnect() zwischendurch?

MfG

d2x
15.11.2018, 14:40
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:

#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);

}




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.


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.

33789

Hier sieht man die Zeitabstände von Paket zu Paket.

- - - Aktualisiert - - -

Neue Erkenntnis:
Ich habe soeben mal drei Pakete unmittelbar hintereinander geschickt:


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:
33791

Moppi
15.11.2018, 18:08
Das ist in der Tat merkwürdig. Aber aus Erfahrung weiß ich: Du bist einen Schritt weiter. :)
Ich bin nahe dran, den Code selber auf ein nodeMCU zu packen und es auszuprobieren. Es wäre möglich, das WiFiUdp.h Schuld daran ist, dass manche Pakete nicht ankommen. Aber nun gilt es, den Haken zu suchen, wo es hängt. Ist immer dasselbe Spiel: Fehler einkreisen, auch wenn es manchmal sehr mühevoll ist.
Der Code, den Du oben hier reingestellt hast, ist der vollständig, dass man den einfach ausprobieren kann?
Trotzdem würde ich ein zweites nodeMCU nutzen, um das auszuprobieren, ob dort auch nur die Pakete ankommen, die Du in den Tools bei Dir auch sehen kannst. Das müsste ja dann identisch sein.

MfG

d2x
15.11.2018, 19:15
Trotzdem würde ich ein zweites nodeMCU nutzen, um das auszuprobieren, ob dort auch nur die Pakete ankommen, die Du in den Tools bei Dir auch sehen kannst. Das müsste ja dann identisch sein.
Vollkommen identisch. Dieser NodeMCU ist sogar aus einer anderen Lieferung. Den Tipp mit der WiFiUdp.h finde ich gut! Ich werde mal sehen ob eine neue Version zu finden ist und werde berichten :)

HaWe
15.11.2018, 19:58
fangen wir doch mal ganz elementar an:
welche Versionen hast du?
Arduino IDE (1.8.6 ?)
welches nodeMCU board (nodeMCU 1.0 = ESP-12E?)
welche esp8288 board core Version (2.4.0 oder 2.4.2 ?) ( <<< 2.4.2 funktioniert bei mir nicht, nur 2.4.0)
hast du die neuesten libs für #include <ESP8266WiFi.h> und #include <WiFiUdp.h> ? https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WiFi/src

kannst du auch dieses (umgekehrte) Besipiel aus 6/2018 probieren : https://github.com/esp8266/Arduino/blob/master/doc/esp8266wifi/udp-examples.rst ?

falls wir hier nicht weiter kommen:
poste mal deinen issue hier bei den Fachleuten/Entwicklern: https://github.com/esp8266/Arduino/issues

d2x
15.11.2018, 21:08
Arduino IDE 1.8.3
nodeMCU Board ist das ESP-12E
ESP8266 Board Core Version : Wo kann ich die Versionsnummer checken?
Die lib ESP8266WiFi von Ivan Grokhotkov ist Ver 1.0 und beinhaltet scheinbar auch die WiFiUdp.h . Über die Biblithekenverwaltung nicht updatebar.

Ich habe das Beispiel 1:1 probiert und bekomme immer zuverlässig eine Antwort !!!

Ich fürchte wir kommen weiter :)

Was ist jetzt der Unterschied? Im Großen und Ganzen würde ich sagen, arbeitet das Beispielscetch mit remoteIP() und remotePort() ... ich hatte in meinem Code auch eine direkte IP (allerdings vom Router) getestet, habe aber auch das Problem gehabt. Ich versuche mal die IP vom Laptop. Bisher dachte ich eigentlich immer das sei egal.... ich probiere es mal.

EDIT:

Fehler gefunden!
Es muss scheinbar die richtige Adresse der Gegenstelle, in meinem Fall die des Laptops, angegeben werden. Es kommt dann jedes Paket an. Kann mir jemand erklären wieso ich die Pakete nicht zuverlässig / vollständig sehen kann wenn diese an Broadcast oder an eine andere IP adressiert sind ? Was macht "Broadcast" denn dann für ein Sinn, wenn es nicht ankommt?

EDIT2:

Mein Code aus dem 1.Beitrag läuft damit allerdings immer noch nicht zuverlässig.....
Es scheint am deepSleep zu liegen. Ohne geht es und mit kommt wieder nur ab und zu ein Paket an.

Moppi
16.11.2018, 07:39
Mit dem Deep Sleep ist das so eine Sache. Es gibt verschiedene Schlaf-Modi, auch das Netztwerkmodul vom nodeMCU kann abgeschaltet werden. Er benötigt Zeit um alles wieder in Betrieb zu nehmen und die Verbindung muss wieder hergestellt werden. Vielleicht bist Du an irgendeiner Stelle einfach zu schnell. Musst überall zum Probieren mal längere Pausen einbauen und gucken, ob es dann funktioniert. Dann rausfummeln, wo er mehr Zeit benötigt, als Du dachtest.

Deine Daten waren:

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);


Dein Netz ist 192.168.10. Dein Paket sollte per Broadcast an 192.168.10.255 gesendet werden, damit es innerhalb DEINES Netzes an jeden Teilnehmer verteilt wird. Ich glaube, Du bringst den Router ganz schön durcheinander.

MfG

d2x
16.11.2018, 08:03
Guten Morgen Moppi,

das war tatsächlich anfangs so. Ich habe mir das auch für die Fehlerbehebung irgendwo abgeguckt.

Ich habe jetzt noch mal getestet:

-ohne deepSleep an 192.168.10.255 -> Pakete kommen nur sporadisch an
-ohne deepSleep an 192.168.10.68 -> Pakete kommen alle an.

-mit deepSleep muss noch etwas anderes faul sein. Was, muss ich noch herausfinden....
Die Resetleitung ist aber angeschlossen, so viel kann ich schon mal sagen :p

Moppi
16.11.2018, 09:02
Guten Morgen auch!

Wenn die Pakete an eine bestimmte Adresse alle ankommen, werden sie auch alle vom nodeMCU verschickt. Egal, ob sie nach .68 oder nach .255 verschickt werden, sie werden immer alle verschickt. Das nodeMCU ist nicht für die Verteilung zuständig.


Die Resetleitung ist aber angeschlossen, so viel kann ich schon mal sagen
Vielleicht stehst Du auf selbiger ;)

Gibt es beim Router oder was Du verwendest Einstellungen zu Broadcast-Nachrichten oder etwas, das was mit Broadcast zu tun hat? Zeitliche Limits oder irgend etwas?

Normalerweise hat man in einem Netzwerk ja mehrere Teilnehmer. Was passiert, wenn Du nur noch einen Empfänger für die UDP-Pakete hast? Kommen dann alle Pakete dort an?

MfG

HaWe
16.11.2018, 10:16
ESP8266 Board Core Version : Wo kann ich die Versionsnummer checken?
Die lib ESP8266WiFi von Ivan Grokhotkov ist Ver 1.0 und beinhaltet scheinbar auch die WiFiUdp.h . Über die Biblithekenverwaltung nicht updatebar.

nur zur Info, da das Problem ja offenbar jetzt woanders lokalisiert wurde:
- die board core Version kannst du über den Boardverwalter sehen, einstellen und installieren: esp8266 eingeben, unter "Info" stehen dann verschiedenen cores zur Auswahl.
- du kannst auch direkt von der github Seite die aktuellen libs einzeln downloaden und ins libraries Verzeihnis kopieren; gerade weil esp8266 nicht von den Arduino.cc Leuten stammt, werden im library manager nicht immer die aktuellsten libs in der IDE bereitgestellt.

Und damit klinke ich mich gleich wieder aus... 8)

d2x
16.11.2018, 10:18
Vielleicht stehst Du auf selbiger
Ich hoffe dem ist nicht so :cool:


Gibt es beim Router oder was Du verwendest Einstellungen zu Broadcast-Nachrichten oder etwas, das was mit Broadcast zu tun hat? Zeitliche Limits oder irgend etwas?

Normalerweise hat man in einem Netzwerk ja mehrere Teilnehmer. Was passiert, wenn Du nur noch einen Empfänger für die UDP-Pakete hast? Kommen dann alle Pakete dort an?

Es kommen ca. 90% der Pakete an Broadcast an wenn ich Laptop und NodeMCU über einen Android-Hotspot laufen lasse.
Scheinbar frisst meine Hardware die Pakete :MistPC:

Der Accesspoint läuft mit einem Open-WRT, der Router ist eine Fritzbox. Ich habe gerade mal durchgesehen und nichts mit Braodcast gefunden.. Die Firewall ist im Open-WRT-AP ausgeschaltet.

@HaWe: vielen Dank
Boardversion ist die 2.4.0

Moppi
16.11.2018, 12:41
Du kannst natürlich mit dem nodeMCU die Pakete auch an jeden Rechner einzeln schicken. Wenn das besser funktioniert. Oder Du schickst jedes Paket 3mal, damit es min. einmal ankommt, bis das Problem gefunden ist.

MfG

HaWe
16.11.2018, 13:43
Du kannst natürlich mit dem nodeMCU die Pakete auch an jeden Rechner einzeln schicken. Wenn das besser funktioniert. Oder Du schickst jedes Paket 3mal, damit es min. einmal ankommt, bis das Problem gefunden ist.

MfG

oder solange wiederholt senden, bis alle ein ack zurückgesendet haben 8)

Klebwax
16.11.2018, 17:04
Als Empfänger habe ich bereits meinen Laptop eingesetzt und habe dazu netcat (Linux) benutzt: "netcat -ul 5005".

Das ist das Problem. netcat spielt nicht gut mit UDP-Boadcasts. Mit "socat" klappt das besser.

MfG Klebwax

d2x
16.11.2018, 19:26
Du kannst natürlich mit dem nodeMCU die Pakete auch an jeden Rechner einzeln schicken. Wenn das besser funktioniert. Oder Du schickst jedes Paket 3mal, damit es min. einmal ankommt, bis das Problem gefunden ist.
An Broadcast wollte ich eigentlich senden, falls der Server mal die IP ändern sollte.


oder solange wiederholt senden, bis alle ein ack zurückgesendet haben
Zurücksenden wollte ich eigentlich nicht. Zumindest war das bisher nicht geplant. Aus übungstechnischer Sicht wäre das allerdings eine Maßnahme. Es ist auch nur ein Empfänger.


Das ist das Problem. netcat spielt nicht gut mit UDP-Boadcasts. Mit "socat" klappt das besser.
Ich konnte bisher keine Mängel bei netcat feststellen. Die Anzeige ist identisch mit Wireshark gewesen. Ich werde es mir dennoch mal ansehen.

Aktueller Stand:
Ohne deepSleep kommen die Pakete zuverlässig an. Mit deepSleep kommen sie an, wenn sie gerade mal Lust haben.

HaWe
16.11.2018, 20:32
brauchst du notwendigerweise deepsleep?
Ich nutze auch für html webserver inzwischen nur noch delay() in der loop()

d2x
16.11.2018, 20:43
Ich möchte einige Sensoren mit Batterien versorgen (Sensor heißt NodeMCU + DHT22 o.ä.) . Daher benötige ich einen Aufbau der wenig Energie benötigt. Ich schalte sogar den DHT22 erst kurz vor dem Auslesen ein und anschließend wieder aus.

Moppi
16.11.2018, 21:16
Kannst Du den Code noch mal posten, den du aktuell verwendest, so wie er funktioniert, dass alle Pakete ankommen und so, wie er nicht funktioniert?

Wenn Du schreibst Deep Sleep, dann ist WiFi = Off, System Clock = Off und CPU = Off.
Zumindest von dem WiFi-Modul habe ich schon gelesen, dass es einige Zeit benötigt, bis es quasi wieder richtig funktioniert.

Irgendwo steht doch in Deinem Code: WiFi.begin ...
Schreib vor diesem Befehl mal versuchsweise: WiFi.forceSleepWake();


MfG

d2x
16.11.2018, 22:23
https://github.com/esp8266/Arduino/issues/3481

Kommt mir sehr bekannt vor! Ich sende auch nur ein einziges Paket!

Hier der Code der funktioniert:

#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 (192, 168, 10, 68);
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[] = ("xxx");
char passphrase[] = ("xxx");
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);
Serial.printf("Now listening at IP %s, UDP port %d\n\n", WiFi.localIP().toString().c_str(), receiveUdpPort);
delay(5000);

}


void loop() {

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);
delay(1000);
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 0,5s..");
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);
//udp.stop();
//WiFi.disconnect();
//WiFi.mode(WIFI_OFF);
Serial.println("wait 5,5s");
delay(5500);
//Serial.println("ESP goes to deepsleep 60s");
//ESP.deepSleep(60e6);
delay(100);
}

}


Und dieser funktioniert nicht zuverlässig. Die Pakete kommen zwischen ca. 10s - 500s an (Unterschied nur in den letzten, nicht mehr auskommentierten Zeilen):

#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 (192, 168, 10, 68);
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[] = ("XXX");
char passphrase[] = ("XXX");
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);
Serial.printf("Now listening at IP %s, UDP port %d\n\n", WiFi.localIP().toString().c_str(), receiveUdpPort);
delay(5000);

}


void loop() {

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);
delay(1000);
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 0,5s..");
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);
udp.stop();
WiFi.disconnect();
WiFi.mode(WIFI_OFF);
Serial.println("wait 5,5s");
delay(5500);
Serial.println("ESP goes to deepsleep 60s");
ESP.deepSleep(60e6);
delay(100);
}

}

Moppi
17.11.2018, 08:07
Irgendwo steht doch in Deinem Code: WiFi.begin ...
Schreib vor diesem Befehl mal versuchsweise: WiFi.forceSleepWake();

Und wie ist das Ergebnis damit?

Und nochmal eine andere blöde Frage von mir, weil ich das mit dem nodeMCU noch nicht ausprobiert habe.
Und zwar: Wenn er aus dem Schlafmodus zurückkehrt, wo läuft das Programm weiter? - Startet der Kontroller komplett neu oder macht er in Loop weiter? Mich irritiert, dass zwar Sachen ausgeschaltet werden, die für die Kommunikation benötigt werden, aber in Loop nicht wieder eingeschaltet werden.


Ich habe das Problem auch noch anderweitig im Netz gefunden, aber ich denke, das muss abzustellen sein. Es sei denn, das WiFi-Modul wäre defekt oder so, aber das ist es nicht, also muss es eine Lösung geben. Wer baut bitte einen Sleep-Mode ins nodeMCU ein, wenn hinterher das integrierte WiFi nicht mehr richtig funktioniert ...

Nachtrag: Habs schon gefunden: der ESP startet neu, nach Deep Sleep

60e6 = 24806 Millisekunden oder wieviel ist das in Sekunden? - 60 sec

Die serielle Kommunikation (Serial...) bitte mal raus nehmen, die brauchst Du später sowieso nicht. Beschränke mal auf das, was das nodeMCU später tun soll. Nämlich Datenerfassung und per WiFI und UDP verschicken.

Nachtrag:

Und zum Schluss vorerst eine andere Vorgehensweise:
Wenn das nodeMCU startet, sende mal bitte ein Paket an das nodeMCU selber (und nur dieses) und warte bis das angekommen ist. Eigentlich müsste das nodeMCU die Pakete, die per Broadcast gesendet werden, auch wieder empfangen können. Daher würde ich ein Paket mit dem nodeMCU verschicken und prüfen, ob das beim nodeMCU auch an kommt. Wenn nicht, würde ich das Paket nochmal senden und warten ob es dann ankommt. Die Alternative ist eben, das erste "Verfikations"-Paket nur an das nodeMCU zu schicken, dass es auch verschickt. Wenn das erfolgreich war, würde ich schauen, ob danach jedes weitere UDP-Paket im Netzwerk ankommt, das verschickt wird.

Im Netz werden unterschiedliche Probleme mit dem Deep Sleep beschrieben und jeder hat andere Erfahrungen damit.


MfG

HaWe
17.11.2018, 11:08
Und nochmal eine andere blöde Frage von mir, weil ich das mit dem nodeMCU noch nicht ausprobiert habe.
Und zwar: Wenn er aus dem Schlafmodus zurückkehrt, wo läuft das Programm weiter? - Startet der Kontroller komplett neu oder macht er in Loop weiter?
MfG
er startet dann komplett neu, inkl. setup().

Der DHT11 ist übrigens auch extrem zickig, er braucht oft bis zu 2sec, bis er nach mehrmaligem Versuch überhaupt Daten liefert, davor ist alles ungültig. Viel bessere Ergebnisse habe ich mit BME280 und BMP280 per i2c.

Moppi
17.11.2018, 11:36
Schön und optimal ist das sicher alles nicht.

Einer schrieb irgendwo, dass er eben WiFi.forceSleepWake(); VOR WiFi.begin(); eingesetzt hat und es dann funktionierte. Andere stellen fest, dass das nodeMCU erst, nachdem es einmal Daten empfangen hat, Daten sicher verschickt. Obwohl das irgendwie alles nicht richtig ist, finde ich. Praktisch startet das nodeMCU neu mit allem drum und dran - hoffentlich. Dann muss es sich ordentlich und sicher am Netzwerk angemeldet haben und dann sollte man auch Daten verschicken können, ohne dass etwas verloren geht. Wenn das nodeMCU aus einer Batterie versorgt wird, kann es an der Spannungsquelle auch nicht liegen, so wie dann wieder auf einer andern Seite geschrieben wird. Wobei es so sein soll, dass das nodeMCU beim Starten mehr Strom benötigen soll (oder so ähnlich), so dass die Spannungsquelle hier mitspielen muss, dass es nicht zu diffusen Fehlern kommt.

MfG

HaWe
17.11.2018, 11:47
ich würde dazu raten, das Problem ganz neu im esp8266 Forum als issue zu melden - und vorher sicherheitshalber auch auf IDE 1.8.6, den neuesten esp core 2.4.2 und auch die neueste esp8266WiFi lib etc. abzudaten, denn es werden die issues nur bei den jeweils neuesten Versionen von den Entwicklern bearbeitet.

Es wird dort auch immer ein minimalistischer lauffähiger Test-Sketch verlangt, den würde ich in jedem Falle mit konstanten oder überprüfbaren randomisierten Werten OHNE DHT11 schreiben.

Moppi
17.11.2018, 18:34
Bitte diese Seite mal durchlesen, das Beispiel scheint auch zu funktionieren und Hinweise zu Problemen gibts auch.

https://www.arduino-hausautomation.de/2017/esp8266-im-tiefschlaf/

MfG
Moppi

d2x
18.11.2018, 11:47
Hallo zusammen,

vielen Dank erst einmal für eure tolle Unterstützung!


Und wie ist das Ergebnis damit?
Leider konnte ich mit WiFi.forceSleepWake(); keinen Unterschied feststellen.
Hier ein kurzer Auszug wie ich es eingebaut habe:

void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n\nSerial connection started");

WiFi.forceSleepWake();
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);
Serial.printf("Now listening at IP %s, UDP port %d\n\n", WiFi.localIP().toString().c_str(), receiveUdpPort);
delay(5000);

}


Die serielle Kommunikation (Serial...) bitte mal raus nehmen, die brauchst Du später sowieso nicht. Beschränke mal auf das, was das nodeMCU später tun soll. Nämlich Datenerfassung und per WiFI und UDP verschicken.
Werde ich machen.


Und zum Schluss vorerst eine andere Vorgehensweise:
Wenn das nodeMCU startet, sende mal bitte ein Paket an das nodeMCU selber (und nur dieses) und warte bis das angekommen ist. Eigentlich müsste das nodeMCU die Pakete, die per Broadcast gesendet werden, auch wieder empfangen können. Daher würde ich ein Paket mit dem nodeMCU verschicken und prüfen, ob das beim nodeMCU auch an kommt. Wenn nicht, würde ich das Paket nochmal senden und warten ob es dann ankommt. Die Alternative ist eben, das erste "Verfikations"-Paket nur an das nodeMCU zu schicken, dass es auch verschickt. Wenn das erfolgreich war, würde ich schauen, ob danach jedes weitere UDP-Paket im Netzwerk ankommt, das verschickt wird.
Das klingt gut! Ich werde die Pakete an 127.0.0.1 schicken, falls das funktioniert..


Der DHT11 ist übrigens auch extrem zickig, er braucht oft bis zu 2sec, bis er nach mehrmaligem Versuch überhaupt Daten liefert, davor ist alles ungültig. Viel bessere Ergebnisse habe ich mit BME280 und BMP280 per i2c.
Das habe ich auch gelesen und habe deshalb ein delay von 3,5s eingebaut.


Schön und optimal ist das sicher alles nicht.
Das sehe ich auch so, denn zu starten und mehr oder weniger nur ein UDP-Paket zu senden ist, denke ich, für ein mit WiFi ausgestatter Mikrokontroler keine überragende Leistung .. Komischer Weise scheint ja das Beispielscetch tadellos zu funktionieren. Also, wo ist der unterschied? In erster Linie sehe ich da nur das zuvor empfangene Paket und das Senden an die RemoteIp + RemotePort...


Wobei es so sein soll, dass das nodeMCU beim Starten mehr Strom benötigen soll (oder so ähnlich), so dass die Spannungsquelle hier mitspielen muss, dass es nicht zu diffusen Fehlern kommt.

Das werde ich auch noch mal testen. Bisher hing der ESP immer am USB-Port des Laptops (soweit ich weiß ~500mA?! ) Ich werde mal ein 2A starkes Steckernetzteil nehmen.


ich würde dazu raten, das Problem ganz neu im ESP8266 Forum als issue zu melden - und vorher sicherheitshalber auch auf IDE 1.8.6, den neuesten esp core 2.4.2 und auch die neueste esp8266WiFi lib etc. abzudaten, denn es werden die issues nur bei den jeweils neuesten Versionen von den Entwicklern bearbeitet.

Es wird dort auch immer ein minimalistischer lauffähiger Test-Sketch verlangt, den würde ich in jedem Falle mit konstanten oder überprüfbaren randomisierten Werten OHNE DHT11 schreiben.
Ich werde in der Tat mal alles auf den neuesten Versionsstand bringen. Das Melden hebe ich mir noch auf...


Bitte diese Seite mal durchlesen, das Beispiel scheint auch zu funktionieren und Hinweise zu Problemen gibts auch.

https://www.arduino-hausautomation.d...im-tiefschlaf/
Diese Seite habe ich auch schon studiert :)

Leider habe ich nicht durchgängig viel Zeit um an diesem Problem zu arbeiten, ich bemühe mich aber schnell Neuigkeiten zu berichten :)

HaWe
18.11.2018, 17:22
es reicht nicht, beim DHT11 einfach per delay(3500) zu warten - man muss es mehrfach immer wieder probieren, bis man gültige Werte erhält.

d2x
18.11.2018, 22:02
man muss es mehrfach immer wieder probieren, bis man gültige Werte erhält.
Kann ich für den DHT22 nicht bestätigen. Ich erhalte immer eine zuverlässige Antwort, auch bei kürzerer Zeit.

HaWe
19.11.2018, 11:55
Kann ich für den DHT22 nicht bestätigen. Ich erhalte immer eine zuverlässige Antwort, auch bei kürzerer Zeit.

muss nicht, nein, und der 22er ist auch besser als der 11er, aber es KANN passieren. Ich selber frage erst immer nach dem Pollen nach nan, und wenn ja, nochmal probieren, ansonsten weitermachen.


float ftmp = DHT11.readTemperature(); // Temperatur auslesen (Celsius)
delay(10);
if (isnan(ftmp)) {
// error, ggf auch in while() Schleife
}
else {
// ok, weitermachen
}

d2x
22.11.2018, 22:06
So, ich habe mich mal wieder mit dem Thema beschäftigen können.

Ein anderes Netzteil bringt keinen Unterschied

Was ich inzwischen herausgefunden habe:
Wenn deepSleep nur einen Durchlauf zulässt, scheint das Senden noch nicht sofort zu funktionieren. Wenn ich 20..30 Pakete vorher an einen anderen Port sende, dann kommt die Nachricht an. (Man könnte die Pakete auch an den gleichen Port senden.) Ich habe diese per For-Schleife geschickt bevor ich meine Nachricht geschickt habe. Ich werde jetzt mal probieren, das deepSleep in eine if-Abfrage zu stecken, damit die loop-Schleife ein paar Runden drehen kann bevor ich meine Nachricht sende. Mal sehen ob ich das morgen mal schaffe. Ich melde mich dazu.
Fakt ist, inzwischen bekomme ich es relativ zuverlässig hin, Pakete per UDP mit deepSleep zu senden. Die Lösung ist bisher allerdings noch etwas hässlich und daher werde ich das oben genannte die Tage mal probieren.
Gruss

Moppi
23.11.2018, 09:12
Guten Morgen d2x,

prima, dass Du dran geblieben bist!

Stichwort eingesetzte Bibliotheken:
Mit einem ATmega328P habe ich auch Probleme mit den Sleep-Modi. Nicht dass es nicht funktioniert, nur mit der Stromaufnahme, die nicht "weit genug" sinkt. Hier ist es mir so ergangen, dass die "sleep.h" und die "power.h" verwendet werden - jedenfalls in den meisten Beispielen, die ich im Internet fand. Ich fand dann noch eine Anleitung, die diese Bibliotheken umgeht und auch in den Deep-Sleep-Power-Down wechselt und zwar mit deutlich mehr Stromersparnis.

MfG

d2x
03.12.2018, 10:27
Update:
Die oben genannten Maßnahmen führen zwar dazu, dass zu 95% das Paket ankommt, hin und wieder reichen aber selbst 150 vorab gesendete Pakete nicht aus. Diese sind dann inklusive meinem Paket mit den Daten verloren.

Moppi
03.12.2018, 14:14
Wenn Du den Sleep-Mode nutzt, geht das doch bei nodeMCU nur per Reset, weil was anderes nicht funktioniert - hatte ich so gelesen.
Probiere mal ohne den Sleep-Modus und mache mit einem Taster am nodeMCU einen längeren Reset. Ob das dann genau so ist oder dann immer funktioniert.
Dann wenn er im Sleep-Mode drin ist, auch mal mit einem Taster am nodeMCU einen langen Reset machen und schauen, wie sich das dann verhält.

Kann es sein, dass das nodeMCU nach einem Reset manchmal nicht richtig "anspringt"?

MfG

d2x
03.12.2018, 21:27
Das werde ich mal testen.
"Nicht richtig anspringt" kann grundlegend nicht der Fall sein, da ich über die serielle Schnittstelle jeden Schritt nachvollziehen kann und das ab dem ersten Loopdurchgang.

Moppi
03.12.2018, 21:41
Ja, aber z.B. das WiFi-Modul oder andere Bausteine auf dem Modul. Irgendetwas muss es ja sein, was mal einwandfrei und mal nicht einwandfrei funktioniert. Sonst hättest Du keine Probleme damit.

Falls das mit dem manuellen Reset dann einwandfrei funktionieren sollte, dann könntest Du eine extra Reset-Schaltung bauen, die einen sauberen Reset durchführt. Das war die Idee dahinter.

Ansonsten wüsste ich auch nicht, was man da noch machen sollte. Leider habe ich zurzeit zu viel zu tun, als nochmals mit was anderem anzufangen. Sonst hätte ich das selber schon ausprobiert. Es ist ja sowieso schon so eine Sache, dass nur eine Art Rückkehr vom Sleep Mode funktionieren soll, weil die anderen Arten nicht richtig implementiert sind, dass sie einwandfrei anwendbar wären. Oder hat sich das in der Zwischenzeit mal geändert?

MfG

d2x
05.01.2019, 14:55
Hallo zusammen,

ich möchte mich noch einmal zu meinem Problem melden. Ich habe es nach wie vor nicht zuverlässig geschafft ein einzelnes UDP-Paket zu senden. Es kann ja nicht sein, erst eine Menge Pakete vorab zu schicken um dann immer noch nicht zuverlässig ein Paket zu senden. Sollte es also jemand schaffen, nach dem Bootvogang des ESP8266 bzw. NodeMCU ein einzelnes UDP-Paket zu verschicken, welches auch auf der Gegenseite ankommt, der möge bitte hier seinen Arduino-Sketch posten. Nach Möglichkeit sollte das Sketch nur ein Paket senden und dann wieder den Tiefschlaf aufrufen.

Wie ich mein Problem jetzt gelöst habe:

MQTT

Ich habe einen MQTT-Clienten eingebunden womit ich nun meine Werte an den MQTT-Broker auf den Server sende. Das funktioniert einwandfrei und zuverlässig!

Viele Grüße

Moppi
05.01.2019, 15:38
Aber MQTT arbeitet ja nun mit TCP. Dennoch geht das ja über WLAN. Und auch hier wirst Du das nodeMCU nach einem Reset neu verbinden müssen oder?
Also meine Erfahrungen mit UDP waren jedenfalls durchweg positiv - zumindest in einem normalen LAN. Da ist nie was abhanden gekommen.

Na, wenigstens hast Du eine Lösung gefunden.


MfG

d2x
07.01.2019, 22:46
Das mit dem LAN hatten wir ja gemeinsam durch probiert. Daran lag es scheinbar nicht. Neu verbinden muss er sich jetzt auch.



Also meine Erfahrungen mit UDP waren jedenfalls durchweg positiv
Dann schreib doch bitte mal ein Scetch indem ein einziges UDP-Paket einen String übermittelt und sich dann der ESP eine Minute schlafen legt. Wie gesagt, eigentlich kein Hexenwerk...:)

Moppi
08.01.2019, 00:05
Ich redete von LAN. Habe mal mit Java auf nem Server einen Chat für Browser gebaut, dort habe ich wegen der Einfachheit UDP verwendet. Nicht nur, dass sich das einfach implementieren lies (wie ich fand) es funktionierte dort auch einwandfrei.

Ich hätte das auch mit dem nodeMCU probiert, aber meine Pläne hatten sich zerschlagen. Ich hatte das nodeMCU schon rausgekramt, Maß genommen (Gehäuse) und wollte loslegen. Dann sah ich, dass nur ein Analogeingang da sein soll. Ich dachte an Multiplexen des Aanlog-Eingangs am nodeMCU, mir ist aber keine brauchbare Lösung eingefallen, so dass ich wieder beim ATmega328 hängen geblieben bin. Sonst hätte ich mich schon hier gemeldet, hätte das dann wahrscheinlich auch per UDP versucht.

Ich schaue mal was, hatten wir hier nicht so einige Links von Beispielcodes?

MfG

Moppi
08.01.2019, 08:12
Ich habe es jetzt mal ausprobiert.

Ich habe dabei auf eine Netzwerkadresse direkt gesendet xxx.xxx.x.1 und auf Broadcast xxx.xxx.x.255. Als Testtool habe ich Packet Sender installiert. UDP-Adresse 58817.
Beim Deep Sleep habe ich einen Wert von 128 eingesetzt. Das sind Abstände von ca. 6 Sekunden in denen er schläft, aufwacht (Reset) und Paket sendet.
Die Pause vor einem Deep Sleep habe ich mit "delay(5000)" gemacht.

Jedes Paket kommt an.

Das Versenden der Pakete dauert durchaus, mit Anmelden am Netzwerk, ein paar Sekunden. Geht das nodeMCU zu schnell in Deep Sleep, wird kein Paket versendet.

Ich habe auch ein nodeMCU, das rumspinnt, weil es ständig Ausnahmefehler produziert und also immer neu startet. Ich habe dann ein anderes nodeMCU genommen, gleiche Sorte (hatte 5 bestellt), das funktioniert scheints einwandfrei.

Jedenfalls, bei diesem ersten Test jetzt kann ich nicht erkennen, dass nichts ankommt, das Gegenteil ist der Fall.

Ich habe die FritzBox Cable 6360.

Ich habe die Sleep-Zeit auf ca. 1min verlängert:

33925


Ich sehe, ob alle Pakete ankommen, weil ich immer nur ein Paket verschicke. Nicht mit mehreren Versuchen (zig Pakete bis eins ankommt).


MfG

PS:


#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#define PORT 50000 //ab 50000 ist mir sicherer, habe ich irgendwann mal ausspioniert, untenrum muss man bei Portnummern ggf. mit Kollisionen anderer Programme rechnen
WiFiUDP udpServer;


const char* ssid = "xxxxxxx"; //SSID WLAN Netz
const char* password = "xxxxxxxxxxxxxxxxxxxxxxx"; //Passwort des WLAN Netzes
const char* ziel = "192.168.0.255"; //Empfänger Broadcast-Adresse xxx.xxx.x.255 !


void setup() {
Serial.begin(115200);
delay(10);


Serial.println();
Serial.println();
Serial.print("Verbinde mich mit Netz: ");
Serial.println(ssid);

WiFi.begin(ssid, password);
WiFi.config(IPAddress(192,168,0,xx), IPAddress(192,168,0,x), IPAddress(255,255,255,0), IPAddress(192,168,0,x));
//richtige Konfiguration - 192,168,0,x : IP-Adresse der FritzBox
//und 192,168,0,xx : IP-Adresse dieses nodeMCU
//255,255,255,0 : Subnetzmaske

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}


Serial.println("");
Serial.println("WiFi Verbindung aufgebaut");
Serial.print("Eigene IP des ESP-Modul: ");
Serial.println(WiFi.localIP());


// UDP Server starten
udpServer.begin(PORT);


delay(500);


if(udpServer.beginPacket(ziel, 58817)==1)Serial.println("beginPacket - ok"); //Zielport muss natürlich stimmen, nicht irgendwo hin schicken - ziel ist hier Broadcast-Addresse (s.o.)
//Port: >50000
udpServer.write("Hallo");
udpServer.endPacket();






}


void loop() {
delay(5000); //extremst wichtig - UDP-Paket muss erst sicher versendet sein!
ESP.deepSleep(60*1000000);
}

d2x
08.01.2019, 21:33
Hallo Moppi,

recht herzlichen Dank das du dir die Mühe gemacht hast!!!
Ich werde in einer ruhigen Minute deinen Scetch ausprobieren. Bis auf die enormen delays erst einmal kein großer Unterschied meine ich. Das die Wartezeiten eingehalten werden müssen wusste ich ja, aber soo lange ist mir neu. Ich bin gespannt ob mein ESP deinen Code frisst und endlich das macht was er soll:)

Zum Thema MQTT kann ich dennoch sagen, dass es vom Handling auch echt super funktioniert.

Gruß d2x

Moppi
08.01.2019, 22:29
Das delay() ist so lang, weil ich sehen wollte, ob es überhaupt funktioniert. Wäre auch erstaunlich, wenn jedes Paket so viel Zeit braucht. Habe nur gesehen, dass es nicht ankommt, wenn man nicht wartet. Immerhin wird jedes mal eine Netzwerkverbindung hergestellt, vielleicht dauert auch das nur einmal so lange und Verschicken geht schneller. Jedenfalls kommt ohne das delay() nix an.

Nun müsstest Du aber analysieren können, warum es bei Dir nicht funktioniert hat.

Ansonsten bin ich so vorgegangen, wie wir vorher schon besprochen hatten, bzw. wie meine Vorschläge waren. Zuerst Fragmente aus dem Internet zusammengesucht und Eigene verwendet, bis es funktionierte. Dann mit dem Hardwarereset-Taster am Modul geschaut, ob es nach dem Starten jedes mal funktioniert. Dann den Sleep eingebaut, dann das delay(). Habs dann noch ein wenig aufgeräumt, damit man durchblickt. War auch noch eine Empfangsroutine drin, die hat auch funktioniert, aber das war ja nun für das Beispiel nicht notwendig.

Interessant ist jetzt natürlich, wo bei Dir das Problem lag.

MfG

Moppi
09.01.2019, 14:25
Ich habe mir den Code jetzt mal angeschaut, was Du anders gemacht hast:

WiFi.mode (WIFI_STA);

verwende ich nicht, sollte aber kein Problem sein.

Die Konfiguration hast Du rausgenommen:

//WiFi.config (IPlocal, IPdns, IPgateway, IPsubnetmask);

Also benutzt Du DHCP...
Frage wäre, ob die FritzBox (die hattest Du doch auch) im Minutentakt neue IP-Adressen für eine MAC-Adresse vergibt. Und wenn, ob dadurch evtl. Schwierigkeiten entstehen.
Der Aufruf der Funktion oben unterscheidet sich außerdem, ich verwende die so:

WiFi.config (IPlocal, IPdns, IPsubnetmask, IPgateway);

Das Senden von Daten läuft dann offenbar identisch, so wie ich es auch mache.

Zum Schluss aber tust Du dann noch das alles:

udp.stop();
WiFi.disconnect();
WiFi.mode(WIFI_OFF);

Wobei ich nicht denken würde, dass letzteres ein Problem darstellen würde. Allerdings brichst Du damit alles ab und u.U. bevor das Paket richtig verschickt wurde. Ich habe davor keine Pause gefunden.

Du tust zwar dieses:

if(sendingStat = 1) {
Serial.println("UDP Packet successful send");
}
else {
Serial.println("UDP Packet not send");
}

Allerdings wartest Du nicht, bis das Paket verschickt wurde und brichst dann also direkt die Verbindung ab.
Außerdem ist ein Syntaxfehler enthalten:

if(sendingStat = 1){..}

Fällt was auf?

So wäre richtig:

if(sendingStat == 1){..}

Zu allem Überfluss, verwendest Du dann auch noch:

sendingStat == udp.endPacket();

Außerhalb einer Bedingungsprüfung, einfach so im Code.
Dieser Ausdruck erfüllt nicht seinen Zweck, udp.endPacket() wird nicht ausgeführt - tippe ich mal.
richtig wäre:


sendingStat = udp.endPacket();


Das Problem an der Sache ist, dass Du mit so einem Programmierstil nicht weit kommst. Copy und Paste mag funktionieren, aber nicht immer. Man kann nicht jeden Ausdruck in einem Code irgendwo raus nehmen und an anderer Stelle wieder einsetzen. Man muss die Sprachsyntax beachten. Deshalb ist ganz wichtig, wenn etwas nicht funktioniert, zunächst nach solchen Fehlern zu schauen. Erst wenn ich sicher wäre, dass der Code syntaktisch richtig und frei von Schreibfehlern ist, würde ich den anderen Leuten zur Prüfung überlassen. Mir fällt das dann auch nur auf, wenn ich mich intensiv damit beschäftige, nicht unbedingt, wenn ich drüber lese. Sonst wäre mir das schon früher aufgefallen.

Ich habe mal geschaut, da kann man Sachen gut in deutscher Sprache finden:

Tutorial Arduino Operatoren (https://www.arduino-tutorial.de/operatoren/)


Als Experiment, der allererste Code, so weit von den vorher angesprochenen Fehlern bereinigt. Da ich DHT.h nicht habe, konnte ich das jetzt nicht kompilieren:



#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
const int SendePause = 2500; //Pause nach Senden - kann verkürzt werden, bis es nicht mehr funktioniert


//Init DHT-Sensor
DHT dht(DHTPIN, DHTTYPE);
//set IPs
IPAddress IPudp (192, 168, 10, 255); //Broadcastadresse (die Art des Broadcast bestimmt die Verteilung des gesendeten Pakets)
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; //an diesem UDP-Port muss der Empfänger immer lauschen


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, IPsubnetmask, IPgateway);
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();
delay(SendePause);


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(60*1000000);
}
}






MfG