Hello Rui & Sara,
I would like to set up an ESP-NOW network with ESP32s: several transmitters (masters) send data to an ESP32 receiver (slave) which acts as a gateway and which must be able to simultaneously connect to a WiFi network broadcast by a router (and therefore have an IP address in the router’s LAN).
Despite all my attempts, I am not succeeding…
The gateway no longer receives messages transmitted with the ESP-NOW protocol.
Do you have a trick to achieve this?
Hi Steph.
We have a similar project. See it here: https://randomnerdtutorials.com/esp32-esp-now-wi-fi-web-server/
There are some tricks:
- you need to set the receiver both as an access point and a station;
- the ESP32 should use a different Wi-Fi channel for station mode and different channel for the access point (for example, channel 2);
- the sender boards should be connected to the receiver via access point on channel 2.
Some of our readers complaint that this approach reduces the communication range (I haven’t tested this). So, they suggested having a receiver board (in “normal” ESP-NOW operation) that then, communicates with other ESP32 via serial. This last ESP32 will connect to a router to host a web server.
I hope this helps.
Regards,
Sara
Hi Sara,
Thank you for your suggestion, but the problem has nothing to do with the case where the ESP32 receiver is in access point mode. I’ve already done a project in this configuration… which I posted a few days ago:
Comparison of temperature sensors
And in this case, everything goes without a hitch. This is the simplest case because there are no constraints imposed by a router’s WiFi network.
The case that interests me here is to place the ESP32 receiver in the LAN network of the WiFi router. It is clear that it has to be configured in WIFI_MODE_APSTA
mode to be able to receive ESP-NOW packets from all ESP-NOW senders, but also to be accessible from the router’s network. I want to expose its web server to HTTP clients that are already on the router’s network. And I don’t want these clients to connect to an access point exposed by the ESP32 itself.
The problem seems to come from a bug in the Espressif framework. It seems indeed impossible to fix the WiFi communication channel between ESP-NOW nodes when the receiver is in WIFI_MODE_APSTA
mode. Indeed, the receiver being in fact connected to the router, it is forced to use the same channel as the router one. And it is impossible for it to receive the packets from the sending nodes if they do not use the same channel as the router! However, the Espressif framework API provides a way to specify the channel of your choice. But it doesn’t work! If you take a closer look at the channel used by ESP-NOW messages, you’ll see that it doesn’t correspond to the channel you set in your code!
However, if you look at the code of Espressif a little closer, you will see that they use channel 1 by default. Therefore, I managed to make everything work on the only condition that the router itself uses channel 1, so that all ESP32s (both senders and receiver) all use this channel. And now it works!
So we are forced to set the WiFi channel of the router to 1, which is still annoying if we have interferences with other routers in the neighborhood … I would really like to find a trick to be able to set the channel of my choice!
So I was wondering if you hadn’t done some further tests on your side. If you haven’t, that’s okay… I’ll try to get by on my side. But I still encourage you to dig a little deeper, because you might give your readers the wrong information…
… and if you manage to fix the channel of your choice, I’d be curious to know how š
Regards,
Steph
Hi Steph.
I’m not sure if I understood your issue.
In our example, the web server is accessible through the local network – it is set as a station. You don’t need to connect to an access point. Your smartphone just needs to be connected to your router to access the web server.
As for the wi-fi channel, the printed wi-fi channel in the serial monitor corresponds to the channel used to communicate with the router (default channel in the diagram), in our case, it is channel 6.
This is my understanding of the situation. I might be wrong. I’ll need to search a bit more about this issue, because I haven’t made any further tests.
Let me know if you find anything else about this issue.
Regards,
Sara
Hi Sara,
Unfortunately, I think you’re making a big mistake.
ESP-NOW is a connectionless protocol.
Read your tutorial again… And have a look at the ESP32 Sender Code (ESP-NOW) section.
Indeed, you connect the senders to the receiver:
//Set device as a Wi-Fi Station WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to Access Point..."); }
From that point on, you don’t really use ESP-NOW protocol…
And a WiFi connection consumes much more energy than the ESP-NOW protocol requires.
In my opinion, the tutorial needs to be revised…
The actual implementation of the ESP-NOW protocol must be done without a connection. Senders must be configured with WIFI_MODE_STA
mode, and must not connect to the receiving ESP32 access point.
What I was trying to explain to you in my previous post is that I had succeeded in doing so on the sole condition that the ESP-NOW communication channel is the same as the channel of the WiFi router to which the ESP32 receiver is connected (since this is precisely what we want here).
However, it is impossible to set the communication channel of the ESP32 senders without a connection! They switch inexorably to channel 1. Therefore, the only solution you have left to ensure that everything works properly is to configure the WiFi router on channel 1.
And that’s what’s so annoying :-/
I guess it’s — either a bug — or a technical constraint (?)
I’ve been unable to find another solution on my own.
Please try to explore the issue with Rui so that we can try to figure it out and come up with a solution if there is one. It makes a big difference in the power consumption of a sensor network!
Cheers,
Steph
Hi Steph.
Now I understand what you’re saying.
Setting up different wi-fi channels and using the access point was the workaround we found at the time to make things work (although it is not connectionless as you mentioned).
As I’ve told you previously, another workaround is to use serial communication with another board that will act as a web server.
Meanwhile, if you find any solution or more details about this, please share.
Thank you so much for your valuable contributions to this forum.
Regards,
Sara
Hi Sara,
Yes, I read FranƧois’ proposal in the tutorial comments. Isolate the ESP-NOW network by serial-linking the receiver to another ESP32 which is connected to the Internet (as a station on a WiFi router) is an excellent idea.
Nevertheless this solution allows to bypass the problem but not to solve itĀ š
For the moment I’m stuck on the solution, acceptable but not ideal, that I explained to you above. I haven’t found a better one yet. But if I do find something, I’ll be sure to share it with you.
But that doesn’t stop you from looking your own way with RuiĀ š
And I still suggest you add a disclaimer in your tutorial to nuance your speech and inform the readers of the underlying problem … It is better to explain things clearly rather than have people think that you have preferred to ignore the difficulties that you have not been able to resolve, hoping that no one will notice. This can only work in favour of the trust your readers have in you.
Best wishes,
Steph
Looking at the ESP-NOW user guideĀ it appears that setting the channel is indeed possible (1 – 14) . Perhaps the library doesn’t support that.
According to thisĀ https://www.instructables.com/id/An-ESP-Now-Home-Weather-Station/Ā “the ESP-Now protocol cannot be active at the same time as the WIFI connection” but this Ā Github ProjectĀ appears to say you can.
My project doesn’t need ESP-NOW so I’m not digging into this any more. Good luck.
The weather station project on instructables circumvents the problem by isolating the ESP-NOW network: the module that receives the data from the sensors is connected to another ESP32 module via a serial link, which is connected to a WiFi router. It therefore does not solve the underlying problem.
As for the GitHub project, it is irrelevant insofar as it connects the sending module to the receiving module via a WiFi link and therefore does not respect the conditions of use of the ESP-NOW protocol.
My research shows that it should be possible to have both ESP-NOW and TCP/IP working at the same time and on whatever channel you want. Caveat – All devices must be on the same channel. Best idea is connect to router and find out what channel it’s using and then set master and slaves ESP-NOW to the same channel.
Reference
The channel 1 issue is also mentioned and a workaround figured out.
Thank you, Steve, for doing some research on your own.
I’ve also come across this discussion…
But after trying a whole bunch of things, it turns out it’s impossible to set another channel than channel 1 on ESP-NOW senders (since they’re not connected to any WiFi access point). They inexorably use channel 1. So the only way to make them communicate with the ESP-NOW receiving node, which is connected to the WiFi router, is to configure the router with channel 1. This is the problem. This constraint is far from ideal.
Did you look at thisĀ example?
It supposedly sets the master (The ESP32 that does both TCP/IP and ESP-NOW protocols) to channel 10 (Note that the router must also be on this channel). Then each slave ((The ESP32 that does ESP-NOW protocol only) connects to WiFi to find the channel number in use, sets that channel number and sets up ESP-NOW on that channel.
There was a post on how to set the channel that worked by setting up a non-connecting WiFi connection.
Thank you Steve, I’ve done a lot of research myself as well… and I’ve come across these proposals as well. Unfortunately, none of them work with the current version of the arduino-esp32 core.
Hi.
One of our readers posted this in our comments’ section:
“
Steph,
AtĀ https://rntlab.com/question/esp-now-gateway-wifi_mode_sta-with-a-wifi-router/, you said, āIāve done a lot of research myself as wellā¦ and Iāve come across these proposals as well. Unfortunately, none of them work with the current version of the arduino-esp32 core.ā
Iām not a member of RNT Lab, so I cannot contribute over there.
It is not impossible to set a channel other than channel 1 on ESP-NOW senders. After some experimentation, Iāve found that the concepts presented in the example linked to by Steven just prior to your post do indeed work. You just need to #include <esp_wifi.h>. Is that not part of the arduino-esp32 core?
The project presented in this post can be easily converted to use purely ESP-NOW between the sender and receiver with just a few simple changes.
Letās start with the receiver code. (Note: Line numbers areĀ currentĀ line numbers before any edits.)
Lines 21-26 and 157-158 are not needed. There is no need to configure and start an Access Point.
Line 144 IS needed as is. Though we do not need a āhotā AP, we do need to enable the AP interface else communication will be unreliable.
Done there. Letās go to the sender code. (Again,Ā currentĀ line numbers.)
#include <esp_wifi.h>
Lines 17-19 are not needed. There is no reason to connect to an AP that isnāt there.
At line 38, set the channel number (CHAN_AP) to the SAME channel number as the receiverās WiFi channel number. It must be the same else communication will be unreliable.
Since we are not connecting to an AP, lines 99-105 are also not needed. But we need to do something else here.
So, replace those lines with:
// Set device as a Wi-Fi Station & set channel
WiFi.mode(WIFI_STA);
//WiFi.printDiag(Serial); // Uncomment to verify channel number before
esp_wifi_set_promiscuous(true);
esp_wifi_set_channel(CHAN_AP, WIFI_SECOND_CHAN_NONE);
esp_wifi_set_promiscuous(false);
//WiFi.printDiag(Serial); // Uncomment to verify channel change after
Unless Iāve overlooked some of the edits I did to make it work, that should be it.
Keep in mind that if you set the peer_addr (or in this case broadcastAddress at line 35) to FF:FF:FF:FF:FF:FF, then any device on the channel will receive it. If you wish to specifically target the receiver, you should set it to the WiFi MAC address of the receiver. You probably already know, but others may not, that you can get the address of the receiver by adding āSerial.println(WiFi.macAddress());ā to the receiver code after setting the WiFi mode.”
You can see the comment here: https://randomnerdtutorials.com/esp32-esp-now-wi-fi-web-server/#comment-480633
Regards,
Sara
Yes, thank you Sara, and I just answered it:
https://randomnerdtutorials.com/esp32-esp-now-wi-fi-web-server/#comment-483289
Thank you Lee for your input.
I donāt rely on the code in this tutorial. I developed my own project.
However, Iāll know what youāre referring to with your line numbers.Neverthelessā¦ the one and only thing that I think is important here (and that I thought I had tested without success on my side) is the use of the following directive:
esp_wifi_set_promiscuous(flag); // true / falseI will try again as soon as possible (I need to finish another project first).
And I will come back to you to let you know the result.Thank you for taking the time to study the problem.
Best regards.
Steph
Hey guys,
The solution proposed on the Espressif forum works!
It is indeed necessary to make sure to use the esp_wifi_set_promiscuous
function before setting the radio channel.
@Steve Thanks again for bringing this solution to my attention.
I report here the answer I gave to Lee :
Hey Lee,
Sorry for my previous answer, which I accidentally took out of the thread.
I was finally able to test the solution proposed on the Espressif forum (which you mentioned in your comment)… and it works!!!
I was sure I had tested it, but it probably escaped me while I was trying to change my code all the time.
Anyway, thanks a lot to you and Steve for bringing this solution to my attention.
I’ve posted a complete sample code on GitHubĀ so that it can be used by the whole RNT community. And I encourage Sara and Rui to quickly modify their tutorial to propose a correct implementation of the ESP-NOW protocol.
Thanks again!
@Sara I posted a reply to Lee in the tutorial comments.
But my answer is waiting for validation :-/ …
Thanks to all of you.
The comment has now been approved. Thanks!
Thank you all for sharing this solution. We’ll update the tutorial in a week or two and probably send it in our newsletter again.
Regards,
Sara
Thank you, Sara, for your approval.
And thank you also for taking the time to correct your tutorial.
It’s a good thing š
Hi.
I finally had the time to experiment your suggestions.
It works perfectly! š
Thank you so much for your valuable inputs.
The tutorial is now updated.
Thank you.
I’ll mark this issue as resolved.
Regards, Sara
Thank you Sara,
I’m glad we could help you and especially draw your attention to the connectionless nature of an ESP-NOW communication. It’s good that you were able to make corrections to the tutorial, so that all your readers now have a template that respects the implementation of the protocol.
Thanks for the reference too š
On my side, I’ve set up an ESP-NOW gateway to collect information from the sensors I spread around the house. I implemented it with an M5Stack so that I can display the collected information live on the TFT screen. And I also set up a web server on a Raspberry Pi to view the information remotely, with all the collection history. The M5Stack transmits the collected data to the Raspberry Pi through an HTTP API (which I implemented in PHP), which stores it in a database.
I also have a constellation of LIFX bulbs in the house. I placed an M5Stick-C with a PIR sensor at the entrance to detect people entering or leaving the house. For example, when someone enters, the sensor sends a signal to the M5Stack to turn on the lights in the house and then immediately goes to sleep. The M5Stack synchronizes its internal clock to an NTP server every hour and also retrieves the sunset time from a remote HTTP API. Based on the detected time of day, the M5Stack broadcasts the appropriate commands to the LIFX lights by issuing UDP packets that implement the proprietary LIFX protocol.
The use of the ESP-NOW protocol is ideal for communicating low-power nodes over a local area network. The range is better than WiFi and very fast. So the autonomy of the sensor network is greatly optimized.
Hi, I came across this discussion due to the fact that I had the same problem as Steph. Unfortunately after implementing the solution, I’m facing “delivery errors” on the sender side. Out of 10 retries i probably only have one success. This does not happen, If I do not connect to wifi and use ESP_NOW only connection.Ā
Any ideas what to look after?Ā
Thanks GuidoĀ
Hi Guido,
How did you initialize the WiFi interface of the receiving ESP32?
WiFi.mode(WIFI_MODE_STA);
or
WiFi.mode(WIFI_MODE_APSTA);
I plan to write a tutorial soon that explains how to solve the recurring problems that users encounter around the joint use of the ESP-NOW protocol on a gateway simultaneously connected to a WiFi router. You should be interested, but you’ll have to wait a little bit more š
Steph
Ok Guido.
You should know that in this mode, the ESP32 periodically enters a power saving mode and puts its radio communication circuit on standby. In other words, if your sender modules try to transmit their data via the ESP-NOW protocol while the receiver’s modem is in standby, the transmissions will inevitably fail. To avoid this, you can force the receiver to keep its radio circuit permanently powered:
WiFi.setSleep(WIFI_PS_NONE);
The disadvantage, of course, is that this is much more energy consuming. In other words, it is better to avoid powering the receiver on battery.
Try this, and everything should be fine š
Regards,
Steph
Hi Steph,
that was the trick! Now it works like a charm. The receiver anyway is always on power and only the sender is on battery. So more power consumption on the receiving side is not a problem.Ā
Thanks a lot
GuidoĀ