ESP32 won't receive data ESPNOW

I'm trying to send data from on ESP32 to another ESP32 via ESPNOW, but the receiving ESP32 is not receiving anything. Here is my code.

ESP32 Sender:

#include <Arduino.h>
#include <esp_now.h>
#include <WiFi.h>

uint8_t address[] = { 0x0C, 0xDC, 0x7E, 0x89, 0x4F, 0x84 };

touch_pad_t touchPin;
void callback() {}
void espnow_enable();

void setup()
{
    Serial.begin(115200);
}

void loop()
{
    WiFi.mode(WIFI_STA);
    espnow_enable();
    touchPin = esp_sleep_get_touchpad_wakeup_status();
    int touchData = 0;

    if(touchPin == 0) { touchData = 1; }

    else if(touchPin == 1) { touchData = 2; }

    else if(touchPin == 2) { touchData = 3; }

    else if(touchPin == 3) { touchData = 4; }

    else if(touchPin == 4) { touchData = 5; }

    else if(touchPin == 5) { touchData = 6; }

    else if(touchPin == 6) { touchData = 7; }

    else if(touchPin == 7) { touchData = 8; }

    else if(touchPin == 8) { touchData = 10; }

    else if(touchPin == 9) { touchData = 11; }

    else { touchData = 0; }

    esp_now_send(address, (uint8_t*) &touchData, sizeof(touchData));
    delay(25);
    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);
    delay(25);

    esp_sleep_enable_touchpad_wakeup();
    touchAttachInterrupt(T0, callback, 50);
    touchAttachInterrupt(T1, callback, 39);
    touchAttachInterrupt(T2, callback, 62);
    touchAttachInterrupt(T3, callback, 60);
    touchAttachInterrupt(T4, callback, 58);
    touchAttachInterrupt(T5, callback, 54);
    touchAttachInterrupt(T6, callback, 52);
    touchAttachInterrupt(T7, callback, 44);
    touchAttachInterrupt(T8, callback, 44);
    touchAttachInterrupt(T9, callback, 42);
    esp_deep_sleep_start();
}

void espnow_enable()
{
    WiFi.mode(WIFI_STA);
    delay(25);

    if(esp_now_init() != ESP_OK) { delay(25); return; }

    esp_now_peer_info_t peerInfo;
    memset(&peerInfo, 0, sizeof(peerInfo));
    memcpy(peerInfo.peer_addr, address, 6);
    peerInfo.channel = 0;
    peerInfo.encrypt = false;
  
    if(esp_now_add_peer(&peerInfo) != ESP_OK) { delay(25); return; }
    delay(25);
}

ESP32 Receiver:

#include <Arduino.h>
#include <WiFi.h>
#include <esp_now.h>

uint8_t address[] = {0x0C, 0xDC, 0x7E, 0x89, 0x4A, 0xCC};

void espnow_enable();
void espnow_receive(const uint8_t * mac, const uint8_t *data, int len);

void setup()
{
    Serial.begin(115200);
}

void loop()
{
   espnow_enable();
}

void espnow_enable() 
{
    WiFi.mode(WIFI_STA);
    delay(25);

    if(esp_now_init() != ESP_OK) { delay(25); return; }

    // esp_now_peer_info_t peerInfo;
    // memset(&peerInfo, 0, sizeof(peerInfo));
    // memcpy(peerInfo.peer_addr, address, 6);
    // peerInfo.channel = 0;
    // peerInfo.encrypt = false;

    // if(esp_now_add_peer(&peerInfo) != ESP_OK) { return; }
    // delay(25);

    esp_now_register_recv_cb(espnow_receive);
}

void espnow_receive(const uint8_t * mac, const uint8_t *data, int len)
{
    int * messagePointer = (int*)data;
    if(*messagePointer != 0)
    {
        Serial.println(*messagePointer);
    }

    else
    {
        Serial.println("Nothing");
    }
}

(There is nothing else hooked up to these ESP32's beside power)

Is there some code to tell me if all the wifi and bluetooth radio things are working properly. Thanks for your time.

Where did your sample code come from?

One source:
Getting Started with ESP-NOW (ESP32 with Arduino IDE) | Random Nerd Tutorials

I wrote it in vscode, I use the platformIO extension. I already looked at Random Nerd Tutorials, could not find anything about my issue.

Try using the ArduinoIDE and the code from the linked Tutorial.
When things do not work as expected, it is important to drop back to known working code and the ArduinoIDE ... later if you have IDE issues, at least you have an idea of where to start applying effort.

I also strongly suggest watching the YouTube video.

1 Like

@mrburnette,

VSCode with platformIO has worked before when I was using ESPNOW.

I have already watched multiple.

On my ESP32 I have a heatsink on top of it to keep it cool, do you think this would affect my ESP32 wifi and bluetooth radios.

The heatsink will not keep it from enumerating unless something shorted and caused a catastrophic failure.

As you have multiple boards, try each independently starting with a blink sketch then with something more complex.

And do try the tutorial code.

@mrburnette,

Both of the boards are able to run code and use GPIO pins properly, but the wifi and bluetooth radios are still not working.

Did you attempt to connect to your AP/WiFi router with a sketch?

If the hardware is correct then you really need to go to a set of tutorial code known to work and test your configuration. Then go off on with coding in another IDE. You must establish a baseline.

1 Like

Your sender-code uses deep-sleep.

You shouldn't combine deep-sleep and ESP-NOW in the first step.
Here is a democode for Tx-Rx with ESP-NOW between two ESP32

Inside this democode you must adjust the MAC-Adress to your boards

always the MAC-Adress of the receiver

This demo-code has a lot of serial-output to make it easier to narrow down bugs

// at the end of this file there is an explanation that uses an analogy with 
// sending / receiving postal letters to explain the several parts of ESP-NOW
// so if you would like to have an easy to understand overview read this
// explanation first.

#include <WiFi.h>
#include <esp_now.h>

// For sending / receiving ESP-NOW-data on both sides sender and receiver
// a structured variable has to be defined with the EXACT SAME structure

// the information that shall be sended/received is transmitted bytewise
// the ESP-NOW-functions know nothing about what the bytes mean
// it just transfers a specified number of bytes
// If the structures do not match 100% the data gets MIS-interpreted on the receiver-side
// in this demo-code a structure with an Array Of Char and an integer is used
// it is defined as follows

// ESP-NOW data-structure-definition
typedef struct MyESP_NOW_Data_type {
  char MyESP_NOW_MsgStr[128];
  int  MyESP_NOW_Int;
} MyESP_NOW_Data_type;

// After defining the structure two variables 
// one for receiving one for sending data
// this demo wants to demonstrate send AND receive in both directions
MyESP_NOW_Data_type my_received_ESP_NOW_Data;      
MyESP_NOW_Data_type my_READYtoSEND_ESP_NOW_Data;   


//#############################################################################################
// list of MAC-Adresses of all receivers:

// important note: ESP-NOW sending is based on the RECEIVERS Mac-adress.
// this means for every ESP-modul that shall receive a ESP-NOW-Messages
// you have to execute register a peer in the Setup-function

// Mac-Adress must be stored in an array of uint8_t
uint8_t ESP_NOW_MAC_adrOfRecv[] = { 0xF4, 0xCF, 0xA2, 0xD1, 0x3D, 0x28 }; // Board 0x06 sendet an Board 0x28
uint8_t broadcastAddress[]      = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };


char MAC_adrOfRecv_as_AoC[18];
//##############################################################################################

//ESP_NOW_functions

// callback function that will be executed when data is received
// Parameters:
// mac:          mac-adress of sender
// incomingData: the bytes that are received
// NoOfBytesRcv: number of bytes received

//void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t NoOfBytesRcv) { 
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int NoOfBytesRcv) {
  // copy data bytewise from variable incomingData to variable my_received_ESP_NOW_Data
  memcpy(&my_received_ESP_NOW_Data, incomingData, sizeof(my_received_ESP_NOW_Data));

  Serial.print("No of Bytes received: ");
  Serial.println(NoOfBytesRcv);

  //these lines must match the variables inside the ESP_NOW-data-structure
  Serial.print("Array of Char: #"); // leading "#"
  Serial.print(my_received_ESP_NOW_Data.MyESP_NOW_MsgStr);
  Serial.println("#"); // trailing "#" makes it easy to see which bytes where received
  
  Serial.print("Int: ");
  Serial.println(my_received_ESP_NOW_Data.MyESP_NOW_Int);

  Serial.println();
}


// callback when data is sent. Gets executed when sending data has finished
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  if (status == ESP_NOW_SEND_SUCCESS) {    
    Serial.println("OnDataSent says 'Delivery Success'");
  }
  else {
    Serial.println("OnDataSent says 'Delivery Failed'");
  }  
}

// attention! for some unknown strange reasons the variable 
// for the peer-info has to be global otherwise you will 
// get the error "ESPNOW: Peer Interface is invalid"
esp_now_peer_info_t MyPeerInfo; 

void ESP_Now_setup() {
  WiFi.mode(WIFI_STA);
  Serial.println("WiFi.mode(WIFI_STA); done");
  WiFi.disconnect(); // for strange reasons WiFi.disconnect() makes ESP-NOW work
  Serial.println("WiFi.disconnect(); done");
  
  // Init ESP-NOW  
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }  
  Serial.println("esp_now_init() was successful");
    
  // register callback-function that will be executed each time 
  // function esp_now_send() has finished
  esp_now_register_send_cb(OnDataSent);
  Serial.println("esp_now_register_send_cb(OnDataSent); done");
  
  // register callback-function that will be executed each time
  // ESP-NOW-Data is received
  esp_now_register_recv_cb(OnDataRecv);  
  Serial.println("esp_now_register_recv_cb(OnDataRecv); done");

  // the ESP-NOW-Sender needs to "fill out" a list with informations about each receiver
  // this is called peer. Therefore you have to create a variable of type esp_now_peer_info_t
  //esp_now_peer_info_t MyPeerInfo;
  // then "fill out" peer-data-form
  memcpy(MyPeerInfo.peer_addr, ESP_NOW_MAC_adrOfRecv, 6);
  MyPeerInfo.channel = 0;  
  MyPeerInfo.encrypt = false;
  
  // after setting up peer-info, add peer        
  if (esp_now_add_peer(&MyPeerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  Serial.println("esp_now_add_peer(&peerInfo) was successful");
  // this setup peer-info and add peer has to be repeated for each receiver 
  // that shall receive from this sender

  for (int i = 0;   i < 6;  i++) {
    strcat (MAC_adrOfRecv_as_AoC, hex02str(ESP_NOW_MAC_adrOfRecv[i])   );
    if (i < 6) {
      strcat (MAC_adrOfRecv_as_AoC, ":" );    
    }  
  }  
  MAC_adrOfRecv_as_AoC[17] = 0;
  strupr(MAC_adrOfRecv_as_AoC); // make letters UPPERCASE
  Serial.print("MAC-Adress of Receiver is ");
  Serial.println(MAC_adrOfRecv_as_AoC);
}


void ESP_NOW_SendData()
{
  // Set values to send
  strcpy(my_READYtoSEND_ESP_NOW_Data.MyESP_NOW_MsgStr, "HI I'M SENDING EVERY TWO SECONDS COUNTiNG UP + 6");
  my_READYtoSEND_ESP_NOW_Data.MyESP_NOW_Int = my_READYtoSEND_ESP_NOW_Data.MyESP_NOW_Int + 6; 

  // Send message via ESP-NOW  
  esp_now_send(ESP_NOW_MAC_adrOfRecv, (uint8_t *) &my_READYtoSEND_ESP_NOW_Data, sizeof(my_READYtoSEND_ESP_NOW_Data));
  Serial.println("esp_now_send(ESP_NOW_MAC_adrOfRecv, (uint8_t *) &my_READYtoSEND_ESP_NOW_Data, sizeof(my_READYtoSEND_ESP_NOW_Data)); done");
  Serial.print("I am the board with the MAC-Adress ");
  Serial.println(WiFi.macAddress()); 
  Serial.print("and I try to send my ESP-NOW-Data to the board with MAC-Adress ");
  Serial.println(MAC_adrOfRecv_as_AoC); 
  
  // if sending has finished function OnDataSent is called
}


/* nonblocking timing based on millis()
this function returns true each time the TimePeriod has expired and immediately 
starts a new TimePeriod. So this function
example-use:
unsigned long myTimer;

  if (TimePeriodIsOver( myTimer,2000) ) {
    //the code here gets executed only every 2000 Milliseconds
  }  
*/  
boolean TimePeriodIsOver (unsigned long &expireTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - expireTime >= TimePeriod )
  {
    expireTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  } 
  else return false;            // not expired
}

unsigned long SendDataTimer;

/*
everytime the compiler compiles the file new 
the macros named "__FILE__",  "__DATE__", "__TIME__"  
where replaced with what their names say  Filename with path
Date and time of the Computer the IDE is running on 
// so by simply starting the device the uploaded code yells filename date and time at the serial interface
*/
void PrintWiFiMacAdress()
{
  char MacAdr_AoC[18];  //suffix _AoC for easier remembering variable-type is ArrayOfChar
  char HexByteDigits[3];
  
  for (uint8_t i = 0; i < 18; i = i + 1)
  { 
    MacAdr_AoC[i] = WiFi.macAddress()[i];
  } 
  MacAdr_AoC[17] = 0; // zero to terminate the string
  Serial.print("ESP Board Wifi.macAddress:  ");
  Serial.println(MacAdr_AoC);
  
  Serial.println();
  Serial.println("copy the line below and replace the codeline");
  Serial.println("uint8_t ESP_NOW_MAC_adrOfRecv[] = { .... };");
  Serial.println("inside the code with the copied line from the serial monitor");
   
  Serial.println();
  Serial.print("uint8_t ESP_NOW_MAC_adrOfRecv[] = {");
  for (uint8_t i = 0; i < 16; i = i + 3)
  { 
    HexByteDigits[0] = MacAdr_AoC[i];
    HexByteDigits[1] = MacAdr_AoC[i+1];
    HexByteDigits[2] = 0; // zero for terminating the string
    Serial.print("0x");
    Serial.print(HexByteDigits);
    if (i < 14) Serial.print(", ");
  }  
  Serial.println(" };");
  Serial.println();      
}

char* hex02str(uint8_t b)  {
 static char str[]="FF"; // RAM für einen 2-Zeichen string reservieren.
  snprintf(str,sizeof(str),"%02x",b);
  return str;
}


void PrintFileNameDateTime()
{
  Serial.print("Code running comes from file ");
  Serial.println(__FILE__);
  Serial.print(" compiled ");
  Serial.print(__DATE__);
  Serial.print("  ");
  Serial.println(__TIME__);  
}

  
void setup() {
  // Init Serial Monitor
  Serial.begin(115200);
  Serial.println();  // a carriage return to make sure serial-output begins in colum 1 of a new line
  PrintFileNameDateTime();
  ESP_Now_setup();

  PrintWiFiMacAdress();  

}

void loop() {
  // check if timer-intervall is over
  if (TimePeriodIsOver(SendDataTimer,2000) )  
    {
     Serial.println("SendData");
     ESP_NOW_SendData();
     Serial.println("SendData done");
    }

}

// explanation how ESP-NOW works:
// sending serial data is as easy as

// Serial.begin(baudrate);
// Serial.print("Hello World");

// This can be coded so easy because a lot of things are fixed
// IO-Pins used by Serial fixed
// Connection to other device: made of wire must not be programmed
// standard serial-connection does not care if receiver is connected
// send data and that's all

// with ESP-NOW more things are NOT fixed = are adjustable and MUST be adjusted
// the receiver is NOT defined by wire but through his MAC-Adress

// Data-transport can do only transporting one or multiple bytes
// That's not a real problem the user can define his own data-pattern (data-structure)

// ESP-NOW offers feedback if a datatransmission was successful or failed

// each ESP-modul can receive data from different senders 
// so an information from WHICH sender the data was sended is useful
// this is identified by the senders MAC-Adress

// Analogy sending / receiving postal letters:

// if you want to SEND out a letter to somebody you have to write 
// the receivers adress on the envelope. 
// similar thing with ESP-NOW: the data is NOT guided by a wire its sended "Up in the air" 
// with ESP-NOW this receiver-adress is the MAC-Adress of the receiver

// if the postman brings you a letter you don't have to be at home. He will put the letter
// into your letter-box and you can pick it out later.

// similar thing with ESP-NOW: there is some kind of "letter-box" the received data will be stored into
// the data-receiving into the "letter-box" runs in the backround similar to an interrupt
// The received data will be catched up and must be copied into some kind of "letterbox"

// any transporting service has some kind of procedure if you want to send a package or a letter
// fill out some kind of form (on paper or onnline) print out and glue a sticker 
// with the transporting informations on the package/envelope put the package / envelope into the
// "send out" box or bring it to a pickup store

// so there are some things to do:

// - build a special designed "package" with multiple special designed compartments
//   where all parts of the data has its own compartment 
//   defining a new variable type "structure"

// - build a "letter-box" designed expecially for the user-defined package 
//   and "mount it in front of your house" so it can be easily found by the postman

// - write a list with receiver-adresses and handover this list to ESP-NOW (the "letter-department" of your "company"

// - setup if data shall be encrypted or not

// - setup transmission channel that shall be used for sending the data wireless

// - design your "sending-form"

// these are the reasons why ESP-NOW needs a bit more than just
// Serial.begin(baudrate);
// Serial.print("My Data");

// Your mobile phone has a lot of functions. It took you some time to learn them all
// Same thing with ESP-NOW it will take some time to learn it

// if you want it fully automated without learning anything 
// use Alexa, Siri or google assistant instead

Be the change you want to see in the world
best regards Stefan

@StefanL38,

I have tested my code with other boards and they work alright. I tested my ESP32 wifi radio by trying to connect to my router. It did not connect, so I think my ESP32 module is defective. I think replacing the ESP32 module for a new should work.

Did you test with a small demo-code that creates an AccessPoint?
If you scan for WLAN with your smartphone ore computer the SSID should show up

#include <WiFi.h>

const char* ssid     = "ESP32-Access-Point";
const char* password = "123456789";

#define LED_on  HIGH
#define LED_off LOW

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String onBoard_LEDState = "off";
String output27State = "off";

// Assign output variables to GPIO pins
const int onBoard_LED = 2;
const int output27 = 27;

void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(onBoard_LED, OUTPUT);
  pinMode(output27, OUTPUT);
  // Set outputs to LOW
  digitalWrite(onBoard_LED, LED_off);
  digitalWrite(output27, LOW);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Setting AP (Access Point)…");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);
  
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            
            // turns the GPIOs on and off
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 on");
              onBoard_LEDState = "on";
              digitalWrite(onBoard_LED, LED_on);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 off");
              onBoard_LEDState = "off";
              digitalWrite(onBoard_LED, LED_off);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);
            }
            
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");
            
            // Web Page Heading
            client.println("<body><h1>ESP32 Web Server</h1>");
            
            // Display current state, and ON/OFF buttons for GPIO 26  
            client.println("<p>on Board LED - State " + onBoard_LEDState + "</p>");
            // If the onBoard_LEDState is off, it displays the ON button       
            if (onBoard_LEDState == "off") {
              client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 
               
            // Display current state, and ON/OFF buttons for GPIO 27  
            client.println("<p>GPIO 27 - State " + output27State + "</p>");
            // If the output27State is off, it displays the ON button       
            if (output27State == "off") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");
            
            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

Be the change you want to see in the world
best regards Stefan

1 Like

Hi Stefan, I have been trying to get ESP-NOW as well as WiFi working but with no luck. Does your statement suggest that they are not usable together?

another user reported that he successfully used both together. If I remember right a pre-condition is to adjust the WiFi-channel that ESP-NOW and WiFi are using the same WiFi-channel.

best regards Stefan

I've tried swapping channels but so far no luck.
Thanks for your help.

Best Regards
Len

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.