Forum: Mikrocontroller und Digitale Elektronik Kommunikation zwischen 2 bzw. mehreren ESP8266


von Michael87 (Gast)


Lesenswert?

Hallo zusammen,

ich versuche folgendes Projekt.
Auf einem ESP8266 soll ein AccessPoint erstellt werden. Dieser soll beim 
aufrufen der "192.168.1.1" eine Webseite mit einem RGB Slider anzeigen.
Diese soll dann auf einen WS2812 LED Streifen übertragen werden.
Dieser Teil funktioniert schon problemlos.
In einem weiteren Schritt wollte ich nun einen zweiten ESP8266 mit dem 
ersten ESP (also dem AP) verbinden.
Dies habe ich mit einer fixen IP gemacht. 192.168.1.101
Später sollen es mal 3 oder 4 Sein (192.168.1.102 / 192.168.1.103

Diese sollen genau die gleiche Farbe anzeigen wie der erste Strip.
Dazu sende ich nun die RGB Farben des ersten ESP (AP) per HTTP.GET an 
den zweiten ESP bzw. später auch an die anderen.

Nun kommt folgendes Problem.
Wenn ich im Serial Monitor die beiden ESP beobachte und mir die 
übertragenen RGB Werte anzeigen lasse, dann klappt das Problemlos. 
Sobald ich aber den Befehl strip.show() beim zweiten ESP ausführe hängt 
sich dieser auf und auch der AP (erste ESP) nimmt die Befehle nur noch 
ca. alle 2 Sekunden an.
Mir wurde in einem anderen Forum gesagt es kann daran liegen, dass die 
WS2812 beim ESP auf der RX Leitung liegen. Somit habe ich die Ausgabe 
der Seriellen Daten aus meinem Code entfernt und nun läuft auch durch 
nur leider leuchtet beim zweiten ESP keien LED.

Habt ihr eine Idee woran es liegen könnte?

Ich hänge mal alles an.

AccessPoint AP, erster ESP
1
#include "index.h"
2
#include <ESP8266WiFi.h>
3
#include <DNSServer.h>
4
#include <ESP8266WebServer.h>
5
#include <NeoPixelBus.h>
6
#include <ESP8266HTTPClient.h>
7
8
const String Client1 = "http://192.168.1.101";
9
const String Client2 = "http://192.168.1.102";
10
const String Client3 = "http://192.168.1.103";
11
12
int redINT;
13
int greenINT;
14
int blueINT;
15
byte CL2CL3_R;
16
byte CL2CL3_G;
17
byte CL2CL3_B;
18
19
20
#define PixelCount 4 // Number of leds on stick
21
#define PixelPin 0 // "NodeMCU pin 2 (RX) connected to Digital In of Pixel Stick"
22
//PIN 2 ist GPIO3 auf dem ESP-01
23
NeoPixelBus<NeoGrbFeature, NeoEsp8266Dma800KbpsMethod> strip(PixelCount, PixelPin);
24
25
const char * const ssid = "RGB";
26
// const char *password = "87654321";
27
28
const byte DNS_PORT = 53;
29
IPAddress apIP(192, 168, 1, 1);
30
DNSServer dnsServer;
31
ESP8266WebServer webServer(80);
32
33
//////////////////////////////////////////////////////////////////////////////////////////////////
34
35
void handleRoot() {
36
  
37
  String s = MAIN_page;
38
webServer.send(200, "text/html", s); //Send web page
39
Serial.println("handle root..");
40
String WebServerArgDecission = webServer.arg(0);
41
Serial.print("WebserverDecission: ");
42
Serial.println(WebServerArgDecission);
43
if (WebServerArgDecission == "C") {
44
  String red = webServer.arg(1); // read RGB arguments
45
  String green = webServer.arg(2);
46
  String blue = webServer.arg(3);
47
  
48
  redINT = 256-(red.toInt()/4);
49
  greenINT = 256-(green.toInt()/4);
50
  blueINT = 256-(blue.toInt()/4);
51
  int calcRGB = redINT + greenINT + blueINT;
52
  
53
  if (calcRGB == 0) {
54
    Serial.println("no no");
55
    }
56
  else {
57
      Serial.print("R:"); // for TESTING
58
      Serial.print(redINT); // for TESTING
59
      Serial.print(", G:"); // for TESTING
60
      Serial.print(greenINT); // for TESTING
61
      Serial.print(", B:"); // for TESTING
62
      Serial.println(blueINT); // for TESTING 
63
      getStatus();
64
    strip.SetPixelColor(0, RgbColor(redINT, greenINT, blueINT));
65
    strip.Show();
66
    }
67
  }
68
else {}
69
webServer.send(200, "text/html", s);
70
}
71
72
//////////////////////////////////////////////////////////////////////////////////////////////////
73
//////////////////////////////////////////////////////////////////////////////////////////////////
74
75
void setup() {
76
  Serial.begin(9600);
77
78
delay(100);
79
80
81
WiFi.mode(WIFI_AP);
82
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
83
WiFi.softAP(ssid);
84
85
// if DNSServer is started with "*" for domain name, it will reply with provided IP to all DNS request
86
dnsServer.start(DNS_PORT, "rgb", apIP);
87
88
webServer.on("/", handleRoot);
89
90
webServer.begin();
91
92
strip.Begin();
93
strip.Show();
94
95
}
96
97
//////////////////////////////////////////////////////////////////////////////////////////////////
98
99
void loop() {
100
101
dnsServer.processNextRequest();
102
webServer.handleClient();
103
104
}
105
106
void getStatus() {
107
  HTTPClient http;
108
  http.begin(Client1 + "/cx" + redINT + "x" + greenINT + "x" + blueINT + "x\r\n");
109
  http.GET();
110
  http.end();
111
}

zweiter, dritter und vierter ESP STA-Mode
1
#include <ESP8266WiFi.h>
2
#include <ESP8266HTTPClient.h>
3
#include <EEPROM.h>
4
#include <NeoPixelBus.h>
5
6
int redINT;
7
int greenINT;
8
int blueINT;
9
10
#define PixelCount 4 // Number of leds on stick
11
#define PixelPin 5
12
NeoPixelBus<NeoGrbFeature, NeoEsp8266Dma800KbpsMethod> strip(PixelCount, PixelPin);
13
14
const char* const ssid = "RGB";    //  Your Wi-Fi Name
15
const char* const password = "12345678";   // Wi-Fi Password
16
17
//Static IP address configuration
18
IPAddress staticIP(192, 168, 1, 101); //ESP static ip
19
IPAddress gateway(192, 168, 1, 1);   //IP Address of your WiFi Router (Gateway)
20
IPAddress subnet(255, 255, 255, 0);  //Subnet mask
21
IPAddress dns(8, 8, 8, 8);  //DNS
22
23
WiFiServer server(80);
24
HTTPClient http;
25
26
void setup()
27
{
28
  WiFi.config(staticIP, subnet, gateway);
29
  WiFi.mode(WIFI_STA);
30
  WiFi.begin(ssid);
31
  while (WiFi.status() != WL_CONNECTED)
32
  {
33
    delay(500);
34
  }
35
}
36
void loop()
37
{
38
  WiFiClient client = server.available();
39
  if (!client)
40
  {
41
    return;
42
  }
43
//  Serial.println("Waiting for new client");
44
  while(!client.available())
45
  {
46
    delay(1);
47
  }
48
  String request = client.readStringUntil('\r');
49
  String CharRequest = request + "xTEST";
50
  int value = LOW;
51
  if(request.indexOf("/c") != -1)
52
  {
53
    String red = (split(CharRequest, 'x',1));
54
    String green = (split(CharRequest, 'x',2));
55
    String blue = (split(CharRequest, 'x',3));
56
    redINT = red.toInt();
57
    greenINT = green.toInt();
58
    blueINT = blue.toInt();
59
  }
60
  client.flush();
61
  strip.SetPixelColor(0, RgbColor(redINT, greenINT, blueINT));
62
  strip.Show();
63
  client.println("HTTP/1.1 200 OK"); //
64
  client.println("Content-Type: text/html");
65
  client.println("");
66
  client.println("<!DOCTYPE HTML>");
67
  client.println("<html>");
68
  client.print(" CONTROL LED: ");
69
}
70
71
String split(String s, char parser, int index) {
72
  String rs="";
73
  int parserIndex = index;
74
  int parserCnt=0;
75
  int rFromIndex=0, rToIndex=-1;
76
  while (index >= parserCnt) {
77
    rFromIndex = rToIndex+1;
78
    rToIndex = s.indexOf(parser,rFromIndex);
79
    if (index == parserCnt) {
80
      if (rToIndex == 0 || rToIndex == -1) return "";
81
      return s.substring(rFromIndex,rToIndex);
82
    } else parserCnt++;
83
  }
84
  return rs;
85
}

index.h des AP:
1
const char MAIN_page[] PROGMEM = R"=====(
2
<html lang="en">
3
<!DOCTYPE html><html><head><title>RGBLIGHT</title><meta name='mobile-web-app-capable' content='yes' />
4
<meta name='viewport' content='width=device-width' /></head><body style='margin: 0px; padding: 0px;'>
5
<canvas id='colorspace'></canvas></body>
6
<script type='text/javascript'>
7
(function () {
8
 var canvas = document.getElementById('colorspace');
9
 var ctx = canvas.getContext('2d');
10
 function drawCanvas() {
11
 var colours = ctx.createLinearGradient(0, 0, window.innerWidth, 0);
12
 for(var i=0; i <= 360; i+=10) {
13
 colours.addColorStop(i/360, 'hsl(' + i + ', 100%, 50%)');
14
 }
15
 ctx.fillStyle = colours;
16
 ctx.fillRect(0, 0, window.innerWidth, window.innerHeight);
17
 var luminance = ctx.createLinearGradient(0, 0, 0, ctx.canvas.height);
18
 luminance.addColorStop(0, '#ffffff');
19
 luminance.addColorStop(0.05, '#ffffff');
20
 luminance.addColorStop(0.5, 'rgba(0,0,0,0)');
21
 luminance.addColorStop(0.95, '#000000');
22
 luminance.addColorStop(1, '#000000');
23
 ctx.fillStyle = luminance;
24
 ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
25
 }
26
 var eventLocked = false;
27
 function handleEvent(clientX, clientY) {
28
 if(eventLocked) {
29
 return;
30
 }
31
 function colourCorrect(v) {
32
 return Math.round(1023-(v*v)/64);
33
 }
34
 var data = ctx.getImageData(clientX, clientY, 1, window.innerHeight).data;
35
 var red = colourCorrect(data[0]);
36
 var params = [
37
 'X=C&r=' + colourCorrect(data[0]),
38
 'g=' + colourCorrect(data[1]),
39
 'b=' + colourCorrect(data[2])
40
 ].join('&');
41
 var req = new XMLHttpRequest();
42
 req.open('POST', '?' + params, true);
43
 req.send();
44
 eventLocked = true;
45
 req.onreadystatechange = function() {
46
 if(req.readyState == 4) {
47
 eventLocked = false;
48
 }
49
 }
50
 }
51
 canvas.addEventListener('click', function(event) {
52
 handleEvent(event.clientX, event.clientY, true);
53
 }, false);
54
 canvas.addEventListener('touchmove', function(event){
55
 handleEvent(event.touches[0].clientX, event.touches[0].clientY);
56
}, false);
57
 function resizeCanvas() {
58
 canvas.width = window.innerWidth
59
 canvas.height = window.innerHeight/2
60
 drawCanvas();
61
 }
62
 window.addEventListener('resize', resizeCanvas, false);
63
 resizeCanvas();
64
 drawCanvas();
65
 document.ontouchmove = function(e) {e.preventDefault()};
66
 })();
67
 function SET_AP1_Client1() {
68
 var request = new XMLHttpRequest();
69
 request.open('POST', '?' + 'X' + '=' + 'F', true);
70
 request.send();
71
 }
72
 function SET_Client2_Client3() {
73
 var request = new XMLHttpRequest();
74
 request.open('POST', '?' + 'X' + '=' + 'R', true);
75
 request.send();
76
 }
77
 function SetAll() {
78
 var request = new XMLHttpRequest();
79
 request.open('POST', '?' + 'X' + '=' + 'B', true);
80
 request.send();
81
 }
82
</script>
83
<div align='center'>
84
<button onclick='SetAll()'>Store 4 all</button><br>
85
<button onclick='SET_AP1_Client1()'>Set AP and Client1</button><br>
86
<button onclick='SET_Client2_Client3()'>Set Client2 and Client3</button>
87
</div>
88
</html>
89
)=====";

von Stefan F. (Gast)


Lesenswert?

Michael87 schrieb:
> Auf einem ESP8266 soll ein AccessPoint erstellt werden. Dieser soll beim
> aufrufen der "192.168.1.1" eine Webseite mit einem RGB Slider anzeigen.

Im AP Modus hat der ESP normalerweise die Adresse 192.168.4.1 und alle 
damit verbundenen Clients haben eine Adresse aus dem Bereich 
192.168.4.x. Welchen Grund hast du, dies zu ändern?

Du wirfst die Begriffe "Server" und "Client" durcheinander. Zu einem 
Client kann man keinen HTTP GET Request senden.

Warum hast du da Code für DNS drin, obwohl alles mit festen IP Adressen 
passiert?

> Mir wurde in einem anderen Forum gesagt es kann daran liegen,
> dass die WS2812 beim ESP auf der RX Leitung liegen.

Die sie verkabelt sind, solltest du selbst doch 100% wissen und und auch 
mitteilen. Wie sollen wir Dir sonst helfen? Zeige deinen Schaltplan.

> Sobald ich aber den Befehl strip.show() beim zweiten ESP
> ausführe hängt sich dieser auf...und nun läuft auch durch
> nur leider leuchtet beim zweiten ESP keien LED.

Ich würde Dir vorschlagen, zuerst die Ansteuerung der LED Streifen ganz 
ohne Netzwerkkommunikation ans Laufen zu bringen. Zum Beispiel bunt 
blinken lassen.
1
void handleRoot() 
2
{ 
3
   webServer.send(200, "text/html", s); //Send web page
4
5
   if (WebServerArgDecission == "C") 
6
   {
7
       ...
8
   }
9
   else 
10
   {
11
   }
12
   webServer.send(200, "text/html", s);
13
}

Da ist etwas doppelt gemoppelt.

> const char MAIN_page[] PROGMEM = R"=====(
> <html lang="en">

Da stimmt wahrscheinlich etwas mit den Anführungsstrichen nicht.

Hänge das ganze Programm in compilierbarer Form an und bringe die 
grausame Formatierung in Ordnung! Dass Dir da nicht einmal die gröbsten 
Fehler auffallen, ist kein Wunder.

von Sascha W. (sascha-w)


Lesenswert?

Hallo Michael,

um die Daten per HTTP an die "clients" oder sagen wir eher Slaves zu 
übertragen, müssen diese als Webserver laufen. Der Master sendet seinen 
Request mit den neuen Daten dann an jeden Slave. Das bringt jede Menge 
Overhead, und wenn ein Slave nicht erreichbar ist hängt die 
Kommunikation zumindest bis ein Timeout zuschlägt.
Ich würde vorschlagen die Verteilung der Daten an die Slaves per UDP zu 
machen, da kannst du die Daten an die Slaves senden und wenn die mal 
offline sind passiert auch nichts da nicht auf irgendwelche 
Bestätigungen gewartet werden muss. Per UDP kannst du sogar per 
Broadcast senden, dann brauchst du die Daten nur 1x senden und alle 
verbundenen Slaves empfangen das Paket. Um einen nachträglich 
verbundenen Slave auf den aktuellen Stand zu bringen kann der einfach 
ein UDP-Paket an den Master senden, bzw sollte es am Master auch die 
Möglichkeit geben einen neu verbundenen Slave über den Netzwerkstack zu 
erkennen.

Sascha

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.