-
Notifications
You must be signed in to change notification settings - Fork 7.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
esp now and Wifi client both are not working simultaneously #878
Comments
This sounds really strange. Generally ESP-NOW has nothing to do with TCP/UDP and runs underneath that stack. Can you please post a minimal sketch that shows this issue so we can run it internally and try to figure out what might be going wrong |
Can you publish a code that work like James-sjec describe ? i have a esp32(server) that is conected to the wifi , also have a esp_now avaiable and five sensors(esp32 now master) publish data to the server and the server send this data to the web,,, can you publish a code to do this scenario ? thanks |
On ESP8266 you can either use ESPNow or connect the module to an AP. Both together doesn't work. I just tested it (after reading about it). I can send and receive data over ESPNow until I connect the WiFi to an AP. After successful connection to AP, ESPNow send fails and I receive no more data. My guess is that on the ESP32 it is the same. |
@beegee-tokyo I raised this question to the team and they confirmed that this is not the expected behaviour on ESP32 and ESP-NOW should work together with WiFi |
I build up a small test configuration with an ESP8266 sending data over ESPNow and an ESP32 receiving data over ESPNow. Then the ESP32 send the received data over MQTT to an MQTT broker and it works. But there is one condition:The Wifi you connect to must be on the same Wifi channel that is used for ESPNow. #include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Ticker.h>
extern "C" {
#include <espnow.h>
#include <user_interface.h>
}
/**
ESPNOW - Basic communication - Master
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
*/
typedef struct esp_now_peer_info {
u8 peer_addr[6]; /**< ESPNOW peer MAC address that is also the MAC address of station or softap */
uint8_t channel; /**< Wi-Fi channel that peer uses to send/receive ESPNOW data. If the value is 0,
use the current channel which station or softap is on. Otherwise, it must be
set as the channel that station or softap is on. */
} esp_now_peer_info_t;
// Global copy of slave
#define NUMSLAVES 20
esp_now_peer_info_t slaves[NUMSLAVES] = {};
int SlaveCnt = 0;
#define CHANNEL 1
void printMacAddress(uint8_t* macaddr) {
Serial.print("{");
for (int i = 0; i < 6; i++) {
Serial.print("0x");
Serial.print(macaddr[i], HEX);
if (i < 5) Serial.print(',');
}
Serial.println("};");
}
// Init ESP Now with fallback
void InitESPNow() {
if (esp_now_init() == 0) {
Serial.println("ESPNow Init Success");
}
else {
Serial.println("ESPNow Init Failed");
ESP.restart();
}
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
}
// Scan for slaves in AP mode
void ScanForSlave() {
int8_t scanResults = WiFi.scanNetworks();
//reset slaves
memset(slaves, 0, sizeof(slaves));
SlaveCnt = 0;
Serial.println("");
if (scanResults == 0) {
Serial.println("No WiFi devices in AP Mode found");
} else {
Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
for (int i = 0; i < scanResults; ++i) {
// Print SSID and RSSI for each device found
String SSID = WiFi.SSID(i);
int32_t RSSI = WiFi.RSSI(i);
String BSSIDstr = WiFi.BSSIDstr(i);
delay(10);
// Check if the current device starts with `Slave`
if (SSID.indexOf("Slave") == 0) {
// SSID of interest
Serial.print(i + 1); Serial.print(": ");
Serial.print(SSID); Serial.print(" [");
Serial.print(BSSIDstr); Serial.print("]");
Serial.print(" ("); Serial.print(RSSI);
Serial.print(")"); Serial.println("");
// Get BSSID => Mac Address of the Slave
char macPart[4];
macPart[0] = '0';
macPart[1] = 'x';
macPart[2] = (char)BSSIDstr[0];
macPart[3] = (char)BSSIDstr[1];
slaves[SlaveCnt].peer_addr[0] = strtol(macPart,0,16);
macPart[2] = (char)BSSIDstr[3];
macPart[3] = (char)BSSIDstr[4];
slaves[SlaveCnt].peer_addr[1] = strtol(macPart,0,16);
macPart[2] = (char)BSSIDstr[6];
macPart[3] = (char)BSSIDstr[7];
slaves[SlaveCnt].peer_addr[2] = strtol(macPart,0,16);
macPart[2] = (char)BSSIDstr[9];
macPart[3] = (char)BSSIDstr[10];
slaves[SlaveCnt].peer_addr[3] = strtol(macPart,0,16);
macPart[2] = (char)BSSIDstr[12];
macPart[3] = (char)BSSIDstr[13];
slaves[SlaveCnt].peer_addr[4] = strtol(macPart,0,16);
macPart[2] = (char)BSSIDstr[15];
macPart[3] = (char)BSSIDstr[16];
slaves[SlaveCnt].peer_addr[5] = strtol(macPart,0,16);
SlaveCnt++;
}
}
}
if (SlaveCnt > 0) {
Serial.print(SlaveCnt); Serial.println(" Slave(s) found, processing..");
} else {
Serial.println("No Slave Found, trying again.");
}
// clean up ram
WiFi.scanDelete();
}
// Check if the slave is already paired with the master.
// If not, pair the slave with master
void manageSlave() {
if (SlaveCnt > 0) {
for (int i = 0; i < SlaveCnt; i++) {
const esp_now_peer_info_t *peer = &slaves[i];
u8 *peer_addr = slaves[i].peer_addr;
Serial.print("Processing: ");
for (int ii = 0; ii < 6; ++ii ) {
Serial.print((uint8_t) slaves[i].peer_addr[ii], HEX);
if (ii != 5) Serial.print(":");
}
Serial.print(" Status: ");
// check if the peer exists
bool exists = esp_now_is_peer_exist((u8*)peer_addr);
if (exists) {
// Slave already paired.
Serial.println("Already Paired");
} else {
// Slave not paired, attempt pair
int addStatus = esp_now_add_peer((u8*)peer_addr, ESP_NOW_ROLE_CONTROLLER, CHANNEL, NULL, 0);
if (addStatus == 0) {
// Pair success
Serial.println("Pair success");
} else {
Serial.println("Pair failed");
}
delay(100);
}
}
} else {
// No slave found to process
Serial.println("No Slave found to process");
}
}
uint8_t data = 0;
// send data
void sendData() {
data++;
for (int i = 0; i < SlaveCnt; i++) {
u8 *peer_addr = slaves[i].peer_addr;
if (i == 0) { // print only for first slave
Serial.print("Sending: ");
Serial.println(data);
}
int result = esp_now_send(peer_addr, &data, sizeof(data));
Serial.print("Send Status: ");
if (result ==0) {
Serial.println("Success " + String(result));
} else {
Serial.println("Failed " + String(result));
}
delay(100);
}
}
// callback when data is sent from Master to Slave
esp_now_send_cb_t OnDataSent(const uint8_t *mac_addr, u8 status) {
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.print("Last Packet Sent to: "); Serial.println(macStr);
Serial.print("Last Packet Send Status: "); Serial.println(status == 0 ? "Delivery Success" : "Delivery Fail");
}
void setup() {
Serial.begin(115200);
//Set device in STA mode to begin with
WiFi.mode(WIFI_STA);
Serial.println("ESPNow/Multi-Slave/Master Example");
// This is the mac address of the Master in Station Mode
Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());
// Init ESPNow with a fallback logic
InitESPNow();
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
// esp_now_register_send_cb(OnDataSent);
esp_now_register_send_cb([](uint8_t* macaddr, uint8_t status) {
printMacAddress(macaddr);
static uint32_t ok = 0;
static uint32_t fail = 0;
if (status == 0) {
Serial.println("ESPNOW: SEND_OK");
ok++;
}
else {
Serial.println("ESPNOW: SEND_FAILED");
fail++;
}
Serial.printf("[SUCCESS] = %lu/%lu \r\n", ok, ok+fail);
});
}
void loop() {
// In the loop we scan for slave
ScanForSlave();
// If Slave is found, it would be populate in `slave` variable
// We will check if `slave` is defined and then we proceed further
if (SlaveCnt > 0) { // check if slave channel is defined
// `slave` is defined
// Add slave as peer if it has not been added already
manageSlave();
// pair success or already paired
// Send data to device
sendData();
} else {
// No slave found to process
}
// wait for 3seconds to run the logic again
delay(1000);
} ESP32 code adapted from ESP32 ESPNow example: /**
ESPNOW - Basic communication - Slave
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
*/
#include <esp_now.h>
#include <WiFi.h>
#include <MQTTClient.h>
#define CHANNEL 1
/** MQTT client class to access mqtt broker */
MQTTClient mqttClient(2560);
/** MQTT broker URL */
static const char * mqttBroker = "xx.xx.xx.xx";
/** MQTT connection id */
static const char * mqttID = "ESP32";
/** MQTT user name */
static const char * mqttUser = "esp32";
/** MQTT password */
static const char * mqttPwd = "PASSWORD";
/** WiFi client class to receive messages from mqtt broker */
WiFiClient mqttReceiver;
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len);
// Init ESP Now with fallback
void InitESPNow() {
if (esp_now_init() == ESP_OK) {
Serial.println("ESPNow Init Success");
}
else {
Serial.println("ESPNow Init Failed");
ESP.restart();
}
}
// config AP SSID
void configDeviceAP() {
String Prefix = "Slave:";
String Mac = WiFi.macAddress();
String SSID = Prefix + Mac;
String Password = "123456789";
bool result = WiFi.softAP(SSID.c_str(), Password.c_str(), CHANNEL, 0);
if (!result) {
Serial.println("AP Config failed.");
} else {
Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID));
}
}
void setup() {
Serial.begin(115200);
Serial.println("ESPNow/Basic/Slave Example");
//Set device in AP mode to begin with
WiFi.mode(WIFI_AP_STA);
WiFi.begin("MYWIFI", "MYWIFIPW");
// configure device AP mode
configDeviceAP();
// This is the mac address of the Slave in AP Mode
Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
// Start connection to MQTT broker
// Connect to MQTT broker
mqttClient.begin(mqttBroker, mqttReceiver);
Serial.println("Connecting to MQTT broker");
int connectTimeout = 0;
while (!mqttClient.connect(mqttID, mqttUser, mqttPwd)) {
delay(100);
connectTimeout++;
if (connectTimeout > 10) { // Wait for 1 seconds to connect
Serial.println("Can't connect to MQTT broker");
ESP.restart();
}
}
Serial.println("Connected to MQTT");
// Init ESPNow with a fallback logic
InitESPNow();
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info.
esp_now_register_recv_cb(OnDataRecv);
}
// callback when data is recv from Master
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.print("Last Packet Recv from: "); Serial.println(macStr);
Serial.print("Last Packet Recv Data: "); Serial.println(*data);
Serial.println("");
mqttClient.publish("/debug","[INFO] Last Packet Recv from: " + tftMsg);
mqttClient.publish("/debug","[INFO] Last Packet Recv Data: " + tftMsg);
recvMsgNum++;
}
void loop() {
// Chill
} Output on Serial from ESP32:
Output on Serial from ESP8266:
Output from my MQTT broker:
|
Hi guys : I have many problems with ESP_NOW sometimes works and sometimes not.. I have an esp sending data via esp_now, i have a server that receive this data, but sometimes the server not receive the data, i change only one function and the program fail.. this is a working code !!! #include <esp_now.h> struct attribute((packed)) SENSOR_DATA_HIGROW {
} ; #define max_Cant_sensores 10 void InitESPNow() { // config AP SSID void setup() {
} Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress()); boolean checkConnection() { void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) { char macStr[18];
hume[sensorData_Higrow.id_sensor]=sensorData_Higrow.hum_tierra; void loop() { }But if i use the checkConnection() function the esp not receive data !!!!! Uncoment this code in the setup function and the system fail /*
} Can somebody explainme how to solve this issue ? Thanks |
I have exactly the same behavior 👍 either I can connect to wifi router and not get the data from ESP-NOW I have even tried to connect to wifi only when received data but it never works... Connection always failed
|
Is your WiFi AP on the same channel as ESPNow? Check ESPNow and connection to WiFi AP. It seems ESPNow is only working when using the same WiFi channel. |
Yes I tried with channel 6 which is my Wifi's channel. But does not work. I tried as well to connect to my wifi router on the "master side"set in STA mode. As soon as it connected messages from ESPnow do not get the slave... For the moment I will save the message with the "Preference Libary" and restart the ESP to connect to wifi. -> (Ugly solution) |
What I find surprising is that even if I try to Wifi.disconnect() it does not work either...
|
Try to set everything to channel 0. That was the only way I got it to work. |
When you say "everything" is it : |
Yes,that was the only way I got it working. |
Well, I have tried to set my wifi box on channel 0... It doesn't exist and starts at 1. |
Can you publish the code?
El lun., 26 mar. 2018 4:41 p. m., f2knw <notifications@github.com> escribió:
… Well, I have tried to set my wifi box on channel 0... It doesn't exist and
starts at 1.
Put all to 1
but still does not work :-(
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#878 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AFwNp8dzmVQDlRdGBGwgY4xnEw2SJIGpks5tiUR2gaJpZM4Qqw4R>
.
|
yes ! It's basically the same as above:
and now slave:
JP |
And here is a shorter version based on a broadcast instead of discovering MAC of the AP Master:
And slave:
|
both codes will work if you comment these lines:
and will block if you un comment... JP |
I'm also having this same problem. I wanted to create an esp-now relay because i read it should be possible to do WiFi and esp-now simultaneously on a ESP32. I have a working sketch but as soon as i do a WiFi begin the party is over and i won't receive esp-now packets anymore. Even tried to call esp_now_init and esp_now_register_recv_cb after begin and even for a second time before and after but all the same behavior. As soon as i try WiFi no esp-now anymore. I was switching to esp-now because the wifi connect on esp32 is so slow (2.5 secs vs <1sec on esp8266). On my esp-32 dev board the connection takes even longer then that. [edit] |
@AndreVanKammen check out the Wiki. The only way I got ESPNow & WiFiClient work together was to put all on Wifi channel 0. ESPNow seems to work only on channel 0 and if WiFi connection changes the channel it stops working. |
Thanks for the fast response. I had everything set to channel 6 but the accespoint i was connecting with was not on 6. So that was my problem, now i'm connecting with the right access point which is on channel 6 everything works. |
@AndreVanKammen happy I could help. Please return the favor by mentioning my Wiki link where it is appropriate. If problem is solved please close the issue. |
I have struggled with the same problem. I have solved the issue to communicate with the Slave and consecutively the Wifi-router without having to reset the ESP8266. It is important to put the device in WIFI_AP mode when receiving data from the Master via ESP-Now and in WIFI_STA mode when connecting to the Wifi-router: void wifiConnect() { WiFi.disconnect(); } I've put my code in the Loop function. void loop() { Here is my complete code for the Slave. I've inherited parts from @beegee-tokyo and Arvind Ravulavaru #include <espnow.h> #define CHANNEL 0 const char* ssid = "MyWiFi"; String Prefix = "Slave:"; int count = 0; void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len); // Init ESP Now with fallback // config AP SSID bool result = WiFi.softAP(SSID.c_str(), Password.c_str(), CHANNEL, 0); // callback when data is recv from Master Serial.print((char *)data); void setup() { WiFi.mode(WIFI_AP); // configure device AP mode // Init ESPNow with a fallback logic void wifiConnect() { WiFi.disconnect(); } void loop() { } |
I'm guessing this isn't solvable without wifi connects and disconnects? |
@beegee-tokyo thanks - I've read that. Unless I'm missing something, it's just saying that the channels have to be the same in the first paragraph - the problem is, while I know what channel I use at home, I don't know what someone else might use. So I would have to recompile for different routers and hope the router doesn't decide to change channels (mine's on auto, so I assume it might decide to change...). Further, since the client is the one that decides the channel for espnow when it starts softAP, and at least in my case the client never connects to WiFi, it has no idea what channel the WiFi would use. I mean, isn't that the point? That they don't all need to connect to WiFi? |
Ok, given no response, I came up with another workaround that should work in all cases, but it isn't particularly pretty. I'm doing something like a reverse channel scan. Slave:
Then the master connects to WiFi and gets the channel using WiFi.channel(), then just the regular scanNetworks(). Only difference in this is that it will keep trying to connect to the client until it succeeds, since the client is changing it's channel every few seconds until the master makes a connection. |
I have a similar problem on using esp now and wifi connection in the same code. I am trying to give command using a espnow master, and a espnow slave will connect to a wifi spot if it received a command. I tried to wifi.begin(ssid, pw) and while(1) for wait until connected in the OnDataReceied callback function. The result is that It cannot connect to the wifi spot, and more importantly this problem is somehow causing the slave esp32 board can never receive any packet from the espnow master anymore, no matter it is in broadcast mode or direct message to the espnow slave mac address. The exact same code was uploaded to another esp32 board, and after serveral trial, it has the same result. I have tried a normal, esp now only (no wifi connection) sample code after the problem had happened, the "broken" board still cannot receive packet from espnow master. The solution I just came up with is that using esptool to erase the flash, with this command: |
@Larryyyyy I had the same problem regarding the sudden stop of connection and did the erase_flash the same way as you have done.
Until now it has worked with no sudden connection problems when changing modules, mac address ,etc. |
I have found that the problem is because esp32 will save your pervious wifi connection info, like ssid, pw, and the wifi channel (you could check the saved info with WiFi.printDiag(Serial); when not connecting to a wifi.). And the problem was caused because the erase function do not erase the channel info, so
I have found that the problem is because esp32 will save your pervious wifi connection info, like ssid, pw, and the wifi channel. (WiFi.printDiag(Serial);) The problem was caused because the erase function do not erase the channel info. So you will connect to a wrong channel (previous router channel) and unable to communicate using esp now. and the wifi connected esp32 cannot change its channel, even you changed, its still stay there but visually return you have changed. so you can get the not wifi connected one change to that channel, or connect to the same wifi, then they will in the same channel and able to communicate in espnow |
larryyyyy, you wrote: I have found that the problem is because esp32 will save your previous wifi connection info, like ssid, pw, and the wifi channel. (WiFi.printDiag(Serial);) The problem was caused because the erase function do not erase the channel info. So you will connect to a wrong channel (previous router channel) and unable to communicate using esp now. and the wifi connected esp32 cannot change its channel, even you changed, its still stay there but visually return you have changed. so you can get the not wifi connected one change to that channel, or connect to the same wifi, then they will in the same channel and able to communicate in espnow Regarding the saving of connection info, yes, I also figured that out. Do you mean the connection info must be erased in another way? I do not have much experience regarding the ESP series, hence all these questions. Below is the setup of the Wifi connection and espnow I use. However, the transmitter(STA) always fails with:
|
I haven't tested on your code yet. I am trying to make redis work on esp. tell me if you had experience on it. The situation is like that: day1, you used espnow for communication between master and slave. You send a wifi info from master esp to slave esp using espnow, so that the slave esp know the wifi and connect to it. the slave esp connected to the wifi: (SSID_WIFI_A, PW_WIFI_A, Channel_A). After connection, the slave esp found the channel of the wifi, using it, and saved those information. now, without wifi, you want to use espnow for communication as usual. However , it doesnt work. because the slave's channel is in channel_A, but Master is in channel 1. Until the slave connected to wifi using command WiFi.begin(ssid, password,WIFI_CHANNEL);, it seems good. However, sometimes the wifi is still using its own channel although you set it to a specific one. I have no idea why. So my solution to this is, keep the slave in the router wifi channel, WiFi.begin(ssid, password), do not set a specific one to the slave. Change the master channel to match it. another way you don't need to change the master's channel is that connect the master to the same wifi, and it will automatically switch to that channel. if the slave need not to be connecting wifi, this command WiFi.begin(ssid, password,WIFI_CHANNEL); cannot be used. then how to change the channel? uint8_t primaryChan = WIFI_CHANNEL; hopes that help😋 back to the redis research.... |
so the solution is that, if wifi is not needed for master and slave , both master and slave do the following 2 steps. after that, they will in the same channel, even previous connected to other wifi or in any channel. and you may try WiFi.begin(ssid, password,WIFI_CHANNEL); now |
@Larryyyyy , Finally, it works :-) |
HI, and the exact solution is ? |
set the wifi channel to a specific one even you haven't connected or not planning to connect to a wifi. |
To illustrate it, here is a cut from my working code.
|
Hi, On my side it does not work... On the slave slide, I do want something independant of the router configuration... Here is the trick I found to avoid this bug (not very clean but seems to work)... Master side is the code found in the Arduino IDE Slave slide is adapted to reboot the ESP after receiving data from the master. A permanent variable is used to boot either with WIFI or ESPnow : RTC_DATA_ATTR bool LaunchWifi Note that you can pass more variables with the same trick... It seems to work ! I leave it under test during a few days to be sure ! here is the code : `/** << This Device Slave >> Flow: Master Flow: Slave Note: Master and Slave have been defined to easily understand the setup. #include <esp_now.h> #include <HTTPClient.h> //to access internet #define CHANNEL 1 RTC_DATA_ATTR bool LaunchWifi = false; //this is used to allow restart le ESP32 from deepsleep without loosing this variable // Init ESP Now with fallback // config AP SSID void setup() { pinMode(LED_PIN, OUTPUT); Serial.println("ESPNow/Basic/Slave Example"); esp_sleep_enable_timer_wakeup(100); //We set our ESP32 to wake up every 100 µseconds if (LaunchWifi)
} //Set device in AP mode to begin with // callback when data is recv from Master void WiFiReset() { void loop() { |
Having banged my head against the wall getting this to work, I thought I would write some summary notes of what works for me ... without 100s of lines of code.
In this way, everything is auto-configured based on one fixed variable - the channel number of the external WiFi AP. Once the master knows this number, it can propagate it to all slaves using the configuration of its soft AP. I hope this helps someone. |
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions. |
yes most of issue related to Wifi channel..I made them all the same for slaves and controller and wifi router and mostly stable than before...there is a drop packets every rarely time but it's better than before! thanks for hint :) |
Since I wrote the examples for the ESPNow, the API for selecting a channel has changed, I discovered using arduino-esp32 1.0.4.
Your error desciption may indicate thet the channel selection is not working.
The country code for ESP32 is default CN which allows channels 1 - 13.
I assume you do not change this.
I have written example code for a 'master' or rather WiFi-ESPNow gateway and a slave which scans all channels looking for the gateway.
You can find the explanation and code here:
https://www.esp32.com/viewtopic.php?f=19&t=12992
The code is only for tests, but you can see how the new channel setting is implemented.
I have not tested channel 13 as too many Wifi devies are constricted to 1 - 11!
Hope this helps.
Sun, 12 Jan 2020 19:54:56 -0800
quangvankts <notifications@github.com> wrote:
I build up a small test configuration with an ESP8266 sending data over ESPNow and an ESP32 receiving data over ESPNow. Then the ESP32 send the received data over MQTT to an MQTT broker and it works.
## But there is one condition:
**The Wifi you connect to must be on the same Wifi channel that is used for ESPNow.**
**_In my case I tested with ESPNow sending/receiving on channel 1 and the ESP32 connected to a WiFi which is using channel 1 as well._**
If I connect to another WiFi that uses e.g. channel 13, the ESP32 does not receive any ESPNow data anymore.
I tried to change the ESPNow channel to 13, but I didn't get the connection between the ESP8266 and ESP32 to work (with or without a WiFi connection). That might be a limitation on the ESP8266 (???) but I have only one ESP32 to test.
Here is the code that worked for me:
ESP8266 code adapted from [ESP32 ESPNow example](https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/ESPNow/Multi-Slave/Slave/Slave.ino):
```c++
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Ticker.h>
extern "C" {
#include <espnow.h>
#include <user_interface.h>
}
/**
ESPNOW - Basic communication - Master
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
*/
typedef struct esp_now_peer_info {
u8 peer_addr[6]; /**< ESPNOW peer MAC address that is also the MAC address of station or softap */
uint8_t channel; /**< Wi-Fi channel that peer uses to send/receive ESPNOW data. If the value is 0,
use the current channel which station or softap is on. Otherwise, it must be
set as the channel that station or softap is on. */
} esp_now_peer_info_t;
// Global copy of slave
#define NUMSLAVES 20
esp_now_peer_info_t slaves[NUMSLAVES] = {};
int SlaveCnt = 0;
#define CHANNEL 1
void printMacAddress(uint8_t* macaddr) {
Serial.print("{");
for (int i = 0; i < 6; i++) {
Serial.print("0x");
Serial.print(macaddr[i], HEX);
if (i < 5) Serial.print(',');
}
Serial.println("};");
}
// Init ESP Now with fallback
void InitESPNow() {
if (esp_now_init() == 0) {
Serial.println("ESPNow Init Success");
}
else {
Serial.println("ESPNow Init Failed");
ESP.restart();
}
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
}
// Scan for slaves in AP mode
void ScanForSlave() {
int8_t scanResults = WiFi.scanNetworks();
//reset slaves
memset(slaves, 0, sizeof(slaves));
SlaveCnt = 0;
Serial.println("");
if (scanResults == 0) {
Serial.println("No WiFi devices in AP Mode found");
} else {
Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
for (int i = 0; i < scanResults; ++i) {
// Print SSID and RSSI for each device found
String SSID = WiFi.SSID(i);
int32_t RSSI = WiFi.RSSI(i);
String BSSIDstr = WiFi.BSSIDstr(i);
delay(10);
// Check if the current device starts with `Slave`
if (SSID.indexOf("Slave") == 0) {
// SSID of interest
Serial.print(i + 1); Serial.print(": ");
Serial.print(SSID); Serial.print(" [");
Serial.print(BSSIDstr); Serial.print("]");
Serial.print(" ("); Serial.print(RSSI);
Serial.print(")"); Serial.println("");
// Get BSSID => Mac Address of the Slave
char macPart[4];
macPart[0] = '0';
macPart[1] = 'x';
macPart[2] = (char)BSSIDstr[0];
macPart[3] = (char)BSSIDstr[1];
slaves[SlaveCnt].peer_addr[0] = strtol(macPart,0,16);
macPart[2] = (char)BSSIDstr[3];
macPart[3] = (char)BSSIDstr[4];
slaves[SlaveCnt].peer_addr[1] = strtol(macPart,0,16);
macPart[2] = (char)BSSIDstr[6];
macPart[3] = (char)BSSIDstr[7];
slaves[SlaveCnt].peer_addr[2] = strtol(macPart,0,16);
macPart[2] = (char)BSSIDstr[9];
macPart[3] = (char)BSSIDstr[10];
slaves[SlaveCnt].peer_addr[3] = strtol(macPart,0,16);
macPart[2] = (char)BSSIDstr[12];
macPart[3] = (char)BSSIDstr[13];
slaves[SlaveCnt].peer_addr[4] = strtol(macPart,0,16);
macPart[2] = (char)BSSIDstr[15];
macPart[3] = (char)BSSIDstr[16];
slaves[SlaveCnt].peer_addr[5] = strtol(macPart,0,16);
SlaveCnt++;
}
}
}
if (SlaveCnt > 0) {
Serial.print(SlaveCnt); Serial.println(" Slave(s) found, processing..");
} else {
Serial.println("No Slave Found, trying again.");
}
// clean up ram
WiFi.scanDelete();
}
// Check if the slave is already paired with the master.
// If not, pair the slave with master
void manageSlave() {
if (SlaveCnt > 0) {
for (int i = 0; i < SlaveCnt; i++) {
const esp_now_peer_info_t *peer = &slaves[i];
u8 *peer_addr = slaves[i].peer_addr;
Serial.print("Processing: ");
for (int ii = 0; ii < 6; ++ii ) {
Serial.print((uint8_t) slaves[i].peer_addr[ii], HEX);
if (ii != 5) Serial.print(":");
}
Serial.print(" Status: ");
// check if the peer exists
bool exists = esp_now_is_peer_exist((u8*)peer_addr);
if (exists) {
// Slave already paired.
Serial.println("Already Paired");
} else {
// Slave not paired, attempt pair
int addStatus = esp_now_add_peer((u8*)peer_addr, ESP_NOW_ROLE_CONTROLLER, CHANNEL, NULL, 0);
if (addStatus == 0) {
// Pair success
Serial.println("Pair success");
} else {
Serial.println("Pair failed");
}
delay(100);
}
}
} else {
// No slave found to process
Serial.println("No Slave found to process");
}
}
uint8_t data = 0;
// send data
void sendData() {
data++;
for (int i = 0; i < SlaveCnt; i++) {
u8 *peer_addr = slaves[i].peer_addr;
if (i == 0) { // print only for first slave
Serial.print("Sending: ");
Serial.println(data);
}
int result = esp_now_send(peer_addr, &data, sizeof(data));
Serial.print("Send Status: ");
if (result ==0) {
Serial.println("Success " + String(result));
} else {
Serial.println("Failed " + String(result));
}
delay(100);
}
}
// callback when data is sent from Master to Slave
esp_now_send_cb_t OnDataSent(const uint8_t *mac_addr, u8 status) {
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.print("Last Packet Sent to: "); Serial.println(macStr);
Serial.print("Last Packet Send Status: "); Serial.println(status == 0 ? "Delivery Success" : "Delivery Fail");
}
void setup() {
Serial.begin(115200);
//Set device in STA mode to begin with
WiFi.mode(WIFI_STA);
Serial.println("ESPNow/Multi-Slave/Master Example");
// This is the mac address of the Master in Station Mode
Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());
// Init ESPNow with a fallback logic
InitESPNow();
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
// esp_now_register_send_cb(OnDataSent);
esp_now_register_send_cb([](uint8_t* macaddr, uint8_t status) {
printMacAddress(macaddr);
static uint32_t ok = 0;
static uint32_t fail = 0;
if (status == 0) {
Serial.println("ESPNOW: SEND_OK");
ok++;
}
else {
Serial.println("ESPNOW: SEND_FAILED");
fail++;
}
Serial.printf("[SUCCESS] = %lu/%lu \r\n", ok, ok+fail);
});
}
void loop() {
// In the loop we scan for slave
ScanForSlave();
// If Slave is found, it would be populate in `slave` variable
// We will check if `slave` is defined and then we proceed further
if (SlaveCnt > 0) { // check if slave channel is defined
// `slave` is defined
// Add slave as peer if it has not been added already
manageSlave();
// pair success or already paired
// Send data to device
sendData();
} else {
// No slave found to process
}
// wait for 3seconds to run the logic again
delay(1000);
}
```
ESP32 code adapted from [ESP32 ESPNow example](https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/ESPNow/Multi-Slave/Master/Master.ino):
```c++
/**
ESPNOW - Basic communication - Slave
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
*/
#include <esp_now.h>
#include <WiFi.h>
#include <MQTTClient.h>
#define CHANNEL 1
/** MQTT client class to access mqtt broker */
MQTTClient mqttClient(2560);
/** MQTT broker URL */
static const char * mqttBroker = "xx.xx.xx.xx";
/** MQTT connection id */
static const char * mqttID = "ESP32";
/** MQTT user name */
static const char * mqttUser = "esp32";
/** MQTT password */
static const char * mqttPwd = "PASSWORD";
/** WiFi client class to receive messages from mqtt broker */
WiFiClient mqttReceiver;
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len);
// Init ESP Now with fallback
void InitESPNow() {
if (esp_now_init() == ESP_OK) {
Serial.println("ESPNow Init Success");
}
else {
Serial.println("ESPNow Init Failed");
ESP.restart();
}
}
// config AP SSID
void configDeviceAP() {
String Prefix = "Slave:";
String Mac = WiFi.macAddress();
String SSID = Prefix + Mac;
String Password = "123456789";
bool result = WiFi.softAP(SSID.c_str(), Password.c_str(), CHANNEL, 0);
if (!result) {
Serial.println("AP Config failed.");
} else {
Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID));
}
}
void setup() {
Serial.begin(115200);
Serial.println("ESPNow/Basic/Slave Example");
//Set device in AP mode to begin with
WiFi.mode(WIFI_AP_STA);
WiFi.begin("MYWIFI", "MYWIFIPW");
// configure device AP mode
configDeviceAP();
// This is the mac address of the Slave in AP Mode
Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
// Start connection to MQTT broker
// Connect to MQTT broker
mqttClient.begin(mqttBroker, mqttReceiver);
Serial.println("Connecting to MQTT broker");
int connectTimeout = 0;
while (!mqttClient.connect(mqttID, mqttUser, mqttPwd)) {
delay(100);
connectTimeout++;
if (connectTimeout > 10) { // Wait for 1 seconds to connect
Serial.println("Can't connect to MQTT broker");
ESP.restart();
}
}
Serial.println("Connected to MQTT");
// Init ESPNow with a fallback logic
InitESPNow();
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info.
esp_now_register_recv_cb(OnDataRecv);
}
// callback when data is recv from Master
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.print("Last Packet Recv from: "); Serial.println(macStr);
Serial.print("Last Packet Recv Data: "); Serial.println(*data);
Serial.println("");
mqttClient.publish("/debug","[INFO] Last Packet Recv from: " + tftMsg);
mqttClient.publish("/debug","[INFO] Last Packet Recv Data: " + tftMsg);
recvMsgNum++;
}
void loop() {
// Chill
}
```
Output on Serial from ESP32:
```
ESPNow/Basic/Slave Example
AP Config Success. Broadcasting with AP: Slave:24:0A:C4:81:CE:9C
AP MAC: 24:0A:C4:81:CE:9D
Connecting to MQTT broker
[E][WiFiClient.cpp:97] connect(): lwip_connect_r: 113
Connected to MQTT
ESPNow Init Success
Last Packet Recv from: 5c:cf:7f:01:5a:5d
Last Packet Recv Data: 91
Last Packet Recv from: 5c:cf:7f:01:5a:5d
Last Packet Recv Data: 92
Last Packet Recv from: 5c:cf:7f:01:5a:5d
Last Packet Recv Data: 93
Last Packet Recv from: 5c:cf:7f:01:5a:5d
Last Packet Recv Data: 94
```
Output on Serial from ESP8266:
```
ESPNow/Multi-Slave/Master Example
STA MAC: 5C:CF:7F:01:5A:5D
ESPNow Init Success
Found 6 devices
2: Slave:24:0A:C4:81:CE:9C [24:0A:C4:81:CE:9D] (-55)
1 Slave(s) found, processing..
Processing: 24:A:C4:81:CE:9D Status: Pair success
Sending: 1
Send Status: Success 0
{0x24,0xA,0xC4,0x81,0xCE,0x9D};
ESPNOW: SEND_OK
[SUCCESS] = 1/1
```
Output from my MQTT broker:
```
[INFO] Last Packet Recv from: 5c:cf:7f:01:5a:5d
[INFO] Last Packet Recv Data: 42
[INFO] Last Packet Recv from: 5c:cf:7f:01:5a:5d
[INFO] Last Packet Recv Data: 43
[INFO] Last Packet Recv from: 5c:cf:7f:01:5a:5d
[INFO] Last Packet Recv Data: 44
```
Im using your code to send ESPNow messages between ESP8266 (Master) to ESP32 (Slave) (without connecting to MQTTClient) , set them up on same channel, but only about 25% of the messages reach the ESP32. The weird thing is even if I set them on different channels, it still works and I still get the same result (still around 20-25% of the messages reach the ESP32). Any idea what I am doing wrong here ? Thanks !
…--
You are receiving this because you commented.
Reply to this email directly or view it on GitHub:
#878 (comment)
|
Change this part of your code: // Get BSSID => Mac Address of the Slave
with this code Hope it helps |
I found a simple solution! :) My ESP-NOW setup worked for over a year flawlessly, with the slave permanently connected to WiFi. Finally I could at least figure out what the problem was. The ESP8266 always uses WiFi channel # 1, regardless which channel was configured with esp_now_add_peer(remoteMac, ESP_NOW_ROLE_SLAVE, wifi_channel, NULL, 0);
"configured WiFi channel: 8" but "sent on WiFi channel 1" Nothing helped! (at least on the ESP8266) The solution I found, was to setup a not-connecting WiFi connection:
With the last parameter connect=false, WiFi is only setup but no connection attempts will be made (which would obviously fail with the dummy SSID and password) but this will change the ESP NOW WiFi channel!. That's it! Now it works with every WiFi channel! :)
"sent on WiFi channel 8" And, btw. for those who don't want to hardcode the channel number:
|
I followed the same in the example but I have strange result! the MAC address of peer is changed from first discovering and after peer processing.. this is the result!
Any Help please! Thanks for all |
I can confirm that Sender -> ESP-Now -> Receiver -> WiFi -> World scheme works only on WiFi channel 1. I made experiment with 2 ESP8266 boards. One is sender and one is receiver. Everything works fine until I tried to start STA connection to WiFi network. Immediatelly after I tried to connect receiver to WiFi it stops receiving packet. So I switch sender to channel 1, recompile and load new sketch. But strange thing. Receiver configured at channel 13 continue receiving packets sending on channel 1. Seems to me Esp-Now works on channel 1 all the time. But may be I'm worng. |
@glush see my solution above to set the WiFi channel: |
Hi If you want to see the code or watch it working, just ask for! |
That doesn't work for me for the ESP32, but this does esp_wifi_set_promiscuous(true); Combine this with the access point and scan that @smartkodian is using above, and everything works no matter what channel you are on (WiFi.channel(i) will return the channel after the scan). It's also a lot easier to use the WiFi.BSSID(i) , which returns a uint8_t pointer, directly in the memcpy of the peer_addr of the esp_now_peer_info_t struct, rather than parse our the string from WiFi.BSSIDstr(i). |
This works for me with an esp32 as Master (transmitter) in the Arduino IDE: Master code (excerpt): //...
#define PEER_SSID_PREFIX "MyIoT" // SSID Praefix of the Slaves
#define PRINTSCANRESULTS 1 // 0: no, 1: yes
#define DELETEBEFOREPAIR 0 // 0: no, 1: yes
//...
uint8_t channel_old = 0;
//...
//-------------------------------------------------
// Scan for slaves in Access Point (AP) mode
//-------------------------------------------------
void ScanForSlave() {
int8_t scanResults = WiFi.scanNetworks();
// reset on each scan
bool slaveFound = 0;
memset(&slave, 0, sizeof(slave));
Serial.println("");
if (scanResults == 0) {
Serial.println("No WiFi devices in AP Mode found");
} else {
Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
for (int i = 0; i < scanResults; ++i) {
// Print SSID and RSSI and channel for each device found
String SSID = WiFi.SSID(i);
int32_t RSSI = WiFi.RSSI(i);
String BSSIDstr = WiFi.BSSIDstr(i);
uint8_t channel = WiFi.channel(i);
if (PRINTSCANRESULTS) {
Serial.print(i + 1);
Serial.print(": ");
Serial.print(SSID);
Serial.print(" (");
Serial.print(RSSI);
Serial.print(")");
Serial.print(" Chn: ");
Serial.print(channel);
Serial.println();
}
delay(10);
// Check if the current device starts with string defined in PEER_SSID_PREFIX
if (SSID.indexOf(PEER_SSID_PREFIX) == 0) {
// SSID of interest
Serial.println("Found a Slave.");
Serial.print(i + 1);
Serial.print(": ");
Serial.print(SSID);
Serial.print(" [");
Serial.print(BSSIDstr);
Serial.print("]");
Serial.print(" (");
Serial.print(RSSI);
Serial.print(")");
Serial.print(" Chn: ");
Serial.print(channel);
Serial.println();
// Get BSSID => Mac Address of the Slave
int mac[6];
if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
for (int ii = 0; ii < 6; ++ii ) {
slave.peer_addr[ii] = (uint8_t) mac[ii];
}
}
slave.channel = channel; // use slave channel
slave.encrypt = 0; // no encryption
// Check if channel has changed?
if(channel != channel_old) {
// esp_wifi_set_promiscuous(true);
// esp_wifi_set_channel(channel,WIFI_SECOND_CHAN_NONE);
// esp_wifi_set_promiscuous(false);
// Workaround to set channel
setupDummyAP();
WiFi.disconnect();
//Set device in Station mode (STA) to begin with
//Usually, Station interface is set for CONTROLLER, SoftAP interface for SLAVE AND COMBO.
WiFi.mode(WIFI_STA);
channel_old = channel;
}
slaveFound = 1;
// we are planning to have only one slave in this example;
// Hence, break after we find one, to be a bit efficient
break;
}
}
}
if (slaveFound) {
Serial.println("Slave Found, processing..");
} else {
Serial.println("Slave Not Found, trying again.");
}
// clean up ram
WiFi.scanDelete();
}
//...
//-------------------------------------------------
// Workaround: setup a not connecting WiFi AP to change the channel
//-------------------------------------------------
void setupDummyAP() {
WiFi.disconnect();
WiFi.mode(WIFI_AP);
delay(100);
const char *dummy = "abcdefgh";
// SSID , PSK , channel , BSSID, connect
WiFi.softAP(dummy, dummy, slave.channel, 0, false);
delay(250);
// DEBUG: print WiFi connection info
// Mode, Channel, SSID, Passphrase , BSSID, AP MAC
//WiFi.printDiag(Serial);
Serial.print("Channel new: ");
Serial.println(WiFi.channel());
delay(100);
}
/-------------------------------------------------
// Setup
//-------------------------------------------------
void setup() {
Serial.begin(115200);
Serial.println("ESPNow/Basic/Master Example");
//WiFiReset();
WiFi.disconnect();
//Set device in Station mode (STA) to begin with
//Usually, Station interface is set for CONTROLLER, SoftAP interface for SLAVE AND COMBO.
WiFi.mode(WIFI_STA);
// This is the mac address of the Master in Station mode (STA)
Serial.print("STA MAC: ");
Serial.println(WiFi.macAddress());
// DEBUG: print WiFi connection info
// Mode, Channel, SSID, Passphrase , BSSID, AP MAC
//WiFi.printDiag(Serial);
Serial.print("Channel: ");
Serial.println(WiFi.channel());
delay(100);
// Init ESP-Now with a fallback logic
InitESPNow();
// Once ESP-Now is successfully initialized, we will register for Send Call Back to
// get the status of the transmitted packet
esp_now_register_send_cb(OnDataSent);
}
//-------------------------------------------------
// Loop
//-------------------------------------------------
void loop() {
// In the loop we scan for slave
ScanForSlave();
// If Slave is found, it would be populate in the 'slave' variable
// We will check if 'slave' variable is defined and then we proceed further
if (slave.channel) { // check if slave channel is defined
// 'slave' is defined
// Add slave as peer if it has not been added already
bool isPaired = manageSlave();
if (isPaired) {
// pair success or already paired
// Send data to device
sendData();
} else {
// slave pair failed
Serial.println("Slave pair failed!");
}
}
else {
// No slave found to process
}
// wait for 10 seconds to run the logic again
delay(10000);
} |
+ peer book listing (debug) + no addressbook/peer list -> all go broadcast! + wifi_channel == 1 for later (espressif/arduino-esp32#878 (comment))
Hardware:
Board: ?ESP32 Dev Module?
Core Installation/update date: ?11/jul/2017?
IDE name: ?Arduino IDE? ?Platform.io? ?IDF component?
Flash Frequency: ?40Mhz?
Upload Speed: ?115200?
Description:
I am using mqtt protocol and sending data to AWS server.
and simultaneously receiving data from other esp32 and sending that data to the server.
The problem is before Wifi client connects to AWS , esp now is working(I am receiving data from other esp32) , but after WiFi client connects to AWS , esp now stops working (No data is received) . And when Wifi client disconnects from AWS , esp now is working.
I loaded esp_now Slave code in the esp32 which to connects AWS and the devices is configured as AP_STA mode. Esp_now Mater code in other esp32 which send its data.
My doubt : Is AP and STA cannot work simultaneously. If it is not possible tell me is there any way to receive data from other esp32 through AP and send data to the server
The text was updated successfully, but these errors were encountered: