Esp32 espnow+wifi

Hello, I want to send data from one ESP to another ESP via ESP-NOW and display the data, date, and time on an ILI9341 screen. My first attempt was with two ESP8266 boards (both NodeMCU), and everything worked well. The data was sent, and the date and time were updated via Ethernet.

Later, I decided to add a CO2 sensor to my receiver. After adding the sensor, I encountered problems because the program had to wait for data from the sensor. While waiting, the program crashed due to RAM issues.

So, I bought an ESP32 (NodeMCU), but I'm unable to use ESP-NOW and WiFi simultaneously. Has anyone else experienced this problem? Or I am just retardet?

Have a look here:

It's not possible to answer your question you have not provided the source code and relevant serial output all in code tags nor the wiring diagrams of the failing setup.
What proof do you have of 'RAM issues'
You might want to read the pinned post re 'How to get the best from the forum', then read one or more of the tutorials on State machines and on doing multiple things at the same time.

the above statement shows a major misunderstanding on your part. The Nerds tutorial on ESP-NOW will be useful.

Hi I don't attach anything because I am new user and I am not able to upload. If you want I can send you the code as txt file.

AFAIK, you just use the button ^^ to post your code. Please use Tools/Auto Format first

so here is code for sender :

#include <espnow.h>
#include <ESP8266WiFi.h>
#include <Adafruit_AHT10.h>
#include "MS5611.h"

const char* targetSSID = "xxx";

uint8_t broadcastAddress[] = { 0x14, 0x08, 0x08, 0xA4, 0xFB, 0xEC };  //{0xC4, 0x5B, 0xBE, 0xF3, 0x5A, 0x7B}; 

typedef struct struct_message {
  float teplota;
  float vlhkost;
  float tlak;
} struct_message;

struct_message myData;

Adafruit_AHT10 aht;
MS5611 MS5611(0x77);

void OnDataSent(uint8_t* mac_addr, uint8_t sendStatus) {
  Serial.print("Status odosielania: ");
  if (sendStatus == 0) {
    Serial.println("Uspešne");
  } else {
    Serial.println("Neuspešne");
  }
}

int getWiFiChannel(const char* ssid) {
  int n = WiFi.scanNetworks();
  for (int i = 0; i < n; ++i) {
    if (WiFi.SSID(i) == ssid) {
      return WiFi.channel(i);
    }
  }
  return 1;  // default channel
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  Serial.println(WiFi.macAddress());

  int channel = getWiFiChannel(targetSSID);
  Serial.print("Nastavený Wi-Fi kanál: ");
  Serial.println(channel);

  if (esp_now_init() != 0) {
    Serial.println("Chyba inicializacie ESP-NOW");
    return;
  }

  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, channel, NULL, 0);
  esp_now_register_send_cb(OnDataSent);

  if (!aht.begin()) {
    Serial.println("Could not find AHT10? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHT10 found");

  Wire.begin();
  if (MS5611.begin() == true) {
    Serial.print("MS5611 found: ");
    Serial.println(MS5611.getAddress());
  } else {
    Serial.println("MS5611 not found. halt.");
    //  while (1);
  }
}

void loop() {
  sensors_event_t humidity, temp;
  aht.getEvent(&humidity, &temp); 

  MS5611.read();
  myData.teplota = temp.temperature;
  myData.vlhkost = humidity.relative_humidity;
  myData.tlak = MS5611.getPressure();

  esp_now_send(broadcastAddress, (uint8_t*)&myData, sizeof(myData));

  delay(5000);
}

and here is code for reciever:

#include <esp_now.h>
#include <WiFi.h>
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include <time.h>
#include <Wire.h>
#include <DFRobot_SCD4X.h>

#define TFT_DC 5
#define TFT_CS 2

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

DFRobot_SCD4X SCD4X(&Wire, SCD4X_I2C_ADDR);

const char* ssid = "xxx";
const char* password = "xxxx";

IPAddress staticIP(192, 168, 1, 43);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 4, 4);

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 3600; 
const int   daylightOffset_sec = 3600; 

typedef struct struct_message {
  float teplota;
  float vlhkost;
  float tlak;
} struct_message;

struct_message incomingData;

unsigned long lastTimeUpdate = 0;
const long timeUpdateInterval = 1000; 

unsigned long lastSCD4XUpdate = 0;
const long scd4xUpdateInterval = 5000; 

volatile bool newDataReceived = false; 

void drawExternalData();
void drawInternalData(float temp, float humidity, int co2);
void drawCurrentTime();
void readSCD4XData();


void OnDataRecv(const esp_now_recv_info_t *mac_info, const uint8_t *incomingData_raw, int len) {

  memcpy(&incomingData, incomingData_raw, sizeof(incomingData));

  char macStr[18];
  Serial.print("Sprava prisla od: ");

  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_info->des_addr[0], mac_info->des_addr[1], mac_info->des_addr[2], 
           mac_info->des_addr[3], mac_info->des_addr[4], mac_info->des_addr[5]);
  Serial.println(macStr);

  newDataReceived = true;
}

TaskHandle_t inData;
 
void setup() {

  Serial.begin(115200);


 WiFi.mode(WIFI_AP_STA);

 if (!WiFi.config(staticIP, gateway, subnet, primaryDNS)) {
    Serial.println("Nepodarilo sa nastavit staticku IP adresu!");
  }

  WiFi.begin(ssid, password);
  Serial.print("Pripajam sa na WiFi...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("Pripojené!");
  Serial.print("Wi-Fi Channel: ");
  Serial.println(WiFi.channel());


  if (esp_now_init() != ESP_OK) {
    Serial.println("Error pri inicializacii ESP-NOW");
    return;
  }

  esp_now_register_recv_cb(OnDataRecv);

  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

  while( !SCD4X.begin() ){
    Serial.println("Communication with device failed, please check connection");
    delay(3000);
  }


  SCD4X.enablePeriodMeasure(SCD4X_STOP_PERIODIC_MEASURE);

  tft.begin();
  tft.setRotation(3);
  tft.fillScreen(ILI9341_WHITE);
  tft.setTextSize(2);
  
  tft.drawRect(15, 30, 130, 120, ILI9341_BLACK);
  tft.drawTriangle(5, 30, 155, 30, 80, 0, ILI9341_BLACK);

   xTaskCreatePinnedToCore(
                    inDatacode,   /* Task function. */
                    "inData",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    1,           /* priority of the task */
                    &inData,      /* Task handle to keep track of created task */
                    0);          /* pin task to core 0 */                  
  delay(500);
  
  Serial.println("Setup hotovy.");
}


  void inDatacode( void * pvParameters ){
  Serial.print("Task1 running on core ");
  Serial.println(xPortGetCoreID());

  for(;;){
    if (millis() - lastSCD4XUpdate >= scd4xUpdateInterval) {
    lastSCD4XUpdate = millis();
    readSCD4XData();
  }
  } 
}
 
void loop() {

  if (newDataReceived) {
    drawExternalData();
    newDataReceived = false;
  }

  if (millis() - lastTimeUpdate >= timeUpdateInterval) {
    lastTimeUpdate = millis();
    drawCurrentTime();
  }

}

void readSCD4XData() {

  SCD4X.measureSingleShot(SCD4X_MEASURE_SINGLE_SHOT);

  while (!SCD4X.getDataReadyStatus()) {
    delay(100); 
  }
  
  DFRobot_SCD4X::sSensorMeasurement_t data;
  SCD4X.readMeasurement(&data);
  drawInternalData(data.temp, data.humidity, data.CO2ppm);
  Serial.println("Precital som vnutorne data.");
}

void drawExternalData() {
  tft.fillRect(180, 50, 102, 16, ILI9341_WHITE);
  tft.setCursor(180, 50);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(2);
  tft.print(incomingData.teplota);
  tft.print(" "); tft.print(char(247)); tft.print("C");

  tft.fillRect(180, 80, 102, 16, ILI9341_WHITE);
  tft.setCursor(180, 80);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(2);
  tft.print(incomingData.vlhkost);
  tft.print(" %");
  
  tft.fillRect(180, 110, 102, 16, ILI9341_WHITE);
  tft.setCursor(180, 110);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(2);
  tft.print(incomingData.tlak);
  tft.print(" hPa");
}

void drawInternalData(float temp, float humidity, int co2) {
  tft.fillRect(40, 50, 80, 16, ILI9341_WHITE);
  tft.setCursor(40, 50);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(2);
  tft.print(temp);
  tft.print(" "); tft.print(char(247)); tft.print("C");

  tft.fillRect(40, 80, 102, 16, ILI9341_WHITE);
  tft.setCursor(40, 80);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(2);
  tft.print(humidity);
  tft.print(" %");

  tft.fillRect(40, 110, 102, 16, ILI9341_WHITE);
  tft.setCursor(40, 110);
  if (co2 <= 800) {
    tft.setTextColor(ILI9341_GREEN);
  } else if (co2 > 800 && co2 <= 1200) {
    tft.setTextColor(ILI9341_YELLOW);
  } else if (co2 > 1200 && co2 <= 1800) {
    tft.setTextColor(ILI9341_ORANGE);
  } else {
    tft.setTextColor(ILI9341_RED);
  }
  tft.setTextSize(2);
  tft.print(co2);
  tft.print(" ppm");
}

void drawCurrentTime() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    return;
  }
  
  char timeString[9];
  strftime(timeString, sizeof(timeString), "%H:%M:%S", &timeinfo);

  char dateString[11];
  strftime(dateString, sizeof(dateString), "%d.%m.%Y", &timeinfo);

  int textWidthTime = strlen(timeString) * 18;
  int textWidthDate = strlen(dateString) * 18;

  int xPosTime = (tft.width() - textWidthTime) / 2;
  int xPosDate = (tft.width() - textWidthDate) / 2;

  int yPosTime = 160;
  int yPosDate = 190;
  
  tft.fillRect(xPosTime, yPosTime, textWidthTime, 24, ILI9341_WHITE);
  tft.setCursor(xPosTime, yPosTime);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(3);
  tft.print(timeString);
  Serial.println(timeString);

  tft.fillRect(xPosDate, yPosDate, textWidthDate, 24, ILI9341_WHITE);
  tft.setCursor(xPosDate, yPosDate);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(3);
  tft.print(dateString);
  Serial.println(dateString);
}

so when I delete this:

WiFi.begin(ssid, password);
  Serial.print("Pripajam sa na WiFi...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("Pripojené!");

from reciever setup esp get data from another esp via esp now.

ESP-NOW requires WiFi, it can't work without it.

Sorry, I am not following. You need to explain better and show the serial output if there is any.

Which esp_now examples are you using?

I use same as is on the tutorial wich is in coment. About serial output if I don't inicialize the WiFi then in serial I saw: Esp Now data are recieve. But when i inicilize WiFi its lok like ESP ignor the ESP NOW and i got onli time and date form NTP server.

So we're on the same page: using WiFi in the usual way, by connecting to an Access Point via its SSID and an optional password, is not required to use ESP-Now. However, because ESP-Now requires that all peers are on the same channel, it's a convenient way to achieve that.

ESP-Now itself is "connection-less": you send directly to a given MAC or MACs; or do a broadcast to everything in range.

I can corroborate that if you call WiFi.begin for whatever reason, if you later want ESP-Now to work, you may have to call WiFi.disconnect first. Otherwise, things would start to flake then fail. This was an issue on a project of mine; turned out disconnecting was not going to be an issue, so fine. Didn't spend more time trying to figure it out. (This was on v2 of the esp32 board core, though; v3 has been out for a while now.)

If you want to run something like that tutorial with both ESP-Now and "regular" WiFi, then that would be a problem.

Follow the examples. Leave out the WiFi.begin.

So I made one change. In the end of setup I put WiFi.disconnect(); and in drawCurrentTime() class I make little update, in the beginning i connect to WiFi and in the end I disconnect from WiFi and it is work.

void drawCurrentTime() {
  
  WiFi.begin(ssid, password);
  Serial.print("Pripajam sa na WiFi...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    return;
  }
  
  char timeString[9];
  strftime(timeString, sizeof(timeString), "%H:%M:%S", &timeinfo);

  char dateString[11];
  strftime(dateString, sizeof(dateString), "%d.%m.%Y", &timeinfo);

  int textWidthTime = strlen(timeString) * 18;
  int textWidthDate = strlen(dateString) * 18;

  int xPosTime = (tft.width() - textWidthTime) / 2;
  int xPosDate = (tft.width() - textWidthDate) / 2;

  int yPosTime = 160;
  int yPosDate = 190;
  
  tft.fillRect(xPosTime, yPosTime, textWidthTime, 24, ILI9341_WHITE);
  tft.setCursor(xPosTime, yPosTime);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(3);
  tft.print(timeString);
  Serial.println(timeString);

  tft.fillRect(xPosDate, yPosDate, textWidthDate, 24, ILI9341_WHITE);
  tft.setCursor(xPosDate, yPosDate);
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(3);
  tft.print(dateString);
  Serial.println(dateString);

  WiFi.disconnect();
}

Now I am able to sending data true ESPNOW and update Day and time from NTP server. I still need to make som updates because it is not smoot but it's work. Here is output from serial monitor:

Pripajam sa na WiFi....18:03:25
04.09.2025
Pripajam sa na WiFi....18:03:26
04.09.2025
Pripajam sa na WiFi....18:03:27
04.09.2025
Sprava prisla od: 14:08:08:a4:fb:ec
Pripajam sa na WiFi....18:03:28
04.09.2025
Pripajam sa na WiFi....18:03:29
04.09.2025

Looks like you are on the right track now.
BTW, what board are you using? I ask because the UNO R4 wiFi has an RTC, so you don't need to use NTP after it is set initially if you attach a small battery.

For sender ESP8266 and for reciever ESP32 both are NodeMCU