Page 1 of 1

espnow wifi channel setup with connection to lan.

Posted: Mon Nov 04, 2019 10:42 am
by ardcp32
arduino-esp32 1.0.4
Arduino ide 1.8.10

Just wondering if this is an acceptable way of finding the common channel
to be used by espnow.

Having used espnow with an earlier arduino-esp32 release, it was sufficient to do:[

Code: Select all

WiFi.mode(WIFI_STA);

WiFi.disconnect();

uint8_t primaryChan = 6;
wifi_second_chan_t secondChan = WIFI_SECOND_CHAN_NONE;
esp_wifi_set_channel(primaryChan, secondChan);

if (esp_now_init() == ESP_OK)
...
However, as I tried this using arduino-esp32 1.0.4 it did not work.
Looking through the error messages and the documentation, I found a solution.

I wanted to let the slave search for the master by changing channel
until a succesfull send response was received.

Using the esp_wifi_set_promiscuous call, I succeded like:

Code: Select all

ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
uint8_t primaryChan = 6;
wifi_second_chan_t secondChan = WIFI_SECOND_CHAN_NONE;
esp_wifi_set_channel(primaryChan, secondChan);

ESP_ERROR_CHECK(esp_wifi_set_promiscuous(false));

WiFi.disconnect();

if (esp_now_init() == ESP_OK)
..

To illustrate how to automatically configure the channel using the channel from the external AP,
below is a 'master' connecting to a local lan, setting the channel of the espnow STA.
And a 'slave' using the esp_wifi_set_channel and a message(token) to search for the 'master'

They are very crude, basic test programs just to show how the 'slave' can find the 'master'.
Long delays are used in order to make the steps easy to follow.

Here is the 'master' code used to test the search for master:
  1. /*
  2.      espnow master
  3. */
  4.  
  5. #include <esp_now.h>
  6. #include <WiFi.h>
  7. #include <esp_wifi.h>
  8.  
  9. #define WIFI_CHANNEL 10
  10. #define FIXED_CHANNEL       6
  11.  
  12. //Use custom MAC for both master and slave
  13. uint8_t CustomMac[] = {0xB4, 0xE6, 0x2D, 0xE9, 0xFE, 0x6E};        
  14. uint8_t slaveDeviceMac[] = {0x3C, 0x71, 0xBF, 0x03, 0x3D, 0x30};  
  15. const byte maxDataFrameSize = 200;
  16. uint8_t dataToSend[maxDataFrameSize];
  17. byte cnt = 0;
  18. int dataSent = 0;
  19.  
  20. esp_now_peer_info_t slave;
  21. const esp_now_peer_info_t *peer = &slave;
  22.  
  23. /*Put your SSID & Password*/
  24. const char* ssid = "<SSID>";  // Enter SSID here
  25. const char* password = "<Password>";  //Enter Password here
  26.  
  27. // Set your Static IP address
  28. IPAddress local_IP(192, 168, xx, xx);
  29. // Set your Gateway IP address
  30. IPAddress gateway(192, 168, xx, xx);
  31.  
  32. IPAddress subnet(255, 255, 255, 0);
  33. IPAddress primaryDNS(192, 168, xx, xx);   //optional
  34.  
  35.  
  36. void WiFiReset() {
  37.   WiFi.persistent(false);
  38.   WiFi.disconnect();
  39.   WiFi.mode(WIFI_OFF);
  40. }
  41.  
  42. void setup()
  43. {
  44.   Serial.begin(115200);
  45.   Serial.print("\r\n\r\n");
  46.   WiFiReset();
  47.  
  48.   WiFi.mode(WIFI_AP_STA );
  49.  
  50.   esp_wifi_set_mac(ESP_IF_WIFI_AP, &CustomMac[0]);
  51.  
  52.  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS)) {
  53.     Serial.println("STA Failed to configure");
  54.   }
  55.   Serial.println("Connecting to ");
  56.   Serial.println(ssid);
  57.  
  58.   //connect to your local wi-fi network
  59.   WiFi.begin(ssid, password, WIFI_CHANNEL);
  60.  
  61.   int maxTry = 10;
  62.   //check wi-fi is connected to wi-fi network
  63.   while (WiFi.status() != WL_CONNECTED && maxTry > 0 ) {
  64.     delay(1000);
  65.     Serial.print(".");
  66.     maxTry--;
  67.   }
  68.   Serial.println("");
  69.   Serial.println("WiFi connected..!");
  70.   Serial.print("Got IP: ");  Serial.println(WiFi.localIP());
  71.  
  72.   // This is the mac address
  73.   Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
  74.   Serial.print("Wifi channel: "); Serial.println(WiFi.channel());
  75.  
  76.     //Force espnow to use a specific channel
  77.   ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
  78.  
  79.   uint8_t primaryChan = WiFi.channel();
  80.   wifi_second_chan_t secondChan = WIFI_SECOND_CHAN_NONE;
  81.   esp_wifi_set_channel(primaryChan, secondChan);
  82.  
  83.   ESP_ERROR_CHECK(esp_wifi_set_promiscuous(false));
  84.  
  85.   //WiFi.disconnect();
  86.  
  87.   //Serial.print("Wifi Channel: "); Serial.println(WiFi.channel());
  88.  
  89.   if (esp_now_init() == ESP_OK) {
  90.     Serial.println("ESPNow Init Success!");
  91.   } else {
  92.     Serial.println("ESPNow Init Failed....");
  93.   }
  94.  
  95.   //Add the slave node to this master node
  96.   memcpy( &slave.peer_addr, &slaveDeviceMac[0], 6 );
  97.   slave.channel = WiFi.channel();
  98.   slave.encrypt = 0;
  99.   slave.ifidx = ESP_IF_WIFI_AP;
  100.  
  101.   if ( esp_now_add_peer(peer) == ESP_OK) {
  102.     Serial.println("Added Peer!");
  103.   }
  104.  
  105.   esp_now_register_recv_cb(OnDataRecv);
  106.   esp_now_register_send_cb(OnDataSent);
  107. }
  108.  
  109. void prntmac(const uint8_t *mac_addr) {
  110.   Serial.print("MAC Address: {0x");
  111.   for (byte i = 0; i < 6; ++i) {
  112.     Serial.print(mac_addr[i], HEX);
  113.     if (i < 5)
  114.       Serial.print(",0x");
  115.   }
  116.   Serial.println("};");
  117. }
  118.  
  119. void loop()
  120. {
  121.   yield();
  122. }
  123.  
  124. void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len)
  125. {
  126.   if (strncmp((const char *)data, "Calling Master",14) == 0 ) {
  127.         Serial.printf("\r\nReceived\t%d Bytes\t%s\n", data_len, data);
  128.     strcpy((char*)dataToSend, "Greeting from Master");
  129.  
  130.     esp_err_t sendResult = esp_now_send(slave.peer_addr, dataToSend,sizeof(dataToSend));
  131.     if (sendResult == ESP_OK) {
  132.       Serial.print("Success sendingS response");
  133.     } else if (sendResult == ESP_ERR_ESPNOW_NOT_INIT) {
  134.       // How did we get so far!!
  135.       Serial.println("ESPNOW not Init.");
  136.     } else if (sendResult == ESP_ERR_ESPNOW_ARG) {
  137.       Serial.println("Invalid Argument");
  138.     } else if (sendResult == ESP_ERR_ESPNOW_INTERNAL) {
  139.       Serial.println("Internal Error");
  140.     } else if (sendResult == ESP_ERR_ESPNOW_NO_MEM) {
  141.       Serial.println("ESP_ERR_ESPNOW_NO_MEM");
  142.     } else if (sendResult == ESP_ERR_ESPNOW_NOT_FOUND) {
  143.       Serial.println("Peer not found.");
  144.     }
  145.     else if (sendResult == ESP_ERR_ESPNOW_IF) {
  146.       Serial.println("Interface Error.");
  147.     } else {
  148.       Serial.printf("\r\nNot sure what happened\t%d", sendResult);
  149.     }
  150.   } else {
  151.         Serial.printf("\r\nReceived\t%d Bytes\t%d\n", data_len, data[0]);
  152.     }
  153. }
  154.  
  155. void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  156.   Serial.print("\r\nLast Packet Send Status:\t");
  157.   Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  158.     Serial.print("Data sent to ");
  159.   prntmac(mac_addr);
  160.   dataSent = 1; //Sent executed
  161. }
  162.  
And the 'slave' test code:
  1. /*
  2.      esp32now slave
  3. */
  4.  
  5. #include <esp_now.h>
  6. #include <WiFi.h>
  7. #include <esp_wifi.h>
  8.  
  9. #define HIGHEST_CHANNEL 13    //Set according to country
  10. #define LOWEST_CHANNEL  1
  11. #define FIXED_CHANNEL       6
  12.  
  13. //#define USE_FIXED_CHANNEL   //Uncomment for no channel search
  14.  
  15. //Use custom MAC for both master and slave
  16. uint8_t masterDeviceMac[] = {0xB4, 0xE6, 0x2D, 0xE9, 0xFE, 0x6E};  
  17. uint8_t CustomMac[] = {0x3C, 0x71, 0xBF, 0x03, 0x3D, 0x30};
  18. esp_now_peer_info_t master;
  19. const esp_now_peer_info_t *masterNode = &master;
  20. esp_err_t sendResult;
  21. const uint8_t maxDataFrameSize = 200;
  22. uint8_t dataToSend[maxDataFrameSize];
  23. byte cnt = 0;
  24. int dataSent = 0;
  25.  
  26. int wifi_channel = 1;
  27.  
  28. int ms_sleep = 0;
  29.  
  30. void WiFiReset() {
  31.   WiFi.persistent(false);
  32.   WiFi.disconnect();
  33.   WiFi.mode(WIFI_OFF);
  34.   delay(100);
  35. }
  36.  
  37.  
  38. void setup()
  39. {
  40.   Serial.begin(115200);
  41.   Serial.print("\r\n\r\n");
  42.  
  43.   WiFiReset();
  44.  
  45. #ifdef USE_FIXED_CHANNEL
  46.   uint8_t primaryChan = FIXED_CHANNEL;
  47. #else
  48.     for (uint8_t primaryChan = LOWEST_CHANNEL; primaryChan <= HIGHEST_CHANNEL; primaryChan++) {
  49. #endif
  50.  
  51.  
  52.   WiFi.mode(WIFI_STA);
  53.     esp_wifi_set_mac(ESP_IF_WIFI_STA, &CustomMac[0]);
  54.  
  55.   Serial.print("Current channel no: ");
  56.   Serial.println(primaryChan);
  57.  
  58.   Serial.println( WiFi.macAddress() );
  59.  
  60.   ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
  61.     wifi_second_chan_t secondChan = WIFI_SECOND_CHAN_NONE;
  62.   ESP_ERROR_CHECK(esp_wifi_set_channel(primaryChan, secondChan));
  63.   ESP_ERROR_CHECK(esp_wifi_set_promiscuous(false));
  64.  
  65.   WiFi.printDiag(Serial);
  66.  
  67.   WiFi.disconnect();
  68.  
  69.   Serial.print("New Wifi channel: "); Serial.println(WiFi.channel());
  70.  
  71.   if (esp_now_init() == ESP_OK) {
  72.     Serial.println("ESP NOW INIT!");
  73.   }
  74.   else {
  75.     Serial.println("ESP NOW INIT FAILED....");
  76.   }
  77.  
  78.   memcpy( &master.peer_addr, masterDeviceMac, 6 );
  79.   master.channel = primaryChan;
  80.   master.encrypt = 0;
  81.   master.ifidx = ESP_IF_WIFI_STA;
  82.  
  83. #ifdef USE_FIXED_CHANNEL
  84.   if ( esp_now_add_peer(masterNode) == ESP_OK) {
  85.     Serial.println("Added Peer!");
  86.   }
  87. #else
  88.   //Add node irst time, else  replace
  89.   if (primaryChan == LOWEST_CHANNEL) {
  90.     if ( esp_now_add_peer(masterNode) == ESP_OK) {
  91.       Serial.println("Added Peer!");
  92.     }
  93.   } else {
  94.     if (esp_now_mod_peer(masterNode) == ESP_OK) {
  95.       Serial.println("Modified Peer!");
  96.     }
  97.   }
  98. #endif
  99.  
  100.   esp_now_register_send_cb(OnDataSent);
  101.     esp_now_register_recv_cb(OnDataRecv);
  102.    
  103.   dataSent = 0;
  104.  
  105.   //Send test data
  106.   if ( TestSend() ) {
  107.  
  108.     //Wait for data sent confirmed
  109.     for (int i = 0; i < 1000; i++, ms_sleep--) {
  110.       delay(1);
  111.       yield();
  112.       if (dataSent != 0 ) {
  113.         break;                              //No data sent, try another channel
  114.       }
  115.     }
  116.     if (dataSent == 1 ) {
  117.       //Save channel to nvr/RTC mem ?
  118.       Serial.printf("Found Master on channel: %d\n", WiFi.channel());
  119. #ifndef USE_FIXED_CHANNEL
  120.       break;
  121. #endif
  122.     }
  123.   }
  124. #ifndef USE_FIXED_CHANNEL
  125.   delay(500);
  126. }
  127. #endif
  128. }
  129.  
  130. void loop()
  131. {
  132.   for (cnt = 0; cnt < maxDataFrameSize; cnt++) {
  133.     dataToSend[cnt]++;
  134.   }
  135.  
  136.   esp_err_t sendResult = esp_now_send(master.peer_addr, dataToSend, sizeof(dataToSend)); //maxDataFrameSize);
  137.     if (sendResult == ESP_OK) {
  138.         Serial.println("Send success");
  139.     } else if (sendResult == ESP_ERR_ESPNOW_NOT_INIT) {
  140.         // How did we get so far!!
  141.         Serial.println("ESPNOW not Init.");
  142.     } else if (sendResult == ESP_ERR_ESPNOW_ARG) {
  143.         Serial.println("Invalid Argument");
  144.     } else if (sendResult == ESP_ERR_ESPNOW_INTERNAL) {
  145.         Serial.println("Internal Error");
  146.     } else if (sendResult == ESP_ERR_ESPNOW_NO_MEM) {
  147.         Serial.println("ESP_ERR_ESPNOW_NO_MEM");
  148.     } else if (sendResult == ESP_ERR_ESPNOW_NOT_FOUND) {
  149.         Serial.println("Peer not found.");
  150.     }
  151.     else if (sendResult == ESP_ERR_ESPNOW_IF) {
  152.         Serial.println("Interface Error.");
  153.     }   else {
  154.         Serial.printf("\r\nNot sure what happened\t%d", sendResult);
  155.     }
  156.    
  157.   delay(2000);
  158. }
  159.  
  160. int TestSend() {
  161.  
  162.   strcpy((char*)dataToSend, "Calling Master");
  163.  
  164.     esp_err_t sendResult = esp_now_send(master.peer_addr, dataToSend, sizeof(dataToSend));
  165.     if (sendResult == ESP_OK) {
  166.         Serial.println("Send success");
  167.         return 1;
  168.     } else if (sendResult == ESP_ERR_ESPNOW_NOT_INIT) {
  169.         // How did we get so far!!
  170.         Serial.println("ESPNOW not Init.");
  171.     } else if (sendResult == ESP_ERR_ESPNOW_ARG) {
  172.         Serial.println("Invalid Argument");
  173.     } else if (sendResult == ESP_ERR_ESPNOW_INTERNAL) {
  174.         Serial.println("Internal Error");
  175.     } else if (sendResult == ESP_ERR_ESPNOW_NO_MEM) {
  176.         Serial.println("ESP_ERR_ESPNOW_NO_MEM");
  177.     } else if (sendResult == ESP_ERR_ESPNOW_NOT_FOUND) {
  178.         Serial.println("Peer not found.");
  179.     }
  180.     else if (sendResult == ESP_ERR_ESPNOW_IF) {
  181.         Serial.println("Interface Error.");
  182.     }   else {
  183.         Serial.printf("\r\nNot sure what happened\t%d", sendResult);
  184.     }
  185.   return 0;
  186. }
  187.  
  188. void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  189.   Serial.print("\r\nLast Packet Send Status:\t");
  190.   Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  191.   dataSent = (status == ESP_NOW_SEND_SUCCESS ? 1 : -1);
  192. }
  193.  
  194. void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
  195.     //Serial.printf("\r\nReceived\t%d Bytes\t%d\n", data_len, data[0]);
  196.   Serial.printf("\r\nReceived\t%d Bytes\t%s\n", data_len, data);
  197. }
  198.  

Re: espnow wifi channel setup with connection to lan.

Posted: Mon Jul 13, 2020 8:24 am
by gmag11
I was having the same problem. Thank you!!!