#include <esp_now.h>

Hello,

im getting the error:


Espnow_New_Version:4:10: fatal error: esp_now.h: No such file or directory

    4 | #include <esp_now.h>

      |          ^~~~~~~~~~~

compilation terminated.

exit status 1

esp_now.h: No such file or directory

Where and how do i add this library? I read it was included in the esp32 board manager.i installed the esp8266 and esp32 board libraries but it still doesn't work.

looking at some programs the ESP8266 uses

#include <espnow.h>

and the ESP32 uses

#include <esp_now.h>

i downloaded both es32 and esp8266 boards in the board manager but its still not there.

what particular ESP module are you using and what board do you select under Tools>Board?
upload the test program which displays the error - select < CODE/ > and paste the code or text where it says “type or paste code here”

upload the complete error message from the compiler - as text not a screen image

as written in the how to get the best out of this forum
you should always post the exact type of microcontroller that you use

if the code that you use is originally written for ESP8266 then your code has to use

#include <espnow.h> // WITHOUT underline "_"

such a code will only compile if you have adjusted the arduino-IDE to ESP8266
If you have a code that uses

#include <espnow.h>

and have the arduino-IDE adjusted to ESP32 you get this error-message
.
.
same vice versa:
if a code is originally written for ESP32 you have to use

#include <esp_now.h> // filename WITH underline "_"

if you have a code that uses

#include <esp_now.h> // filename WITH underline "_"

and the arduino-IDE is adjusted to ESP8266 you get this error-message

in short
for microcontroller ESP8266 use #include <espnow.h> // WITH OUT underline ""
.
for microcontroller ESP32 use #include <esp_now.h> // WITH underline "
"

But there are additional things.
The function-calls related to ESP-NOW differ a lot between ESP8266 and ESP32
this means:
if your microcontroller is a ESP8266 use a code that is originally written for ESP8266
.
if your microcontroller is a ESP32 use a code that is originally written for ESP32

you can find a lot of examples at random nerd tutorials

best regards Stefan

im using a nodemcu, which is esp8266, and a d1 mini esp32.
Under the board manager i am selecting Nodemcu 1.0, or generic esp8266
and lolin d32 pro for the d1 mini.

After the comment of Stefan i realised it had to to with the espnow vs esp_now.
i now dont have the compilation error anymore, the code just doesn't work the way it should.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <espnow.h>

int espNowChannel = 1;  // Set the desired communication channel
uint8_t espNowKey[16] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};  // Set your encryption key
const char* ssid = "SquirrelAP";         // Access Point SSID
const char* password = "12345678";       // Access Point password
const int onboardLedPin = 2;  // GPIO 2

ESP8266WebServer server(80);

unsigned long timerDuration = 0;
unsigned long timerStartTime = 0;
unsigned long elapsedTime = 0;
unsigned long buttonEndTimes[10][5] = {0};

bool isTimerStarted = false;
bool isRelayOn = false;
String selectedAnimal = "";  // Variable to store the selected animal

// Store the state of each button (true if active, false otherwise)
bool buttonStates[10][5] = {false};  // 10 animals, each with 5 durations

const int relayPin = 0;  // GPIO 0 (connected to a relay, change as per your setup)

// Macros for button durations
const int DURATION_5_MINUTES = 300;
const int DURATION_10_MINUTES = 600;
const int DURATION_20_MINUTES = 1200;
const int DURATION_30_MINUTES = 1800;
const int DURATION_60_MINUTES = 3600;

struct __attribute__((packed)) espData {
  char animal[20];  // Adjust the size based on the maximum length of the animal name
  int duration;
};

// MAC addresses of the 10 ESP8266 devices
uint8_t esp8266Macs[10][6] = {
  {0xEC, 0xFA, 0xBC, 0x27, 0x66, 0x4F},  // Elephant
  {0x12, 0x34, 0x56, 0x78, 0x9A, 0xDE},  // Panda
  {0x12, 0x34, 0x56, 0x78, 0x9A, 0xEF},  // Squirrel
  {0x12, 0x34, 0x56, 0x78, 0x9A, 0xF0},  // DogBrown
  {0x12, 0x34, 0x56, 0x78, 0x9A, 0xF1},  // Sabertooth
  {0x12, 0x34, 0x56, 0x78, 0x9A, 0xF2},  // DogYellow
  {0x12, 0x34, 0x56, 0x78, 0x9A, 0xF3},  // Chipmunk
  {0x12, 0x34, 0x56, 0x78, 0x9A, 0xF4},  // Octopus
  {0xB4, 0xE6, 0x2D, 0x31, 0x3D, 0x67},  // Cow
  {0x12, 0x34, 0x56, 0x78, 0x9A, 0xF5}   // AngryBird
  // Add the MAC addresses for the other 8 ESP8266 devices
};

void OnDataRecv(uint8_t *mac_addr, uint8_t *data, uint8_t len) {
    // Handle data received from ESP8266 devices if needed
    if (len == sizeof(espData)) {
        espData receivedData;
        memcpy(&receivedData, data, sizeof(receivedData));

        Serial.print("Received data from: ");
        for (int i = 0; i < 6; i++) {
            Serial.print(mac_addr[i], HEX);
            if (i < 5) {
                Serial.print(":");
            }
        }
        Serial.println();

        // Convert the MAC address to a String before concatenating
        String macAddressStr;
        for (int i = 0; i < 6; i++) {
            macAddressStr += String(mac_addr[i], HEX);
            if (i < 5) {
                macAddressStr += ":";
            }
        }

        Serial.println("Received Animal: " + String(receivedData.animal));
        Serial.println("Received Duration: " + String(receivedData.duration));
        Serial.println("Received MAC Address: " + macAddressStr);  // Use the converted MAC address String
    } else {
        Serial.println("Invalid data length received");
    }
}

void sendCommandToESP8266(String animal, int duration) {
  int animalIndex = -1;
  String animals[] = {"Elephant", "Panda", "Squirrel", "DogBrown", "Sabertooth", "DogYellow", "Chipmunk", "Octopus", "Cow", "AngryBird"};

  for (int i = 0; i < 10; i++) {
    if (animals[i] == animal) {
      animalIndex = i;
      break;
    }
  }

  if (animalIndex != -1) {
    espData data;

    // Convert String to char array
    animal.toCharArray(data.animal, sizeof(data.animal));
    data.duration = duration;

    // Turn on the onboard LED to indicate data transmission
    digitalWrite(onboardLedPin, HIGH);

    // Send data to the corresponding ESP8266
    if (esp_now_send(esp8266Macs[animalIndex], (uint8_t*)&data, sizeof(data)) != 0) {
      Serial.println("Failed to send data via ESP-NOW");
      // Handle send failure
    }

    // Wait for a short time to make the LED blink noticeable
    delay(500);

    // Turn off the onboard LED
    digitalWrite(onboardLedPin, LOW);
  }
}

void handleStartAnimalTimer() {
  String animal = server.arg("animal");
  int duration = server.arg("duration").toInt();

  if (duration > 0) {
    // Send command to the corresponding ESP8266
    sendCommandToESP8266(animal, duration);

    // Local processing
    timerDuration = duration;
    timerStartTime = millis();
    elapsedTime = 0;
    isTimerStarted = true;
    selectedAnimal = animal;  // Update the selected animal
    updateButtonState(animal, duration);  // Set the button state to active
  } else {
    isTimerStarted = false;
  }

  server.sendHeader("Location", "/");
  server.send(302, "text/plain", "");
}

void updateButtonState(String animal, int duration) {
  String animals[] = {"Elephant", "Panda", "Squirrel", "DogBrown", "Sabertooth", "DogYellow", "Chipmunk", "Octopus", "Cow", "AngryBird"};
  int animalIndex = -1;
  for (int i = 0; i < 10; i++) {
    if (animals[i] == animal) {
      animalIndex = i;
      break;
    }
  }

  if (animalIndex != -1) {
    // Reset the state for the animal
    for (int i = 0; i < 5; i++) {
      buttonStates[animalIndex][i] = false;
      buttonEndTimes[animalIndex][i] = 0;  // Reset end times
    }

    // Set the button state to active based on the provided duration
    if (duration == DURATION_5_MINUTES) {
      buttonStates[animalIndex][0] = true;
      buttonEndTimes[animalIndex][0] = millis() + duration * 1000;
    } else if (duration == DURATION_10_MINUTES) {
      buttonStates[animalIndex][1] = true;
      buttonEndTimes[animalIndex][1] = millis() + duration * 1000;
    } else if (duration == DURATION_20_MINUTES) {
      buttonStates[animalIndex][2] = true;
      buttonEndTimes[animalIndex][2] = millis() + duration * 1000;
    } else if (duration == DURATION_30_MINUTES) {
      buttonStates[animalIndex][3] = true;
      buttonEndTimes[animalIndex][3] = millis() + duration * 1000;
    } else if (duration == DURATION_60_MINUTES) {
      buttonStates[animalIndex][4] = true;
      buttonEndTimes[animalIndex][4] = millis() + duration * 1000;
    }
  }
}

void handleTimer() {
  if (server.method() == HTTP_POST) {
    String durationStr = server.arg("duration");
    timerDuration = durationStr.toInt();
    if (timerDuration > 0) {
      timerStartTime = millis();
      elapsedTime = 0;
      isTimerStarted = true;
    } else {
      isTimerStarted = false;
    }
  }
  server.sendHeader("Location", "/");
  server.send(302);
}

void handleAddThirtySeconds() {
  if (isTimerStarted) {
    unsigned long currentTime = millis();
    unsigned long latestPressTime = 0;

    // Find the latest pressed time among all active buttons
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 5; j++) {
        if (buttonStates[i][j] && (buttonEndTimes[i][j] > latestPressTime)) {
          latestPressTime = buttonEndTimes[i][j];
        }
      }
    }

    // Add 30 seconds to all active buttons pressed within 15 seconds of the latest pressed button
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 5; j++) {
        if (buttonStates[i][j] && (latestPressTime - buttonEndTimes[i][j] <= 15000)) {
          // Add 30 seconds to the timer for this button
          buttonEndTimes[i][j] += 30 * 1000;  // Update the button end time accordingly
        }
      }
    }

    // Also, update the overall timer duration
    timerDuration += 30;
  }

  server.sendHeader("Location", "/");
  server.send(302);
}

void handleAddOneMinute() {
  if (isTimerStarted) {
    timerDuration += 60; // Add 1 minute (60 seconds) to the timer
  }
  server.sendHeader("Location", "/");
  server.send(302);
}

void handleAddFiveMinutes() {
  if (isTimerStarted) {
    timerDuration += 300; // Add 5 minutes (300 seconds) to the timer
  }
  server.sendHeader("Location", "/");
  server.send(302);
}

void handleStartRelay() {
  isRelayOn = true; // Turn on the relay
  digitalWrite(relayPin, HIGH); // Set the GPIO pin to HIGH to activate the relay
  server.sendHeader("Location", "/");
  server.send(302);
}

void handleStopTimer() {
  timerDuration = 0;
  elapsedTime = 0;
  isTimerStarted = false;
  server.sendHeader("Location", "/");
  server.send(302);
}

void handleRoot() {
  String html = "<html><head><style>";
  html += "body { font-size: 20px; }";
  html += "input[type='submit'] { font-size: 20px; padding: 10px; }";
  html += "table { border-collapse: collapse; width: 100%; }";
  html += "th, td { border: 1px solid black; text-align: center; padding: 15px; }";
  html += ".start-button { background-color: #3498db; color: #fff; }"; 
  html += ".active-button { background-color: #2ecc71 !important; color: #fff; }"; 
  html += "</style></head><body>";

  html += "<h1>Manual Time Setting</h1>";
  html += "<form action='/timer' method='POST'>";
  html += "Timer Duration (in seconds): <input type='number' name='duration' min='0'><br><br>";
  html += "<input type='submit' value='Start Timer'>";
  html += "<input type='submit' value='Stop Timer' formaction='/stop-timer'>";
  html += "<input type='submit' value='Start Relay' formaction='/start-relay'>";
  html += "<input type='submit' value='Stop Relay' formaction='/stop-relay'>";
  html += "</form>";

  html += "<h2>Relay Status</h2>";
  html += "<p>Status: " + getRelayStatusHTML() + "</p>";

  html += "<h2>Animal Timers</h2>";
  html += "<table>";
  html += "<tr><th>Animal</th><th>5 Minutes</th><th>10 Minutes</th><th>20 Minutes</th><th>30 Minutes</th><th>60 Minutes</th></tr>";

  String animals[] = {"Elephant", "Panda", "Squirrel", "DogBrown", "Sabertooth", "DogYellow", "Chipmunk", "Octopus", "Cow", "AngryBird"};
  for (int i = 0; i < 10; i++) {
    html += "<tr><td>" + animals[i] + "</td>";

    int durations[] = {5, 10, 20, 30, 60};
    for (int j = 0; j < 5; j++) {
      html += "<td><form class='start-form' action='/start-animal-timer' method='POST'>";
      html += "<input type='hidden' name='animal' value='" + animals[i] + "'>";
      html += "<input type='hidden' name='duration' value='" + String(durations[j] * 60) + "'>";  
      html += "<input class='start-button";
      if (buttonStates[i][j]) {
        html += " active-button";  
      }
      html += "' type='submit' value='Start'></form></td>";
    }

    html += "</tr>";
  }

  html += "</table>";

  html += "<h2>Add Time</h2>";
  html += "<form action='/add-thirty-seconds' method='POST'>";
  html += "<input type='submit' value='Add 30 Seconds'>";
  html += "</form>";

  html += "<form action='/add-one-minute' method='POST'>";
  html += "<input type='submit' value='Add 1 Minute'>";
  html += "</form>";

  html += "<form action='/add-five-minutes' method='POST'>";
  html += "<input type='submit' value='Add 5 Minutes'>";
  html += "</form>";

  html += "<h2>Timer Information</h2>";
  html += "<p>Duration: " + String(timerDuration / 60) + " minutes</p>";  
  if (isTimerStarted) {
    html += "<p>Time Elapsed: " + String(getElapsedTime()) + " seconds</p>";
    html += "<p>Time Remaining: " + String(getRemainingMinutes()) + " minutes " + String(getRemainingSeconds()) + " seconds</p>";
    html += "<p>Selected Animal: " + selectedAnimal + "</p>";  
  } else {
    html += "<p>Time Elapsed: Not started</p>";
    html += "<p>Time Remaining: Not started</p>";
    html += "<p>Selected Animal: Not selected</p>";
  }

  html += "<script>";
  html += "document.addEventListener('DOMContentLoaded', function() {";
  html += "  var startButtons = document.querySelectorAll('.start-form');";
  html += "  startButtons.forEach(function(form) {";
  html += "    form.addEventListener('submit', function(event) {";
  html += "      event.preventDefault();";  
  html += "      var buttons = form.querySelectorAll('.start-button');";
  html += "      buttons.forEach(function(button) {";
  html += "        button.classList.remove('active-button');"; 
  html += "      });";
  html += "      form.querySelector('.start-button').classList.add('active-button');"; 
  html += "      setTimeout(function() {";
  html += "      var duration = " + String(timerDuration * 1000) + ";";  
  html += "      form.querySelector('.start-button').classList.add('active-button');"; 
  html += "      setTimeout(function() {";
  html += "        form.querySelector('.start-button').classList.remove('active-button');"; 
  html += "      }, duration);";
  html += "    });";
  html += "  });";
  html += "});";
  html += "</script>";

  html += "</body></html>";
  server.send(200, "text/html", html);
}

void handleStopRelay() {
  isRelayOn = false; 
  digitalWrite(relayPin, LOW); 
  server.sendHeader("Location", "/");
  server.send(302);
}

void handleNotFound() {
  server.send(404, "text/plain", "Not found");
}

unsigned long getElapsedTime() {
  unsigned long currentTime = millis();
  elapsedTime = (currentTime - timerStartTime) / 1000;
  return elapsedTime;
}

long getRemainingTime() {
  long remainingTime = timerDuration - getElapsedTime();
  if (remainingTime < 0) {
    remainingTime = 0;
  }
  return remainingTime;
}

int getRemainingMinutes() {
  int remainingMinutes = getRemainingTime() / 60;
  return remainingMinutes;
}

int getRemainingSeconds() {
  int remainingSeconds = getRemainingTime() % 60;
  return remainingSeconds;
}

String getRelayStatusHTML() {
  if (isRelayOn) {
    return "<span style='color: green;'>ON</span>";
  } else {
    return "<span style='color: red;'>OFF</span>";
  }
}

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

  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, LOW);  

  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);

  IPAddress apIP = WiFi.softAPIP();
  Serial.print("Access Point IP address: ");
  Serial.println(apIP);

  pinMode(onboardLedPin, OUTPUT);
  digitalWrite(onboardLedPin, LOW);  

    // Set ESP-NOW channel
    wifi_set_channel(espNowChannel);

    uint8_t key[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
    esp_now_add_peer(esp8266Macs[0], ESP_NOW_ROLE_COMBO, 1, key, 16);

  server.on("/", HTTP_GET, handleRoot);
  server.on("/timer", HTTP_POST, handleTimer);
  server.on("/add-thirty-seconds", HTTP_POST, handleAddThirtySeconds);
  server.on("/add-one-minute", HTTP_POST, handleAddOneMinute);
  server.on("/add-five-minutes", HTTP_POST, handleAddFiveMinutes);
  server.on("/start-relay", HTTP_POST, handleStartRelay);
  server.on("/stop-timer", HTTP_POST, handleStopTimer);
  server.on("/stop-relay", HTTP_POST, handleStopRelay);
  server.on("/start-animal-timer", HTTP_POST, handleStartAnimalTimer);

  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");

  if (esp_now_init() != 0) {
    Serial.println("ESP-NOW initialization failed");
  } else {
    Serial.println("ESP-NOW initialization successful");
  }

  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  server.handleClient();

  unsigned long currentTime = millis();  

  if (isTimerStarted && !isRelayOn) {
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 5; j++) {
        if (buttonStates[i][j] && currentTime >= buttonEndTimes[i][j]) {
          buttonStates[i][j] = false;  
        }
      }
    }

    if (currentTime - timerStartTime >= (timerDuration * 1000)) {
      Serial.println("Timer expired!");
      timerDuration = 0;
      isTimerStarted = false;
      isRelayOn = true; 
      digitalWrite(relayPin, HIGH); 
    }
  }
}

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