I have a project where I want to create a Master and 2 Slave devices whereby the Slaves collect data and send to the Master over WiFI for display on a Web Page, the User can then interact with the web page to send commands back to each of the Master and Slaves for control of some connected equipment. I have had the web page and the user control of the equipment working in its barest form (some LED’s connected to each of the Master and one Slave). I am using ESP8266mod boards and UDP as a communication protocol and the system has to work standalone and in remote locations, for example a boating lake or model flying field. To that end my Master board also acts as an Access Point and a Web Server.
The problem I am facing is with what appears to be some inconsistency and illogical behaviour of the hardware (the ESP8266’s) with respect to the UDP comms. I have reduced my code down to a bear minimum to test and prove the comms but still things don’t seem logical when so much of the code is common between both the Master and Slave modules. I have posted both the Master and Slave module code below.
I originally bought 3 ESP8266 modules and saw some inconsistencies so then bought a further 2 from another supplier in an attempt to rule out a hardware problem. The two additional boards are slightly different in respect of PCB printing and soldering so are at the very least from a different batch if not from a different manufacturer. Also the vendor logo on the WiFi module is different between the three off and the two off.
My code has been simplified down to the following…
The Slave sends a message (1111) to the Master approx. every 10 seconds, when the Master receives the message it then sends a reply back to the slave to acknowledge receipt. Each of these steps are displayed in the respective Serial Monitor windows.
The problem I have is that Boards 1, 2, 4 & 5 all work successfully as Masters (which proves that they can all send and receive UDP messages OK) but Board 3 is the only board that will work as the Slave. If I set up any of boards 1, 2, 4 or 5 as the Slave then they will connect to the WiFi and appear to send the 1111 message but nothing is received at the Master. I cannot test if board 3 will work as a Master as I have no other working Slave to try it with.
What is really confusing me is that it doesn’t appear to be possible that it is either a software or hardware issue.
- With respect to software, I have copied the same Slave code into all boards and it is only Board 3 that works, so I don’t see that it can be a software issue.
- With respect to hardware, the fact that boards 1, 2, 4 & 5 can all send and receive successfully as Masters would suggest that it is also not the fault of the hardware.
Hopefully someone can help shed a little light on this for me please? (I apologise in advance if I've made some rookie errors but I just seem to be going around in circles, many thanks.)
My "Min_AP_Master.ino" file follows...
//This is the minimum required code to prove the functionality of a 3-way UDP communication system
//between a MASTER and two SLAVE ESP8266MOD boards (Wemos D1 Mini's).
//
//This is the code for the ACCESS POINT and MASTER board.
//
//The long term goal here is that the Slaves will collect sensor data and send it to the Master board,
//the Master board will confirm receipt otherwise the data is sent again (the send again part is not
//yet implimented).
//
//The code has been stripped to a minimum and the Slaves will send an Integer value of 1111 (from Slave 1)
//and 2222 (from Slave 2) as UDP messages to the MASTER approximately every 10 seconds.
//
//
//
// Import required libraries
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char* ssid = "ESP8266-Access-Point";
const char* password = "123456789";
// Set this boards Static IP address and gateway
IPAddress local_IP(192, 168, 4, 3);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);
//IPAddress primaryDNS(8, 8, 8, 8); // optional
//IPAddress secondaryDNS(8, 8, 4, 4); // optional
const char* APIP = "192.168.4.1";
// Slave board 1 IP address and port
const char* slave1IP = "192.168.4.11";
const unsigned int slave1Port = 8081;
// Slave board 2 IP address and port
const char* slave2IP = "192.168.4.12";
const unsigned int slave2Port = 8082;
WiFiUDP udp;
unsigned int localPort = 4212; // The port to listen on
char incomingPacket[255]; // Buffer to hold incoming packets
unsigned long CurrentTime = millis();
unsigned long PreviousTime = millis();
String replyForSlave1 = "Slave 1 message received by AP";
String replyForSlave2 = "Slave 2 message received by AP";
String receivedMessage = "";
void setup() {
Serial.begin(115200);
delay(5000); //This delay is just to give time to set the baud rate.
// Configures static IP address
if (!WiFi.config(local_IP, gateway, subnet)) {
Serial.println("STA Failed to configure");
}
Serial.println("Local IP and baud rate set.");
Serial.print("Local IP address: ");
Serial.println(WiFi.localIP());
Serial.print("Local Gateway : ");
Serial.println(WiFi.gatewayIP());
Serial.print("Local Subnet : ");
Serial.println(WiFi.subnetMask());
Serial.println();
Serial.println("Setting AP (Access Point)…");
// Remove the password parameter, if you want the AP (Access Point) to be open
WiFi.softAP(ssid, password);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);
// Print ESP8266 Local IP Address
Serial.print("ESP8266 Local IP address: ");
Serial.println(WiFi.localIP());
// Start UDP
udp.begin(localPort);
Serial.printf("Listening on UDP port %d\n", localPort);
Serial.println();
Serial.println();
}
void loop() {
//Put the retrieval of the UDP messages from boards 2 & 3 here...
// Listen for incoming UDP packets
// if (udp.available()) {
int packetSize = udp.parsePacket();
if (packetSize) {
int len = udp.read(incomingPacket, 255);
if (len > 0) {
incomingPacket[len] = 0;
}
Serial.printf("UDP packet received: %s\n", incomingPacket);
String rIP = udp.remoteIP().toString();
Serial.print(" From IP..... ");
Serial.println(rIP);
int rP = udp.remotePort();
Serial.print(" From Port... ");
Serial.println(rP);
Serial.println();
// receivedMessage = int(incomingPacket);
receivedMessage = incomingPacket;
}
// }
if (receivedMessage == "1111") {
// Reply to Slave 1
udp.beginPacket(slave1IP, slave1Port);
// udp.beginPacket(APIP, slave1Port);
udp.print(replyForSlave1);
udp.endPacket();
Serial.print("Just sent a reply to Slave 1 at IP ");
Serial.print(APIP);
Serial.print(" and Port ");
Serial.println(slave1Port);
Serial.println();
receivedMessage = "";
}
if (receivedMessage == "2222") {
// Reply to Slave 2
udp.beginPacket(slave2IP, slave2Port);
udp.print(replyForSlave2);
udp.endPacket();
Serial.print("Just sent a reply to Slave 2 at IP ");
Serial.print(slave2IP);
Serial.print(" and Port ");
Serial.println(slave2Port);
Serial.println();
receivedMessage = "";
}
}
And my "Min_Slave_1.ino" file follows here...
//This is the minimum required code to prove the functionality of a 3-way UDP communication system
//between a MASTER and two SLAVE ESP8266MOD boards (Wemos D1 Mini's).
//
//This is the code for SLAVE number 1.
//
//The long term goal here is that the Slaves will collect sensor data and send it to the Master board,
//the Master board will confirm receipt otherwise the data is sent again (the send again part is not
//yet implimented).
//
//This code has been stripped to a minimum and will send an Integer value of 1111 as a UDP message to
//the MASTER approximately every 10 seconds (10,037 milliseconds).
//
//
//
// Import required libraries
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
// Your network credentials
const char* ssid = "ESP8266-Access-Point";
const char* password = "123456789";
// Set this boards Static IP address and gateway
IPAddress local_IP(192, 168, 4, 11);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);
//IPAddress primaryDNS(8, 8, 8, 8); // optional
//IPAddress secondaryDNS(8, 8, 4, 4); // optional
// Master board IP address and port
const char* masterIP = "192.168.4.1"; //seems to only work with AP IP address not Masters local IP address
const unsigned int masterPort = 4212;
// UDP settings
WiFiUDP udp;
unsigned int localPort = 8081; // The port to listen on
char incomingPacket[255]; // Buffer to hold incoming packets
unsigned long currentTime = millis();
unsigned long udpSentTime = millis();
unsigned long elapsedTime = 0;
int udpSendPeriod = 10037;
int intToSend = 1111;
void setup() {
Serial.begin(115200);
delay(5000); //This delay is just to give time to set the baud rate.
// Configures static IP address
if (!WiFi.config(local_IP, gateway, subnet)) {
Serial.println("STA Failed to configure");
}
Serial.println("Local IP and baud rate set.");
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println();
Serial.println("Now connected to WiFi");
Serial.print("Local IP Address: ");
Serial.println(WiFi.localIP());
Serial.print("Gateway : ");
Serial.println(WiFi.gatewayIP());
Serial.print("Subnet : ");
Serial.println(WiFi.subnetMask());
// Start UDP
udp.begin(localPort);
Serial.printf("Listening on UDP port %d\n", localPort);
Serial.println();
Serial.println();
}
void loop() {
// Listen for incoming UDP packets
// if (udp.available()) {
int packetSize = udp.parsePacket();
if (packetSize) {
int len = udp.read(incomingPacket, 255);
if (len > 0) {
incomingPacket[len] = 0;
}
Serial.printf("UDP packet received: %s\n", incomingPacket);
String rIP = udp.remoteIP().toString();
Serial.print(" From IP..... ");
Serial.println(rIP);
int rP = udp.remotePort();
Serial.print(" From Port... ");
Serial.println(rP);
Serial.println();
}
currentTime = millis();
elapsedTime = currentTime - udpSentTime;
if (elapsedTime >= udpSendPeriod) {
udpSend();
}
}
void udpSend() {
//
Serial.print("Sending message: ");
Serial.println(intToSend);
udp.beginPacket(masterIP, masterPort);
udp.print(intToSend);
udp.endPacket();
udpSentTime = millis();
Serial.print("Just sent a message to IP ");
Serial.print(masterIP);
Serial.print(" and Port ");
Serial.println(masterPort);
Serial.println();
}


