Ich möchte nicht über eine vom ESP erzeugte Webseite steuern, sondern ein anderer ESP soll per Wifi einen Schaltbefehl senden. Geht das? Wenn ja, wie? Hat evtl. jemand ein Beispiel-Sketch?
Zum Beispiel:
die Frage kommt gefühlt alle 3 Wochen.
3 Varianten:
UDP, wenn Nachrichten schnell kommen sollen, aber auch mal ausfallen können
TCP, wenn man durchs Protokoll absichern will, dass Nachrichten ankommen
HTTP - als untermenge von TCP - wenn man schon einen webserver hat und den dann halt auch für die Übertragung von Daten mitnutzen möchte.
Variante HTTP, hab ich hier:
https://werner.rothschopf.net/201809_arduino_esp8266_server_client_0.htm
im speziellen das senden mittels POST und der relativ einfache Datenempfang über die Parameterinfrastruktur des Webservers.
Auch bei UDP kann man in einem eigenen Protokoll eine Quittung senden, abhängig vom empfangenen Signal. Oder man versendet die Daten mehrfach hintereinander.
Wenn nur die beiden ESPs miteinander kommunizieren sollen und der Abstand zwischen den beiden ESPs nicht allzugroß ist kann man auch ESP-NOW nehmen.
Der ESP8266 kann aber entweder nur ESP-NOW oder WiFi/WLAN
Der ESP32 kann ESP-NOW und WiFi nur dann wenn beide auf dem gleichen Kanal betrieben werden.
ESP-NOW ist für kleine Datenmengen bis 250 byte. Die Übertragung geht dabei sehr schnell.
Man kann da ca 100 mal pro Sekunde senden.
vgs
Oh, hab ich mir einfacher vorgestellt. ![]()
![]()
Danke für eure Tips!
Muss ich mal in Ruhe durchschauen und testen.
Ich habe mittlerweile auch eine interessante Seite dazu gefunden:
UDP ist einfach. ![]()
Das stimmt nicht. Ich betreibe ESP8266 mit WLAN und ESP-now erfolgreich.
mit WLAN und ESP-NOW wirklich gleichzeitig? oder schaltest du da hin- und her?
Wow ! Hast du da einen Link wo beschrieben wird wie man das macht?
vgs
jetzt kommt es ja darauf an was du denn insgesamt machen willst.
Vielleicht ist es in der Tat einfacher einen 4-Kanal Funkschalter zu nehmen.
Das kann man aber nur dann beurteilen wenn du denn beschrieben hättest was du da insgesamt vor hast.
vgs
Ich lese mit einem ESP Zählerdaten(Strom) aus. Bei Solarüberschuss soll ein weiterer ESP angesteuert werden welcher über Relaismodule Verbraucher zuschaltet.
Der ESPZähler ist mit dem Router verbunden. Von ihm kann ich per Tablet Zustandsdaten abfragen.
Also müsste der ESPZähler als Server/Client und der ESPRelais als Server arbeiten?!
UDP soll nicht so zuverlässig sein? Kann ich per UDP eine Rückmeldung bekommen um ggf einen Schaltbefehl nochmal zu senden?![]()
Hatte ich in Post #4 schon geschrieben. Zuverlässig hängt ganz von deinen Programmierfähigkeiten ab. Ich sehe das in einem privaten Umfeld als völlig ausreichend. Beimir kommunizieren 10 ESP8266 per UDP untereinander und das problemlos.
Ja gleichzeitig. Ich habe es einfach gemacht, funktioniert. Es stand nirgends das es verboten ist.
Wenn ein ESP8266 ohne WLAN mit einem ESP8266, der mit dem WLAN verbunden ist, über ESP-now kommunizieren will, muss man den Channel natürlich an dem ESP8266 ohne WLAN anpassen, damit die Frequenz gleich ist. Sonnst gehen Daten verloren wenn die Frequenzen wenig abweichen bis hin zu das keine Daten ankommen wenn die Frequenzen stark abweichen. Aber auch dafür gibt es Methoden.
Standardmäßig ist ESP-now auf Channel 1 unterwegs.
Der Vorteil von ESP-now ist nicht das „schnelle“ Senden, sondern eher das man sich die Zeit für das „einwählen“ ins WLAN spart. Vor allem bei Akku betriebenen Geräten im Deep-Sleep macht sich das stark bemerkbar, wenn sie nicht 2-3 Sekunden wach sind sondern nur 0,25 Sekunden.
Naja... - ich versuche es trotzdem! ![]()
Ein Versuch per UDP kann nicht schaden und man lernt ja dazu.
Tommy56 hat mal was dazu gepostet:
Das sieht ganz brauchbar aus...
Und gute Infos dazu findest du auch bei fips.
Oh schei..., jetzt funktioniert das auch noch! ![]()
Ich habe Tommy56s Code mal eingebaut. Master ESPnodeMCU, Slave ESPnodeMCU mit OLED.
Wie kann ich das ganze erweitern auf mehrere Schaltkanäle?
Master:
// NodeMCU ohne alles
// Master in einem bestehenden WLAN
// Steuert an einen anderen NodeMCU eine LED
#include <ESP8266WiFi.h>
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
#include <SSD1306Wire.h> // für OLED`
#include <WiFiUdp.h>
char *ssid = "xxxxxxxx";
char *password = "xxxxxxxxx";
// hier die Adresse vom Slave eintragen
IPAddress remoteIP(192,168,100,127);
unsigned int remotePort = 4210; // remote port to listen on
char befehl[10];
WiFiUDP Udp;
uint32_t aktMillis;
uint32_t prevMillis;
boolean ledStatus = false;
// Initialize the OLED display using Wire library
SSD1306Wire display(0x3c, D1, D2); //D2=SDK D1=SCK As per labeling on NodeMCU
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println("Start");
Serial.print("Connecting to "); Serial.println(ssid);
display.init();
display.flipScreenVertically();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
//display.setFont(ArialMT_Plain_10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.print("\n connected.");
Serial.println(WiFi.localIP());
}
void loop() {
aktMillis = millis();
if (aktMillis - prevMillis >= 5000) {
prevMillis = aktMillis;
Serial.print("LED schalten auf ");
if (ledStatus) {
Serial.println("An");
befehl[0] = 1;
}
else {
Serial.println("Aus");
befehl[0] = 0;
}
Udp.beginPacket(remoteIP, remotePort);
Udp.write(befehl, 1);
Udp.endPacket();
ledStatus = !ledStatus;
}
}
Slave:
// NodeMCU mit LED an D7
// Als UDP-Slave, der vom NodeMCU 1 seine Befehle bekommt
// für UDP-Server
#include <ESP8266WiFi.h>
//#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
#include <SSD1306Wire.h> // für OLED`
#include <WiFiUdp.h>
#define LED D7
WiFiUDP Udp;
unsigned int localUdpPort = 4210; // local port to listen on
char befehl[10]; // buffer for incoming packets
boolean ledStatus = false;
char myIpString[24]; //um IP Adresse in String umzuwandeln und anzuzeigen
char *ssid = "xxxxxxx";
char *password = "xxxxxxxx";
// Initialize the OLED display using Wire library
SSD1306Wire display(0x3c, D1, D2); //D2=SDK D1=SCK As per labeling on NodeMCU
void setup() {
Serial.begin(9600);
//Serial.setDebugOutput(true);
display.init();
display.flipScreenVertically();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
//display.setFont(ArialMT_Plain_10);
display.clear();
display.drawString(0, 0, "Start");
display.display();
delay(3000);
digitalWrite(LED, LOW);
pinMode(LED, OUTPUT);
WiFiStart(); //Unterprogramm verbindet ESP mit Router
Udp.begin(localUdpPort);
//Serial.print("\n connected UDP-Server bereit an IP: ");
//Serial.print(WiFi.localIP());
//Serial.println("UDP-Server bereit.");
}
void loop() {
int packetSize, len;
// UDP
packetSize = Udp.parsePacket();
// Da ist was da
if (packetSize) {
//Serial.print("Empfangen "); Serial.print(packetSize);
//Serial.print(" von IP "); Serial.print(Udp.remoteIP());
//Serial.print(" Port "); Serial.println(Udp.remotePort());
len = Udp.read(befehl, 10);
ledStatus = befehl[0]; // erstes Byte 0 oder 1
if (ledStatus) {
display.clear();
display.drawString(0, 0, "Relais1= 1");
display.display();
}
else {
display.clear();
display.drawString(0, 0, "Relais1= 0");
display.display();
}
}
}
void WiFiStart() // Unterprogramm um WiFi am Router anzumelden
{
// Connect to WiFi network
display.clear();
display.setFont(ArialMT_Plain_10);
display.drawString(0, 0, "Call to " + String(ssid));
display.display();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
// Print the IP address
IPAddress myIp = WiFi.localIP();
sprintf(myIpString, "%d.%d.%d.%d", myIp[0], myIp[1], myIp[2], myIp[3]); //IP muss in String umgewandelt werden
display.clear();
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, myIpString);
display.display();
delay(3000); // Unterprogramm aufrufen um Sprengerzeiten neu einzustellen
}
Indem Du die Bytes im Array befehl entsprechend belegst/nutzt/auswertest.
Gruß Tommy
Danke für den Code Tommy!![]()
Lassen sich auch 2 Slaves damit steuern?
Ja.
wenn du die broadcast-IP-adresse xxx.xxx.xxx.255 = letzte Gruppe hat den Wert 255 verwendest musst du dann in die Nachricht noch eine ID-Nummer einbauen mit der die Slaves entscheiden können ob der Schaltbefehl für sie selbst sind
oder wenn du nur an die spezifische IP-adressse des slaves sendest dann ist die IP-adresse sozusagen die "Adressierung (wie der Name schon sagt.
Udp.write(befehl, 1);
``` sendet **1** byte. Man kann auch mehrere bytes senden. Dem Sendebefehl ist schnurzwurscht was die Bytes bedeuten.
Im Empfänger liest du die bytes ein und dann muss dein Programm sie weiterverarbeiten wie auch immer.
Du solltest dich ein ganzes Stück tiefer in diese Funktionsweise einarbeiten. Ich meine damit mit dem byte-Senden expermimentieren um die Funktionsweise dadurch zu verstehen. Wenn man etwas anderes als ein einzelnes byte übertragen will dann muss man meistens type-casting zu uint_8 machen.
vgs