I have a project started that has an esp32 as a receiver bd. and several esp8266-01 as sending boards using espnow. All works great (following your instructions of course!) The next step was to be able to update the sending units OTA due to the number of boards (18) and access to those boards once installed. Using the BasicOTA example code I get delivery failures… Having the original working sketch and just adding : WiFi.begin(ssid,password); The failures are immediate and consistent. My question is how to have espnow communication and using OTA for updates?
Hi.
Have you tried any other OTA method?
For example: https://randomnerdtutorials.com/esp32-ota-over-the-air-arduino/
Does the receiver act also as a web server or it’s just an ESP-NOW receiver?
Regards
Sara
Hi Sara, The receiver is set with WiFi.mode(WIFI_AP_STA); I think the channels are different or the network changes. Right now if power up both units the espnow functions, sending data from remote to receiver. trying OTA update, it works the first time but then cannot find remote unit(channel or net changed from AP?) If I power down receiver then OTA functions flawlessly. I do not need to OTA the receiver only the remote sending units. I am not sure of your forum rules for posting code.But here is the receiver code
/*
Block Occupancy Detection Receiver board HomeBase
=======================================================================
10/29/22 11:12am works to receive data but cannot OTA update
Revision 0.1a jsl from Randomnerds tutorial online
ESP32 To receive data from occupancy detectors (esp8266-01's)
then ESP32 tracks those and set signals appropriately.
*/
#include WiFi.h
#include esp_now.h
const char* ssid = "mySSID";
const char* password = "mypassword";
IPAddress local_IP(192, 168, 0, 200); // Set your Static IP address
IPAddress gateway(192, 168, 0, 1); // Set your Gateway IP address
IPAddress subnet(255, 255, 0, 0);
IPAddress primaryDNS(8, 8, 8, 8); //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional
// uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0x07, 0x0D, 0x64};
int blk1 ;
int blk2 ;
int blk3 ;
int blk4 ;
int blk5 ;
int blk6 ;
int blk7 ;
int blk8 ;
int blk9 ;
int blk10 ;
// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
int id;
int blk1;
int blk2;
int resetPwr;
} struct_message;
// Create a struct_message called blkData
struct_message blkData;
// Create a structure to hold the readings from each board
struct_message board1;
struct_message board2;
struct_message board3;
struct_message board4;
struct_message board5;
// Create an array with all the structures
struct_message boardsStruct[36] = {board1, board2, board3, board4, board5};
// Callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac_addr, const uint8_t *incomingData, int len) {
char macStr[18];
Serial.print("Packet received from: ");
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.println(macStr);
memcpy(&blkData, incomingData, sizeof(blkData));
Serial.printf("Board ID %u: %u bytes\n", blkData.id, len);
// Update the structures with the new incoming data
boardsStruct[blkData.id - 1].blk1 = blkData.blk1;
boardsStruct[blkData.id - 1].blk2 = blkData.blk2;
Serial.printf("blk1 value: %d \n", boardsStruct[blkData.id - 1].blk1);
Serial.printf("blk2 value: %d \n", boardsStruct[blkData.id - 1].blk2);
Serial.println();
blk1 = boardsStruct[0].blk1; //A1
blk2 = boardsStruct[0].blk2; //A1
blk3 = boardsStruct[1].blk1; //A2
blk4 = boardsStruct[1].blk2; //A2
blk5 = boardsStruct[2].blk1; //A3
blk6 = boardsStruct[2].blk2; //A3
blk7 = boardsStruct[3].blk1; //A4
blk8 = boardsStruct[3].blk2; //A4
blk9 = boardsStruct[4].blk1; //A5
blk10 = boardsStruct[4].blk2; //A5
}
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
Serial.println("Booting");
// Configures static IP address
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure");
}
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_AP_STA); //***************
// WiFi.begin(ssid,password); //***************
Serial.print("Station IP Address: ");
Serial.println(WiFi.localIP());
Serial.print("Wi-Fi Channel: ");
Serial.println(WiFi.channel());
//Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_register_recv_cb(OnDataRecv);
Serial.println("Setup Complete...");
}
void loop() {
}
Here is sender code:
/*********
ESP8266-01 Remote Detection Board 10/29/22
Sends Detection data to homebase esp32 mac address
Revision 0.1a jsl from Randomnerds tutorial online
Change IP address according to board number
IP 201 = bd. A1
IP 202 = bd. A2
*****************************************************/
#include espnow.h
#include ESP8266WiFi.h
#include ESP8266mDNS.h
#include WiFiUdp.h
#include ArduinoOTA.h
const char* ssid = "mySSID"; // enter your ssid
const char* password = "myPassword"; // enter your password
IPAddress local_IP(192, 168, 0, 201); // Set your Static IP address
IPAddress gateway(192, 168, 0, 1); // Set your Gateway IP address
IPAddress subnet(255, 255, 0, 0);
IPAddress primaryDNS(8, 8, 8, 8); //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional
//**************************************************************************
// Variables to BD-1 or BD-2 to provide occupancy data or Block Power Data
//**********************************************************************************************************
// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0x0C, 0xB8, 0x15, 0xD8, 0xEB, 0xE4};// 0C:B8:15:D8:EB:E4 32C1
//**************************************************************************************************
// Set your Board ID (ESP8266-01 Sender #1 = BOARD_ID 1, ESP8266-01 Sender #2 = BOARD_ID 2, etc)
#define BOARD_ID 1 // Board using esp8266-01 A1
int OccupiedData1 = 0;
int OccupiedData2 = 0;
const int blockOccupancy1 = 2; // GPIO-0 esp-01 Pin 4
const int blockOccupancy2 = 0; // GPIO-2 esp-01 Pin 6
unsigned long debouncePeriod = 200; // debounce Period
// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
Serial.print("\r\nLast Packet Send Status: ");
if (sendStatus == 0) {
Serial.println("Delivery success");
}
else {
Serial.println("Delivery fail");
}
}
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
int id;
int blk1;
int blk2;
int resetPwr;
} struct_message;
// Create a struct_message called test to store variables to be sent
struct_message blkData;
void setup() {
Serial.begin(115200);
Serial.println("Booting");
// Configures static IP address
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure");
}
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
// Port defaults to 8266
// ArduinoOTA.setPort(8266);
// Hostname defaults to esp8266-[ChipID]
// ArduinoOTA.setHostname("myesp8266");
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_FS
type = "filesystem";
}
// NOTE: if updating FS this would be the place to unmount FS using FS.end()
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.begin();
//***************************************************************************************
pinMode(blockOccupancy1, INPUT_PULLUP); // pin 6 GPIO 2 as block occupancy Detected
digitalWrite(blockOccupancy1, LOW); //init to UnOccupied - off state
pinMode(blockOccupancy2, INPUT_PULLUP); // pin 4 GPIO 0 as output for power to block
digitalWrite(blockOccupancy2, LOW); //init to No Pwer to block - off state
//***************************************************************************************
// call ISR blockDetected when pin 6 GPIO-02 is brought low "Train In Block1"
attachInterrupt(digitalPinToInterrupt(blockOccupancy1), trainBlock1, FALLING);
// call ISR blockDetected when pin 4 GPIO-0 is brought low "Train In Block2"
attachInterrupt(digitalPinToInterrupt(blockOccupancy2), trainBlock2, FALLING);
//***************************************************************************************
Serial.print("Mac address = ");
Serial.println(WiFi.macAddress());
Serial.print("Station 1 IP Address: ");
Serial.println(WiFi.localIP());
Serial.print("Wi-Fi Channel: ");
Serial.println(WiFi.channel());
//***************************************************************************************
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Set ESP-NOW role
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
// Once ESPNow is successfully init, we will register for Send CB to
// get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
void loop() {
ArduinoOTA.handle();
delay(2000);
}
//************************************************************************************************************
ICACHE_RAM_ATTR void trainBlock1() {
static unsigned long lastInterrupt = 0;
unsigned long interruptTime = millis() ;
if (interruptTime - lastInterrupt > debouncePeriod) //debounce time
{
unsigned long debouncePeriodT ;
debouncePeriodT = interruptTime - lastInterrupt;
if (OccupiedData1 == 1) {
OccupiedData1 = 0;
blkData.blk1 = OccupiedData1;
blkData.id = BOARD_ID;
esp_now_send(0, (uint8_t *) &blkData, sizeof(blkData));
}
else
{
OccupiedData1 = 1;
blkData.blk1 = OccupiedData1;
blkData.id = BOARD_ID;
esp_now_send(0, (uint8_t *) &blkData, sizeof(blkData));
}
}
lastInterrupt = interruptTime;
}
/* ====================================================================================
==================================================================================== */
ICACHE_RAM_ATTR void trainBlock2() {
static unsigned long lastInterrupt = 0;
unsigned long interruptTime = millis() ;
if (interruptTime - lastInterrupt > debouncePeriod) //debounce time
{
// blockOccupied change
if (OccupiedData2 == 1) {
OccupiedData2 = 0;
blkData.blk2 = OccupiedData2;
blkData.id = BOARD_ID;
esp_now_send(0, (uint8_t *) &blkData, sizeof(blkData));
}
else
{
OccupiedData2 = 1;
blkData.blk2 = OccupiedData2;
blkData.id = BOARD_ID;
esp_now_send(0, (uint8_t *) &blkData, sizeof(blkData));
}
}
lastInterrupt = interruptTime;
}
Hi.
Yes. It’s probably related to the channels.
Make sure you use the same wi-fi channel for the receiver and sender so that they can exchange esp-now data.
That issue is addressed in the following tutorials:
- https://randomnerdtutorials.com/esp-now-auto-pairing-esp32-esp8266/
- https://randomnerdtutorials.com/esp8266-esp-now-wi-fi-web-server/
Check the snippets of code that set the Wi-Fi channel. You can set them manually, or add some code that searches for the Wi-Fi channel of the receiver and then, changes its channel to match. Both tutorials address that subject, but provide different solutions.
Regards,
Sara
Thank you for your quick response and pointing me in the correct direction. I’ll update with progress as I go along. Again Thanks
John
Hi All,
Sorry to say that it is not a channel mismatch. I followed the instructions on the tutorial.
and it has delivery failures when
WiFi.begin(ssid, password);
is not commented out.
Both are on the same channel and using static IP should be on same network. I do not have enough
experience with esp networking to figure this out myself. anyone Help
Hi again.
I really believe it is something to do with the Wi-Fi channel and Wi-Fi mode, but I can’t be sure.
There are other discussions about this issue online. See if you find something you think might help you solve the issue:
There’s also this discussion that might provide useful information: https://rntlab.com/question/esp8266-to-esp32-wifi-esp-now-problem/
I hope this helps.
Regards,
Sara
At the present moment it works for sending data via espnow and to do ota updates on the remotes, the ap_sta esp32 is powered down and ota works, which is a bit of a pain but workable. I suspect the ap sta is changing ip addresses from the static ones i set. Is that possible????