I had this working in Station mode perfectly, but I when I turn everything off and on again, sometimes the wifi/ESP-NOW channel used by the master and slaves wasn't the same, and communication wouldn't work. To solve that problem, I switched to the soft wifi access point, but when I did that I started getting interface errors in the form of "ESP_ERR_ESPNOW_IF," even though I can confirm the wifi and ESP-NOW channels are exactly the same for the master and all the slaves. Is there some trick to setting up wifi, a web-server, and ESP-NOW on the ESP32 acting as the master in SoftAP mode that keeps everything working? Here's the master code I'm using (please excuse all the debugging statements):
Code: Select all
#include <WiFi.h>
#include <esp_now.h>
#include <WebServer.h>
#include <esp_wifi.h> // Include the ESP-IDF Wi-Fi header
// SoftAP credentials
const char* ssid = "MYSSID";
const char* password = "Password1234";
const int wifi_channel = 6; // Fixed Wi-Fi channel
// Create a web server object
WebServer server(80);
// ESP-NOW peer information
uint8_t slaveAddress1[] = {0x78, 0x21, 0x84, 0x8c, 0xCC, 0xE4};
uint8_t slaveAddress2[] = {0x78, 0x21, 0x84, 0x88, 0x58, 0xC8};
uint8_t slaveAddress3[] = {0x78, 0x21, 0x84, 0x8e, 0x52, 0xD0};
typedef struct struct_message {
char a[32];
} struct_message;
struct_message myData;
// Function to handle incoming data
void onDataReceive(const esp_now_recv_info* info, const uint8_t *data, int len) {
memcpy(&myData, data, sizeof(myData));
Serial.print("Message received: ");
Serial.println(myData.a);
}
// Function to handle the root path and serve the web form
void handleRoot() {
String html = "<html><body>"
"<h1>ESP32 Web Form</h1>"
"<form action=\"/submit\" method=\"post\">"
"<button name=\"button\" value=\"A\" type=\"submit\">Button A</button>"
"<button name=\"button\" value=\"B\" type=\"submit\">Button B</button>"
"</form></body></html>";
server.send(200, "text/html", html);
}
// Function to handle form submission and send ESP-NOW messages
void handleSubmit() {
if (server.hasArg("button")) {
String button = server.arg("button");
if (button == "A") {
strcpy(myData.a, "Signal X");
Serial.println("Button A pressed, sending Signal X");
} else if (button == "B") {
strcpy(myData.a, "Signal Y");
Serial.println("Button B pressed, sending Signal Y");
}
// Send to all three slaves and print detailed error codes
esp_err_t result;
result = esp_now_send(slaveAddress1, (uint8_t *) &myData, sizeof(myData));
if (result == ESP_OK) {
Serial.println("Message sent successfully to Slave 1");
} else {
Serial.print("Error sending message to Slave 1: ");
printEspNowError(result);
}
result = esp_now_send(slaveAddress2, (uint8_t *) &myData, sizeof(myData));
if (result == ESP_OK) {
Serial.println("Message sent successfully to Slave 2");
} else {
Serial.print("Error sending message to Slave 2: ");
printEspNowError(result);
}
result = esp_now_send(slaveAddress3, (uint8_t *) &myData, sizeof(myData));
if (result == ESP_OK) {
Serial.println("Message sent successfully to Slave 3");
} else {
Serial.print("Error sending message to Slave 3: ");
printEspNowError(result);
}
server.send(200, "text/html", "Message sent!");
} else {
server.send(400, "text/html", "Invalid request");
}
}
// Function to interpret ESP-NOW errors
void printEspNowError(esp_err_t err) {
switch (err) {
case ESP_OK:
Serial.println("ESP_OK: Success");
break;
case ESP_ERR_ESPNOW_NOT_INIT:
Serial.println("ESP_ERR_ESPNOW_NOT_INIT: ESP-NOW is not initialized");
break;
case ESP_ERR_ESPNOW_ARG:
Serial.println("ESP_ERR_ESPNOW_ARG: Invalid argument");
break;
case ESP_ERR_ESPNOW_INTERNAL:
Serial.println("ESP_ERR_ESPNOW_INTERNAL: Internal error");
break;
case ESP_ERR_ESPNOW_NO_MEM:
Serial.println("ESP_ERR_ESPNOW_NO_MEM: Out of memory");
break;
case ESP_ERR_ESPNOW_NOT_FOUND:
Serial.println("ESP_ERR_ESPNOW_NOT_FOUND: Peer not found");
break;
case ESP_ERR_ESPNOW_IF:
Serial.println("ESP_ERR_ESPNOW_IF: Interface error");
break;
default:
Serial.print("Unknown error: ");
Serial.println(err);
break;
}
}
// Initialize ESP-NOW
void initESPNow() {
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_recv_cb(onDataReceive);
Serial.println("ESP-NOW initialized");
// Add peers
esp_now_peer_info_t peerInfo;
memset(&peerInfo, 0, sizeof(peerInfo));
memcpy(peerInfo.peer_addr, slaveAddress1, 6);
peerInfo.channel = wifi_channel;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer 1");
return;
}
Serial.println("Added peer 1");
memcpy(peerInfo.peer_addr, slaveAddress2, 6);
peerInfo.channel = wifi_channel;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer 2");
return;
}
Serial.println("Added peer 2");
memcpy(peerInfo.peer_addr, slaveAddress3, 6);
peerInfo.channel = wifi_channel;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer 3");
return;
}
Serial.println("Added peer 3");
}
void setup() {
Serial.begin(115200);
// Initialize Wi-Fi as SoftAP
WiFi.softAP(ssid, password, wifi_channel);
Serial.print("AP started, IP address: ");
Serial.println(WiFi.softAPIP());
// Ensure the channel is set correctly
esp_wifi_set_promiscuous(true);
esp_wifi_set_channel(wifi_channel, WIFI_SECOND_CHAN_NONE);
esp_wifi_set_promiscuous(false);
// Initialize the web server
server.on("/", handleRoot);
server.on("/submit", HTTP_POST, handleSubmit);
server.begin();
Serial.println("Web server started");
// Initialize ESP-NOW after SoftAP and web server are set up
initESPNow();
Serial.print("ESP-NOW and AP initialized on channel: ");
Serial.println(wifi_channel);
}
void loop() {
// Handle web server
server.handleClient();
}
Code: Select all
#include <WiFi.h>
#include <esp_now.h>
#include <esp_wifi.h>
#include <Adafruit_NeoPixel.h>
// Master device's MAC address
uint8_t masterAddress[] = {0x78, 0x21, 0x84, 0x8D, 0x02, 0x40};
int wifi_channel = 6; // Set to match master's Wi-Fi channel
// Setting pins and colors for NeoPixels
const int INDICATOR_LED = 21;
Adafruit_NeoPixel indicatorLed = Adafruit_NeoPixel(1, INDICATOR_LED, NEO_GRB + NEO_KHZ800);
uint32_t orange = indicatorLed.Color(255,140,0);
uint32_t blue = indicatorLed.Color(0,0,255);
uint32_t off = indicatorLed.Color(0,0,0);
typedef struct struct_message {
char a[32];
} struct_message;
struct_message incomingData;
struct_message ackData;
void allLedsOff() {
indicatorLed.setPixelColor(0, off);
indicatorLed.show();
}
void onDataReceive(const esp_now_recv_info* info, const uint8_t *data, int len) {
memcpy(&incomingData, data, sizeof(incomingData));
Serial.print("Message received: ");
Serial.println(incomingData.a);
// Correct string comparison
if (strcmp(incomingData.a, "Signal X") == 0) {
indicatorLed.setPixelColor(0, orange);
indicatorLed.show();
delay(5000);
allLedsOff();
} else if (strcmp(incomingData.a, "Signal Y") == 0) {
indicatorLed.setPixelColor(0, blue);
indicatorLed.show();
delay(5000);
allLedsOff();
}
// Prepare acknowledgment data
strcpy(ackData.a, "ACK");
// Send acknowledgment back to master
esp_err_t result = esp_now_send(masterAddress, (uint8_t *) &ackData, sizeof(ackData));
if (result == ESP_OK) {
Serial.println("Acknowledgment sent successfully");
} else {
Serial.println("Error sending acknowledgment");
}
}
void setup() {
Serial.begin(115200);
Serial.println("Starting...");
indicatorLed.begin();
indicatorLed.show();
allLedsOff();
// Initialize Wi-Fi
WiFi.mode(WIFI_STA);
esp_wifi_set_promiscuous(true); // Enable promiscuous mode for Wi-Fi
esp_wifi_set_channel(wifi_channel, WIFI_SECOND_CHAN_NONE); // Set channel
esp_wifi_set_promiscuous(false); // Disable promiscuous mode
Serial.print("WiFi initialized on channel: ");
Serial.println(wifi_channel);
// Initialize ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
Serial.println("ESP-NOW initialized");
// Register callback function for when data is received
esp_now_register_recv_cb(onDataReceive);
Serial.println("Receive callback registered");
// Add master as a peer
esp_now_peer_info_t peerInfo;
memset(&peerInfo, 0, sizeof(peerInfo));
memcpy(peerInfo.peer_addr, masterAddress, 6);
peerInfo.channel = wifi_channel;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
Serial.print("Master peer added on channel: ");
Serial.println(peerInfo.channel);
}
void loop() {
// Nothing to do here, all work is done in the callback
}