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)
...
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:
Code: Untitled.cpp Select all
/*
espnow master
*/
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#define WIFI_CHANNEL 10
#define FIXED_CHANNEL 6
//Use custom MAC for both master and slave
uint8_t CustomMac[] = {0xB4, 0xE6, 0x2D, 0xE9, 0xFE, 0x6E};
uint8_t slaveDeviceMac[] = {0x3C, 0x71, 0xBF, 0x03, 0x3D, 0x30};
const byte maxDataFrameSize = 200;
uint8_t dataToSend[maxDataFrameSize];
byte cnt = 0;
int dataSent = 0;
esp_now_peer_info_t slave;
const esp_now_peer_info_t *peer = &slave;
/*Put your SSID & Password*/
const char* ssid = "<SSID>"; // Enter SSID here
const char* password = "<Password>"; //Enter Password here
// Set your Static IP address
IPAddress local_IP(192, 168, xx, xx);
// Set your Gateway IP address
IPAddress gateway(192, 168, xx, xx);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(192, 168, xx, xx); //optional
void WiFiReset() {
WiFi.persistent(false);
WiFi.disconnect();
WiFi.mode(WIFI_OFF);
}
void setup()
{
Serial.begin(115200);
Serial.print("\r\n\r\n");
WiFiReset();
WiFi.mode(WIFI_AP_STA );
esp_wifi_set_mac(ESP_IF_WIFI_AP, &CustomMac[0]);
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS)) {
Serial.println("STA Failed to configure");
}
Serial.println("Connecting to ");
Serial.println(ssid);
//connect to your local wi-fi network
WiFi.begin(ssid, password, WIFI_CHANNEL);
int maxTry = 10;
//check wi-fi is connected to wi-fi network
while (WiFi.status() != WL_CONNECTED && maxTry > 0 ) {
delay(1000);
Serial.print(".");
maxTry--;
}
Serial.println("");
Serial.println("WiFi connected..!");
Serial.print("Got IP: "); Serial.println(WiFi.localIP());
// This is the mac address
Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
Serial.print("Wifi channel: "); Serial.println(WiFi.channel());
//Force espnow to use a specific channel
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
uint8_t primaryChan = WiFi.channel();
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();
//Serial.print("Wifi Channel: "); Serial.println(WiFi.channel());
if (esp_now_init() == ESP_OK) {
Serial.println("ESPNow Init Success!");
} else {
Serial.println("ESPNow Init Failed....");
}
//Add the slave node to this master node
memcpy( &slave.peer_addr, &slaveDeviceMac[0], 6 );
slave.channel = WiFi.channel();
slave.encrypt = 0;
slave.ifidx = ESP_IF_WIFI_AP;
if ( esp_now_add_peer(peer) == ESP_OK) {
Serial.println("Added Peer!");
}
esp_now_register_recv_cb(OnDataRecv);
esp_now_register_send_cb(OnDataSent);
}
void prntmac(const uint8_t *mac_addr) {
Serial.print("MAC Address: {0x");
for (byte i = 0; i < 6; ++i) {
Serial.print(mac_addr[i], HEX);
if (i < 5)
Serial.print(",0x");
}
Serial.println("};");
}
void loop()
{
yield();
}
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len)
{
if (strncmp((const char *)data, "Calling Master",14) == 0 ) {
Serial.printf("\r\nReceived\t%d Bytes\t%s\n", data_len, data);
strcpy((char*)dataToSend, "Greeting from Master");
esp_err_t sendResult = esp_now_send(slave.peer_addr, dataToSend,sizeof(dataToSend));
if (sendResult == ESP_OK) {
Serial.print("Success sendingS response");
} else if (sendResult == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW not Init.");
} else if (sendResult == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
} else if (sendResult == ESP_ERR_ESPNOW_INTERNAL) {
Serial.println("Internal Error");
} else if (sendResult == ESP_ERR_ESPNOW_NO_MEM) {
Serial.println("ESP_ERR_ESPNOW_NO_MEM");
} else if (sendResult == ESP_ERR_ESPNOW_NOT_FOUND) {
Serial.println("Peer not found.");
}
else if (sendResult == ESP_ERR_ESPNOW_IF) {
Serial.println("Interface Error.");
} else {
Serial.printf("\r\nNot sure what happened\t%d", sendResult);
}
} else {
Serial.printf("\r\nReceived\t%d Bytes\t%d\n", data_len, data[0]);
}
}
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
Serial.print("Data sent to ");
prntmac(mac_addr);
dataSent = 1; //Sent executed
}
Code: Untitled.cpp Select all
/*
esp32now slave
*/
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#define HIGHEST_CHANNEL 13 //Set according to country
#define LOWEST_CHANNEL 1
#define FIXED_CHANNEL 6
//#define USE_FIXED_CHANNEL //Uncomment for no channel search
//Use custom MAC for both master and slave
uint8_t masterDeviceMac[] = {0xB4, 0xE6, 0x2D, 0xE9, 0xFE, 0x6E};
uint8_t CustomMac[] = {0x3C, 0x71, 0xBF, 0x03, 0x3D, 0x30};
esp_now_peer_info_t master;
const esp_now_peer_info_t *masterNode = &master;
esp_err_t sendResult;
const uint8_t maxDataFrameSize = 200;
uint8_t dataToSend[maxDataFrameSize];
byte cnt = 0;
int dataSent = 0;
int wifi_channel = 1;
int ms_sleep = 0;
void WiFiReset() {
WiFi.persistent(false);
WiFi.disconnect();
WiFi.mode(WIFI_OFF);
delay(100);
}
void setup()
{
Serial.begin(115200);
Serial.print("\r\n\r\n");
WiFiReset();
#ifdef USE_FIXED_CHANNEL
uint8_t primaryChan = FIXED_CHANNEL;
#else
for (uint8_t primaryChan = LOWEST_CHANNEL; primaryChan <= HIGHEST_CHANNEL; primaryChan++) {
#endif
WiFi.mode(WIFI_STA);
esp_wifi_set_mac(ESP_IF_WIFI_STA, &CustomMac[0]);
Serial.print("Current channel no: ");
Serial.println(primaryChan);
Serial.println( WiFi.macAddress() );
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
wifi_second_chan_t secondChan = WIFI_SECOND_CHAN_NONE;
ESP_ERROR_CHECK(esp_wifi_set_channel(primaryChan, secondChan));
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(false));
WiFi.printDiag(Serial);
WiFi.disconnect();
Serial.print("New Wifi channel: "); Serial.println(WiFi.channel());
if (esp_now_init() == ESP_OK) {
Serial.println("ESP NOW INIT!");
}
else {
Serial.println("ESP NOW INIT FAILED....");
}
memcpy( &master.peer_addr, masterDeviceMac, 6 );
master.channel = primaryChan;
master.encrypt = 0;
master.ifidx = ESP_IF_WIFI_STA;
#ifdef USE_FIXED_CHANNEL
if ( esp_now_add_peer(masterNode) == ESP_OK) {
Serial.println("Added Peer!");
}
#else
//Add node irst time, else replace
if (primaryChan == LOWEST_CHANNEL) {
if ( esp_now_add_peer(masterNode) == ESP_OK) {
Serial.println("Added Peer!");
}
} else {
if (esp_now_mod_peer(masterNode) == ESP_OK) {
Serial.println("Modified Peer!");
}
}
#endif
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
dataSent = 0;
//Send test data
if ( TestSend() ) {
//Wait for data sent confirmed
for (int i = 0; i < 1000; i++, ms_sleep--) {
delay(1);
yield();
if (dataSent != 0 ) {
break; //No data sent, try another channel
}
}
if (dataSent == 1 ) {
//Save channel to nvr/RTC mem ?
Serial.printf("Found Master on channel: %d\n", WiFi.channel());
#ifndef USE_FIXED_CHANNEL
break;
#endif
}
}
#ifndef USE_FIXED_CHANNEL
delay(500);
}
#endif
}
void loop()
{
for (cnt = 0; cnt < maxDataFrameSize; cnt++) {
dataToSend[cnt]++;
}
esp_err_t sendResult = esp_now_send(master.peer_addr, dataToSend, sizeof(dataToSend)); //maxDataFrameSize);
if (sendResult == ESP_OK) {
Serial.println("Send success");
} else if (sendResult == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW not Init.");
} else if (sendResult == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
} else if (sendResult == ESP_ERR_ESPNOW_INTERNAL) {
Serial.println("Internal Error");
} else if (sendResult == ESP_ERR_ESPNOW_NO_MEM) {
Serial.println("ESP_ERR_ESPNOW_NO_MEM");
} else if (sendResult == ESP_ERR_ESPNOW_NOT_FOUND) {
Serial.println("Peer not found.");
}
else if (sendResult == ESP_ERR_ESPNOW_IF) {
Serial.println("Interface Error.");
} else {
Serial.printf("\r\nNot sure what happened\t%d", sendResult);
}
delay(2000);
}
int TestSend() {
strcpy((char*)dataToSend, "Calling Master");
esp_err_t sendResult = esp_now_send(master.peer_addr, dataToSend, sizeof(dataToSend));
if (sendResult == ESP_OK) {
Serial.println("Send success");
return 1;
} else if (sendResult == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW not Init.");
} else if (sendResult == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
} else if (sendResult == ESP_ERR_ESPNOW_INTERNAL) {
Serial.println("Internal Error");
} else if (sendResult == ESP_ERR_ESPNOW_NO_MEM) {
Serial.println("ESP_ERR_ESPNOW_NO_MEM");
} else if (sendResult == ESP_ERR_ESPNOW_NOT_FOUND) {
Serial.println("Peer not found.");
}
else if (sendResult == ESP_ERR_ESPNOW_IF) {
Serial.println("Interface Error.");
} else {
Serial.printf("\r\nNot sure what happened\t%d", sendResult);
}
return 0;
}
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
dataSent = (status == ESP_NOW_SEND_SUCCESS ? 1 : -1);
}
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
//Serial.printf("\r\nReceived\t%d Bytes\t%d\n", data_len, data[0]);
Serial.printf("\r\nReceived\t%d Bytes\t%s\n", data_len, data);
}