Help Combining Two ESP8266 Projects with Web Control, Timers, and EEPROM

Hi everyone,

I’m working on combining two separate ESP8266 projects, but I’m having some difficulty merging their functionalities. Here’s a quick overview of the two codes I want to integrate:

Code 1:
This code controls a fan and light system with configurable on/off timers via a web interface. It uses the AsyncWebServer library, stores settings in EEPROM, and updates timer values in real-time.

Code 2:
This code monitors temperature and humidity using the AHT10 sensor and controls a relay and a humidifier based on configurable thresholds. It also uses EEPROM for saving configurations and includes a web interface for user settings.

My Goal:
I want to create a single codebase that integrates the following:

  1. Fan and light control with on/off timers.
  2. Relay and humidifier control based on temperature and humidity thresholds.
  3. A unified web interface to configure all settings (timers, temperature, humidity, etc.).
  4. Persistent storage for all settings using EEPROM.

I’ve tried merging the codes, but I’m facing challenges with overlapping functions, libraries, and managing the timers and states simultaneously.

My Questions:

  1. How can I efficiently integrate both web interfaces without conflict?
  2. What’s the best way to handle multiple timers and states in one loop()?
  3. Are there any examples of combining projects like this, or tips for managing complexity?

I’d appreciate any advice, examples, or suggestions to simplify the integration process. Let me know if you’d like to see the full code for each project. and mt idea for web page look likr this https://codepen.io/pars-tondar/pen/zxOwEyE

Thank you!

#include <Wire.h>
#include <Thinary_AHT10.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <NTPClient.h>
#include <EEPROM.h>  // اضافه کردن کتابخانه EEPROM

AHT10Class AHT10;
AsyncWebServer server(80);

// تنظیمات شبکه
const char* ssid = "9KEYnew";
const char* password = "n123456789";

const int relayPin = D5;
const int humidifierPin = D7; // پین ترانزیستور مرطوب‌کننده

float currentTemp = 0;
float currentHumidity = 0;
int minTemp = 20; // حداقل دمای پیش‌فرض
int maxTemp = 25; // حداکثر دمای پیش‌فرض
int minHumidity = 40; // مقدار پیش‌فرض حداقل رطوبت
int maxHumidity = 60; // مقدار پیش‌فرض حداکثر رطوبت
int lampWattage = 100;

bool relayState = false;
bool humidifierState = false;

unsigned long lastUpdate = 0;
const int updateInterval = 10000;

// تعریف اندازه حافظه EEPROM
#define EEPROM_SIZE 10

// تابع برای ذخیره تنظیمات در EEPROM
void saveSettings() {
  EEPROM.begin(EEPROM_SIZE);
  EEPROM.write(0, minTemp); // ذخیره حداقل دما
  EEPROM.write(1, maxTemp); // ذخیره حداکثر دما
  EEPROM.write(2, minHumidity);
  EEPROM.write(3, maxHumidity);
  EEPROM.commit();
  EEPROM.end();
  Serial.println("Settings saved!");
}

// تابع برای بارگذاری تنظیمات از EEPROM
void loadSettings() {
  EEPROM.begin(EEPROM_SIZE);
  minTemp = EEPROM.read(0);
  maxTemp = EEPROM.read(1);
  minHumidity = EEPROM.read(2);
  maxHumidity = EEPROM.read(3);
  EEPROM.end();

  // بررسی صحت مقادیر و تنظیم پیش‌فرض در صورت غیرمعتبر بودن
  if (minTemp < 0 || minTemp > 80) minTemp = 20;
  if (maxTemp < 0 || maxTemp > 80 || maxTemp <= minTemp) maxTemp = 25;
  if (minHumidity < 0 || minHumidity > 100) minHumidity = 40;
  if (maxHumidity < 0 || maxHumidity > 100 || maxHumidity <= minHumidity) maxHumidity = 60;

  Serial.println("Settings loaded!");
}

void setup() {
  Serial.begin(9600);
  Wire.begin();
  pinMode(relayPin, OUTPUT);
  pinMode(humidifierPin, OUTPUT);

  digitalWrite(relayPin, LOW);
  digitalWrite(humidifierPin, LOW);

  if (AHT10.begin(eAHT10Address_Low))
    Serial.println("Init AHT10 Success.");
  else
    Serial.println("Init AHT10 Failure.");

  // بارگذاری تنظیمات از EEPROM
  loadSettings();

  // ایجاد نقطه دسترسی
  WiFi.softAP(ssid, password);
  Serial.println("Access Point Started");
  Serial.print("SSID: ");
  Serial.println(ssid);
  Serial.print("IP Address: ");
  Serial.println(WiFi.softAPIP());
  
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", getHTML());
  });

  server.on("/settemp", HTTP_GET, [](AsyncWebServerRequest *request){
    if (request->hasParam("minTemp")) {
      minTemp = request->getParam("minTemp")->value().toInt();
    }
    if (request->hasParam("maxTemp")) {
      maxTemp = request->getParam("maxTemp")->value().toInt();
    }
    if (request->hasParam("watt")) {
      lampWattage = request->getParam("watt")->value().toInt();
    }
    if (request->hasParam("minHum")) {
      minHumidity = request->getParam("minHum")->value().toInt();
    }
    if (request->hasParam("maxHum")) {
      maxHumidity = request->getParam("maxHum")->value().toInt();
    }
    
    // ذخیره تنظیمات جدید در EEPROM
    saveSettings();
    request->redirect("/");
  });

  server.begin();
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - lastUpdate >= updateInterval) {
    lastUpdate = currentMillis;
    readSensor();
  }
  controlRelay();
  controlHumidifier();
}

void readSensor() {
  currentHumidity = AHT10.GetHumidity();
  currentTemp = AHT10.GetTemperature();
  Serial.println("Humidity(%RH):\t\t" + String(currentHumidity) + "%");
  Serial.println("Temperature(℃):\t" + String(currentTemp) + "℃");
}

void controlRelay() {
  if (currentTemp >= maxTemp) { // خاموش کردن رله در دمای بالاتر از حداکثر
    if (relayState) {
      relayState = false;
    }
    digitalWrite(relayPin, LOW);
  } else if (currentTemp < minTemp) { // روشن کردن رله در دمای کمتر از حداقل
    if (!relayState) {
      relayState = true;
    }
    digitalWrite(relayPin, HIGH);
  }
}

void controlHumidifier() {
  if (currentHumidity < minHumidity) {
    if (!humidifierState) {
      humidifierState = true;
      digitalWrite(humidifierPin, HIGH);
    }
  } else if (currentHumidity > maxHumidity) {
    if (humidifierState) {
      humidifierState = false;
      digitalWrite(humidifierPin, LOW);
    }
  }
}

String getHTML() {
  String html = "<html><body><h1>Temperature and Humidity</h1>";
  html += "<p>Temperature: " + String(currentTemp) + " °C</p>";
  html += "<p>Humidity: " + String(currentHumidity) + " %</p>";

  html += "<h2>Settings</h2>";
  html += "<form action=\"/settemp\" method=\"get\">";
  html += "<label for=\"minTemp\">Minimum Temperature (°C):</label>";
  html += "<input type=\"number\" name=\"minTemp\" value=\"" + String(minTemp) + "\" min=\"0\" max=\"80\"><br>";

  html += "<label for=\"maxTemp\">Maximum Temperature (°C):</label>";
  html += "<input type=\"number\" name=\"maxTemp\" value=\"" + String(maxTemp) + "\" min=\"0\" max=\"80\"><br>";

  html += "<label for=\"watt\">Lamp Wattage:</label>";
  html += "<select name=\"watt\" id=\"watt\">";
  for (int i = 100; i <= 1000; i += 100) {
    html += "<option value=\"" + String(i) + "\"" + (i == lampWattage ? " selected" : "") + ">" + String(i) + " W</option>";
  }
  html += "</select><br>";

  html += "<label for=\"minHum\">Minimum Humidity (%):</label>";
  html += "<input type=\"number\" name=\"minHum\" value=\"" + String(minHumidity) + "\" min=\"0\" max=\"100\"><br>";

  html += "<label for=\"maxHum\">Maximum Humidity (%):</label>";
  html += "<input type=\"number\" name=\"maxHum\" value=\"" + String(maxHumidity) + "\" min=\"0\" max=\"100\"><br>";

  html += "<input type=\"submit\" value=\"Update Settings\">";
  html += "</form>";

  html += "<h2>Device Status</h2>";
  html += "<p>Relay: " + String(relayState ? "ON" : "OFF") + "</p>";
  html += "<p>Humidifier: " + String(humidifierState ? "ON" : "OFF") + "</p>";

  html += "</body></html>";
  return html;
}

2th code

#include <Wire.h>
#include <Thinary_AHT10.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <EEPROM.h>  // Include the EEPROM library

AHT10Class AHT10;
AsyncWebServer server(80);

// Network settings
const char* ssid = "ESP8266-Access-Point";  // Set the SSID of the Access Point
const char* password = "123456789";  // Set the password for the Access Point

// Pin definitions
const int fanPin = D6;
const int lightPin = D0;

// On/off times in hours and minutes
int fanOnHour = 0;
int fanOnMin = 1;
int fanOffHour = 0;
int fanOffMin = 1;
int lightOnHour = 0;
int lightOnMin = 1;
int lightOffHour = 0;
int lightOffMin = 1;

// Timer settings
unsigned long startMillis;
unsigned long currentMillis;
int seconds = 0;
int minutes = 0;
int hours = 0;
int days = 0;

// Status of fan and light
bool fanState = false;
bool lightState = false;

// EEPROM storage
void loadSettings() {
  EEPROM.begin(512);
  fanOnHour = EEPROM.read(0);
  fanOnMin = EEPROM.read(1);
  fanOffHour = EEPROM.read(2);
  fanOffMin = EEPROM.read(3);
  lightOnHour = EEPROM.read(4);
  lightOnMin = EEPROM.read(5);
  lightOffHour = EEPROM.read(6);
  lightOffMin = EEPROM.read(7);
  EEPROM.end();
}

void saveSettings() {
  EEPROM.begin(512);
  EEPROM.write(0, fanOnHour);
  EEPROM.write(1, fanOnMin);
  EEPROM.write(2, fanOffHour);
  EEPROM.write(3, fanOffMin);
  EEPROM.write(4, lightOnHour);
  EEPROM.write(5, lightOnMin);
  EEPROM.write(6, lightOffHour);
  EEPROM.write(7, lightOffMin);
  EEPROM.end();
}

// Wi-Fi and Web server setup
void setupWiFi() {
  // Start the Access Point
  WiFi.softAP(ssid, password);  // Set the SSID and password for the AP

  // Print the IP address assigned to the ESP8266
  Serial.println("Access Point Started");
  Serial.print("IP Address: ");
  Serial.println(WiFi.softAPIP());

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    String html = "<html><body>";
    html += "<h1>Control System</h1>";
    html += "<form action='/set' method='POST'>";
    html += "Fan On Time (hours:minutes): <input type='number' name='fanOnHour' min='0' max='23' value='" + String(fanOnHour) + "'> : <input type='number' name='fanOnMin' min='0' max='59' value='" + String(fanOnMin) + "'><br>";
    html += "Fan Off Time (hours:minutes): <input type='number' name='fanOffHour' min='0' max='23' value='" + String(fanOffHour) + "'> : <input type='number' name='fanOffMin' min='0' max='59' value='" + String(fanOffMin) + "'><br>";
    html += "Light On Time (hours:minutes): <input type='number' name='lightOnHour' min='0' max='23' value='" + String(lightOnHour) + "'> : <input type='number' name='lightOnMin' min='0' max='59' value='" + String(lightOnMin) + "'><br>";
    html += "Light Off Time (hours:minutes): <input type='number' name='lightOffHour' min='0' max='23' value='" + String(lightOffHour) + "'> : <input type='number' name='lightOffMin' min='0' max='59' value='" + String(lightOffMin) + "'><br>";
    html += "<input type='submit' value='Set'>";
    html += "</form>";

    // Show the status of the fan and light
    html += "<h2>Status:</h2>";
    html += "<p>Fan: " + String(fanState ? "ON" : "OFF") + "</p>";
    html += "<p>Light: " + String(lightState ? "ON" : "OFF") + "</p>";

    // Display timer information
    html += "<h2>Timer Status:</h2>";
    html += "<p>Seconds: " + String(seconds) + "</p>";
    html += "<p>Minutes: " + String(minutes) + "</p>";
    html += "<p>Hours: " + String(hours) + "</p>";
    html += "<p>Days: " + String(days) + "</p>";
    html += "</body></html>";

    request->send(200, "text/html", html);  // Send the response to the client
  });

  server.on("/set", HTTP_POST, [](AsyncWebServerRequest *request){
    fanOnHour = request->arg("fanOnHour").toInt();
    fanOnMin = request->arg("fanOnMin").toInt();
    fanOffHour = request->arg("fanOffHour").toInt();
    fanOffMin = request->arg("fanOffMin").toInt();
    lightOnHour = request->arg("lightOnHour").toInt();
    lightOnMin = request->arg("lightOnMin").toInt();
    lightOffHour = request->arg("lightOffHour").toInt();
    lightOffMin = request->arg("lightOffMin").toInt();
    saveSettings();

    // Redirect to the main page after saving settings
    request->redirect("/");  // Use request->redirect to redirect the user to the main page
  });

  server.begin();
}

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

  pinMode(fanPin, OUTPUT);
  pinMode(lightPin, OUTPUT);

  loadSettings();  // Load settings from EEPROM

  setupWiFi();

  startMillis = millis();
}

void loop() {
  currentMillis = millis();

  // Calculate time
  if (currentMillis - startMillis >= 1000) {
    startMillis = currentMillis;
    seconds++;

    if (seconds >= 60) {
      seconds = 0;
      minutes++;
    }
    if (minutes >= 60) {
      minutes = 0;
      hours++;
    }
    if (hours >= 24) {
      hours = 0;
      days++;
    }
  }

  // Control the intake fan and light system
  static unsigned long fanTimer = 0;
  static unsigned long lightTimer = 0;

  if (fanState) {
    digitalWrite(fanPin, HIGH);
  } else {
    digitalWrite(fanPin, LOW);
  }

  if (lightState) {
    digitalWrite(lightPin, HIGH);
  } else {
    digitalWrite(lightPin, LOW);
  }

  // Timer for fan and light on/off control
  if (fanState && (millis() - fanTimer >= (fanOnHour * 3600000 + fanOnMin * 60000))) {
    fanState = false;
    fanTimer = millis();
  }
  if (!fanState && (millis() - fanTimer >= (fanOffHour * 3600000 + fanOffMin * 60000))) {
    fanState = true;
    fanTimer = millis();
  }

  if (lightState && (millis() - lightTimer >= (lightOnHour * 3600000 + lightOnMin * 60000))) {
    lightState = false;
    lightTimer = millis();
  }
  if (!lightState && (millis() - lightTimer >= (lightOffHour * 3600000 + lightOffMin * 60000))) {
    lightState = true;
    lightTimer = millis();
  }
}



  1. There are several ways. Which is best only you can decide. You could merge the two web pages into one. You could keep them as two separate web pages, perhaps with a main menu page with links for the other two pages.
  2. Use separate variables for each of the timers and states. Don't use blocking code.
  3. Most projects are the result of combining code from multiple examples or code snippets copied from other projects. There is no magic or trick to doing this. You have to have a good level of coding experience and you must exactly understand how each line of copied code works and it's precise purpose.

i tried alot but i can't figure out . can you send me combined code you think work

here is my resulte that have some compile problem

#include <Wire.h>
#include <Thinary_AHT10.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <NTPClient.h>
#include <EEPROM.h>  // اضافه کردن کتابخانه EEPROM

AHT10Class AHT10;
AsyncWebServer server(80);

// تنظیمات شبکه
const char* ssid = "9KEYnew";
const char* password = "n123456789";

const int relayPin = D5;
const int humidifierPin = D7; // پین ترانزیستور مرطوب‌کننده
const int fanPin = D6;
const int lightPin = D0;

float currentTemp = 0;
float currentHumidity = 0;
int minTemp = 20; // حداقل دمای پیش‌فرض
int maxTemp = 25; // حداکثر دمای پیش‌فرض
int minHumidity = 40; // مقدار پیش‌فرض حداقل رطوبت
int maxHumidity = 60; // مقدار پیش‌فرض حداکثر رطوبت
int lampWattage = 100;

bool relayState = false;
bool humidifierState = false;

unsigned long lastUpdate = 0;
const int updateInterval = 10000;



// On/off times in hours and minutes
int fanOnHour = 0;
int fanOnMin = 1;
int fanOffHour = 0;
int fanOffMin = 1;
int lightOnHour = 0;
int lightOnMin = 1;
int lightOffHour = 0;
int lightOffMin = 1;

// Timer settings
unsigned long startMillis;
unsigned long currentMillis;
int seconds = 0;
int minutes = 0;
int hours = 0;
int days = 0;

// Status of fan and light
bool fanState = false;
bool lightState = false;

// تعریف اندازه حافظه EEPROM
#define EEPROM_SIZE 24

// تابع برای ذخیره تنظیمات در EEPROM
void saveSettings() {
  EEPROM.begin(EEPROM_SIZE);
  EEPROM.write(0, minTemp); // ذخیره حداقل دما
  EEPROM.write(1, maxTemp); // ذخیره حداکثر دما
  EEPROM.write(2, minHumidity);
  EEPROM.write(3, maxHumidity);
  EEPROM.write(4, fanOnHour);
  EEPROM.write(5, fanOnMin);
  EEPROM.write(6, fanOffHour);
  EEPROM.write(7, fanOffMin);
  EEPROM.write(8, lightOnHour);
  EEPROM.write(9, lightOnMin);
  EEPROM.write(10, lightOffHour);
  EEPROM.write(11, lightOffMin);

  EEPROM.commit();
  Serial.println("Settings saved!");
}

// تابع برای بارگذاری تنظیمات از EEPROM
void loadSettings() {
  EEPROM.begin(EEPROM_SIZE);
  minTemp = EEPROM.read(0);
  maxTemp = EEPROM.read(1);
  minHumidity = EEPROM.read(2);
  maxHumidity = EEPROM.read(3);
  fanOnHour = EEPROM.read(4);
  fanOnMin = EEPROM.read(5);
  fanOffHour = EEPROM.read(6);
  fanOffMin = EEPROM.read(7);
  lightOnHour = EEPROM.read(8);
  lightOnMin = EEPROM.read(9);
  lightOffHour = EEPROM.read(10);
  lightOffMin = EEPROM.read(11);
  EEPROM.end();

  // بررسی صحت مقادیر و تنظیم پیش‌فرض در صورت غیرمعتبر بودن
  if (minTemp < 0 || minTemp > 80) minTemp = 20;
  if (maxTemp < 0 || maxTemp > 80 || maxTemp <= minTemp) maxTemp = 25;
  if (minHumidity < 0 || minHumidity > 100) minHumidity = 40;
  if (maxHumidity < 0 || maxHumidity > 100 || maxHumidity <= minHumidity) maxHumidity = 60;

  Serial.println("Settings loaded!");
}

void setup() {
  Serial.begin(9600);
  Wire.begin();
  pinMode(relayPin, OUTPUT);
  pinMode(humidifierPin, OUTPUT);
  pinMode(fanPin, OUTPUT);
  pinMode(lightPin, OUTPUT);

  digitalWrite(relayPin, LOW);
  digitalWrite(humidifierPin, LOW);

  if (AHT10.begin(eAHT10Address_Low))
    Serial.println("Init AHT10 Success.");
  else
    Serial.println("Init AHT10 Failure.");

  // بارگذاری تنظیمات از EEPROM
  loadSettings();

  // ایجاد نقطه دسترسی
  WiFi.softAP(ssid, password);
  Serial.println("Access Point Started");
  Serial.print("SSID: ");
  Serial.println(ssid);
  Serial.print("IP Address: ");
  Serial.println(WiFi.softAPIP());
  
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", getHTML());
  });

  server.on("/settemp", HTTP_GET, [](AsyncWebServerRequest *request){
    if (request->hasParam("minTemp")) {
      minTemp = request->getParam("minTemp")->value().toInt();
    }
    if (request->hasParam("maxTemp")) {
      maxTemp = request->getParam("maxTemp")->value().toInt();
    }
    if (request->hasParam("watt")) {
      lampWattage = request->getParam("watt")->value().toInt();
    }
    if (request->hasParam("minHum")) {
      minHumidity = request->getParam("minHum")->value().toInt();
    }
    if (request->hasParam("maxHum")) {
      maxHumidity = request->getParam("maxHum")->value().toInt();
    }
    
    // ذخیره تنظیمات جدید در EEPROM
    saveSettings();
    request->redirect("/");
  });
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    String html = "<html><body>";
    html += "<h1>Control System</h1>";
    html += "<form action='/set' method='POST'>";
    html += "Fan On Time (hours:minutes): <input type='number' name='fanOnHour' min='0' max='23' value='" + String(fanOnHour) + "'> : <input type='number' name='fanOnMin' min='0' max='59' value='" + String(fanOnMin) + "'><br>";
    html += "Fan Off Time (hours:minutes): <input type='number' name='fanOffHour' min='0' max='23' value='" + String(fanOffHour) + "'> : <input type='number' name='fanOffMin' min='0' max='59' value='" + String(fanOffMin) + "'><br>";
    html += "Light On Time (hours:minutes): <input type='number' name='lightOnHour' min='0' max='23' value='" + String(lightOnHour) + "'> : <input type='number' name='lightOnMin' min='0' max='59' value='" + String(lightOnMin) + "'><br>";
    html += "Light Off Time (hours:minutes): <input type='number' name='lightOffHour' min='0' max='23' value='" + String(lightOffHour) + "'> : <input type='number' name='lightOffMin' min='0' max='59' value='" + String(lightOffMin) + "'><br>";
    html += "<input type='submit' value='Set'>";
    html += "</form>";

    // Show the status of the fan and light
    html += "<h2>Status:</h2>";
    html += "<p>Fan: " + String(fanState ? "ON" : "OFF") + "</p>";
    html += "<p>Light: " + String(lightState ? "ON" : "OFF") + "</p>";

    // Display timer information
    html += "<h2>Timer Status:</h2>";
    html += "<p>Seconds: " + String(seconds) + "</p>";
    html += "<p>Minutes: " + String(minutes) + "</p>";
    html += "<p>Hours: " + String(hours) + "</p>";
    html += "<p>Days: " + String(days) + "</p>";
    html += "</body></html>";

    request->send(200, "text/html", html);  // Send the response to the client
  });

  server.on("/set", HTTP_POST, [](AsyncWebServerRequest *request){
    fanOnHour = request->arg("fanOnHour").toInt();
    fanOnMin = request->arg("fanOnMin").toInt();
    fanOffHour = request->arg("fanOffHour").toInt();
    fanOffMin = request->arg("fanOffMin").toInt();
    lightOnHour = request->arg("lightOnHour").toInt();
    lightOnMin = request->arg("lightOnMin").toInt();
    lightOffHour = request->arg("lightOffHour").toInt();
    lightOffMin = request->arg("lightOffMin").toInt();
    saveSettings();

    // Redirect to the main page after saving settings
    request->redirect("/");  // Use request->redirect to redirect the user to the main page
  });

  server.begin();
}

void loop() {
   currentMillis = millis();

  // Calculate time
  if (currentMillis - startMillis >= 1000) {
    startMillis = currentMillis;
    seconds++;

    if (seconds >= 60) {
      seconds = 0;
      minutes++;
    }
    if (minutes >= 60) {
      minutes = 0;
      hours++;
    }
    if (hours >= 24) {
      hours = 0;
      days++;
    }
  }

  // Control the intake fan and light system
  static unsigned long fanTimer = 0;
  static unsigned long lightTimer = 0;

  if (fanState) {
    digitalWrite(fanPin, HIGH);
  } else {
    digitalWrite(fanPin, LOW);
  }

  if (lightState) {
    digitalWrite(lightPin, HIGH);
  } else {
    digitalWrite(lightPin, LOW);
  }

  // Timer for fan and light on/off control
  if (fanState && (millis() - fanTimer >= (fanOnHour * 3600000 + fanOnMin * 60000))) {
    fanState = false;
    fanTimer = millis();
  }
  if (!fanState && (millis() - fanTimer >= (fanOffHour * 3600000 + fanOffMin * 60000))) {
    fanState = true;
    fanTimer = millis();
  }

  if (lightState && (millis() - lightTimer >= (lightOnHour * 3600000 + lightOnMin * 60000))) {
    lightState = false;
    lightTimer = millis();
  }
  if (!lightState && (millis() - lightTimer >= (lightOffHour * 3600000 + lightOffMin * 60000))) {
    lightState = true;
    lightTimer = millis();
  }
}


void readSensor() {
  currentHumidity = AHT10.GetHumidity();
  currentTemp = AHT10.GetTemperature();
  Serial.println("Humidity(%RH):\t\t" + String(currentHumidity) + "%");
  Serial.println("Temperature(℃):\t" + String(currentTemp) + "℃");
}

void controlRelay() {
  if (currentTemp >= maxTemp) { // خاموش کردن رله در دمای بالاتر از حداکثر
    if (relayState) {
      relayState = false;
    }
    digitalWrite(relayPin, LOW);
  } else if (currentTemp < minTemp) { // روشن کردن رله در دمای کمتر از حداقل
    if (!relayState) {
      relayState = true;
    }
    digitalWrite(relayPin, HIGH);
  }
}

void controlHumidifier() {
  if (currentHumidity < minHumidity) {
    if (!humidifierState) {
      humidifierState = true;
      digitalWrite(humidifierPin, HIGH);
    }
  } else if (currentHumidity > maxHumidity) {
    if (humidifierState) {
      humidifierState = false;
      digitalWrite(humidifierPin, LOW);
    }
  }
}

String getHTML() {
  String html = "<html><body><h1>Temperature and Humidity</h1>";
  html += "<p>Temperature: " + String(currentTemp) + " °C</p>";
  html += "<p>Humidity: " + String(currentHumidity) + " %</p>";

  html += "<h2>Settings</h2>";
  html += "<form action=\"/settemp\" method=\"get\">";
  html += "<label for=\"minTemp\">Minimum Temperature (°C):</label>";
  html += "<input type=\"number\" name=\"minTemp\" value=\"" + String(minTemp) + "\" min=\"0\" max=\"80\"><br>";

  html += "<label for=\"maxTemp\">Maximum Temperature (°C):</label>";
  html += "<input type=\"number\" name=\"maxTemp\" value=\"" + String(maxTemp) + "\" min=\"0\" max=\"80\"><br>";

  html += "<label for=\"watt\">Lamp Wattage:</label>";
  html += "<select name=\"watt\" id=\"watt\">";
  for (int i = 100; i <= 1000; i += 100) {
    html += "<option value=\"" + String(i) + "\"" + (i == lampWattage ? " selected" : "") + ">" + String(i) + " W</option>";
  }
  html += "</select><br>";

  html += "<label for=\"minHum\">Minimum Humidity (%):</label>";
  html += "<input type=\"number\" name=\"minHum\" value=\"" + String(minHumidity) + "\" min=\"0\" max=\"100\"><br>";

  html += "<label for=\"maxHum\">Maximum Humidity (%):</label>";
  html += "<input type=\"number\" name=\"maxHum\" value=\"" + String(maxHumidity) + "\" min=\"0\" max=\"100\"><br>";

  html += "<input type=\"submit\" value=\"Update Settings\">";
  html += "</form>";

  html += "<h2>Device Status</h2>";
  html += "<p>Relay: " + String(relayState ? "ON" : "OFF") + "</p>";
  html += "<p>Humidifier: " + String(humidifierState ? "ON" : "OFF") + "</p>";

  html += "</body></html>";
  return html;
}

No. This forum is not a free code writing service. I will help you to combine the code, but you must do the hard work, otherwise you will learn nothing.

Why don't you post your best attempt to merge the code. If you are unable to get it to compile, post the complete set of error messages between code tags. I will help you understand what the messages are telling you and how to change the code to fix them.

in first attemp i dont have fan and light timerfield in the web page .
here is my other attemp . that have com pile issue .

#include <Wire.h>
#include <Thinary_AHT10.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <NTPClient.h>
#include <EEPROM.h>  // اضافه کردن کتابخانه EEPROM

AHT10Class AHT10;
AsyncWebServer server(80);

// تنظیمات شبکه
const char* ssid = "9KEYnew";
const char* password = "n123456789";

const int relayPin = D5;
const int humidifierPin = D7; // پین ترانزیستور مرطوب‌کننده
const int fanPin = D6;
const int lightPin = D0;

float currentTemp = 0;
float currentHumidity = 0;
int minTemp = 20; // حداقل دمای پیش‌فرض
int maxTemp = 25; // حداکثر دمای پیش‌فرض
int minHumidity = 40; // مقدار پیش‌فرض حداقل رطوبت
int maxHumidity = 60; // مقدار پیش‌فرض حداکثر رطوبت
int lampWattage = 100;

bool relayState = false;
bool humidifierState = false;

unsigned long lastUpdate = 0;
const int updateInterval = 10000;



// On/off times in hours and minutes
int fanOnHour = 0;
int fanOnMin = 1;
int fanOffHour = 0;
int fanOffMin = 1;
int lightOnHour = 0;
int lightOnMin = 1;
int lightOffHour = 0;
int lightOffMin = 1;

// Timer settings
unsigned long startMillis;
unsigned long currentMillis;
int seconds = 0;
int minutes = 0;
int hours = 0;
int days = 0;

// Status of fan and light
bool fanState = false;
bool lightState = false;

// تعریف اندازه حافظه EEPROM
#define EEPROM_SIZE 24

// تابع برای ذخیره تنظیمات در EEPROM
void saveSettings() {
  EEPROM.begin(EEPROM_SIZE);
  EEPROM.write(0, minTemp); // ذخیره حداقل دما
  EEPROM.write(1, maxTemp); // ذخیره حداکثر دما
  EEPROM.write(2, minHumidity);
  EEPROM.write(3, maxHumidity);
  EEPROM.write(4, fanOnHour);
  EEPROM.write(5, fanOnMin);
  EEPROM.write(6, fanOffHour);
  EEPROM.write(7, fanOffMin);
  EEPROM.write(8, lightOnHour);
  EEPROM.write(9, lightOnMin);
  EEPROM.write(10, lightOffHour);
  EEPROM.write(11, lightOffMin);

  EEPROM.commit();
  Serial.println("Settings saved!");
}

// تابع برای بارگذاری تنظیمات از EEPROM
void loadSettings() {
  EEPROM.begin(EEPROM_SIZE);
  minTemp = EEPROM.read(0);
  maxTemp = EEPROM.read(1);
  minHumidity = EEPROM.read(2);
  maxHumidity = EEPROM.read(3);
  fanOnHour = EEPROM.read(4);
  fanOnMin = EEPROM.read(5);
  fanOffHour = EEPROM.read(6);
  fanOffMin = EEPROM.read(7);
  lightOnHour = EEPROM.read(8);
  lightOnMin = EEPROM.read(9);
  lightOffHour = EEPROM.read(10);
  lightOffMin = EEPROM.read(11);
  EEPROM.end();

  // بررسی صحت مقادیر و تنظیم پیش‌فرض در صورت غیرمعتبر بودن
  if (minTemp < 0 || minTemp > 80) minTemp = 20;
  if (maxTemp < 0 || maxTemp > 80 || maxTemp <= minTemp) maxTemp = 25;
  if (minHumidity < 0 || minHumidity > 100) minHumidity = 40;
  if (maxHumidity < 0 || maxHumidity > 100 || maxHumidity <= minHumidity) maxHumidity = 60;

  Serial.println("Settings loaded!");
}

void setup() {
  Serial.begin(9600);
  Wire.begin();
  pinMode(relayPin, OUTPUT);
  pinMode(humidifierPin, OUTPUT);
  pinMode(fanPin, OUTPUT);
  pinMode(lightPin, OUTPUT);

  digitalWrite(relayPin, LOW);
  digitalWrite(humidifierPin, LOW);

  if (AHT10.begin(eAHT10Address_Low))
    Serial.println("Init AHT10 Success.");
  else
    Serial.println("Init AHT10 Failure.");

  // بارگذاری تنظیمات از EEPROM
  loadSettings();

  // ایجاد نقطه دسترسی
  WiFi.softAP(ssid, password);
  Serial.println("Access Point Started");
  Serial.print("SSID: ");
  Serial.println(ssid);
  Serial.print("IP Address: ");
  Serial.println(WiFi.softAPIP());
  
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", getHTML());
  });

  server.on("/settemp", HTTP_GET, [](AsyncWebServerRequest *request){
    if (request->hasParam("minTemp")) {
      minTemp = request->getParam("minTemp")->value().toInt();
    }
    if (request->hasParam("maxTemp")) {
      maxTemp = request->getParam("maxTemp")->value().toInt();
    }
    if (request->hasParam("watt")) {
      lampWattage = request->getParam("watt")->value().toInt();
    }
    if (request->hasParam("minHum")) {
      minHumidity = request->getParam("minHum")->value().toInt();
    }
    if (request->hasParam("maxHum")) {
      maxHumidity = request->getParam("maxHum")->value().toInt();
    }
    
    // ذخیره تنظیمات جدید در EEPROM
    saveSettings();
    request->redirect("/");
  });
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    String html = "<html><body>";
    html += "<h1>Control System</h1>";
    html += "<form action='/set' method='POST'>";
    html += "Fan On Time (hours:minutes): <input type='number' name='fanOnHour' min='0' max='23' value='" + String(fanOnHour) + "'> : <input type='number' name='fanOnMin' min='0' max='59' value='" + String(fanOnMin) + "'><br>";
    html += "Fan Off Time (hours:minutes): <input type='number' name='fanOffHour' min='0' max='23' value='" + String(fanOffHour) + "'> : <input type='number' name='fanOffMin' min='0' max='59' value='" + String(fanOffMin) + "'><br>";
    html += "Light On Time (hours:minutes): <input type='number' name='lightOnHour' min='0' max='23' value='" + String(lightOnHour) + "'> : <input type='number' name='lightOnMin' min='0' max='59' value='" + String(lightOnMin) + "'><br>";
    html += "Light Off Time (hours:minutes): <input type='number' name='lightOffHour' min='0' max='23' value='" + String(lightOffHour) + "'> : <input type='number' name='lightOffMin' min='0' max='59' value='" + String(lightOffMin) + "'><br>";
    html += "<input type='submit' value='Set'>";
    html += "</form>";

    // Show the status of the fan and light
    html += "<h2>Status:</h2>";
    html += "<p>Fan: " + String(fanState ? "ON" : "OFF") + "</p>";
    html += "<p>Light: " + String(lightState ? "ON" : "OFF") + "</p>";

    // Display timer information
    html += "<h2>Timer Status:</h2>";
    html += "<p>Seconds: " + String(seconds) + "</p>";
    html += "<p>Minutes: " + String(minutes) + "</p>";
    html += "<p>Hours: " + String(hours) + "</p>";
    html += "<p>Days: " + String(days) + "</p>";
    html += "</body></html>";

    request->send(200, "text/html", html);  // Send the response to the client
  });

  server.on("/set", HTTP_POST, [](AsyncWebServerRequest *request){
    fanOnHour = request->arg("fanOnHour").toInt();
    fanOnMin = request->arg("fanOnMin").toInt();
    fanOffHour = request->arg("fanOffHour").toInt();
    fanOffMin = request->arg("fanOffMin").toInt();
    lightOnHour = request->arg("lightOnHour").toInt();
    lightOnMin = request->arg("lightOnMin").toInt();
    lightOffHour = request->arg("lightOffHour").toInt();
    lightOffMin = request->arg("lightOffMin").toInt();
    saveSettings();

    // Redirect to the main page after saving settings
    request->redirect("/");  // Use request->redirect to redirect the user to the main page
  });

  server.begin();
}

void loop() {
   currentMillis = millis();

  // Calculate time
  if (currentMillis - startMillis >= 1000) {
    startMillis = currentMillis;
    seconds++;

    if (seconds >= 60) {
      seconds = 0;
      minutes++;
    }
    if (minutes >= 60) {
      minutes = 0;
      hours++;
    }
    if (hours >= 24) {
      hours = 0;
      days++;
    }
  }

  // Control the intake fan and light system
  static unsigned long fanTimer = 0;
  static unsigned long lightTimer = 0;

  if (fanState) {
    digitalWrite(fanPin, HIGH);
  } else {
    digitalWrite(fanPin, LOW);
  }

  if (lightState) {
    digitalWrite(lightPin, HIGH);
  } else {
    digitalWrite(lightPin, LOW);
  }

  // Timer for fan and light on/off control
  if (fanState && (millis() - fanTimer >= (fanOnHour * 3600000 + fanOnMin * 60000))) {
    fanState = false;
    fanTimer = millis();
  }
  if (!fanState && (millis() - fanTimer >= (fanOffHour * 3600000 + fanOffMin * 60000))) {
    fanState = true;
    fanTimer = millis();
  }

  if (lightState && (millis() - lightTimer >= (lightOnHour * 3600000 + lightOnMin * 60000))) {
    lightState = false;
    lightTimer = millis();
  }
  if (!lightState && (millis() - lightTimer >= (lightOffHour * 3600000 + lightOffMin * 60000))) {
    lightState = true;
    lightTimer = millis();
  }
}


void readSensor() {
  currentHumidity = AHT10.GetHumidity();
  currentTemp = AHT10.GetTemperature();
  Serial.println("Humidity(%RH):\t\t" + String(currentHumidity) + "%");
  Serial.println("Temperature(℃):\t" + String(currentTemp) + "℃");
}

void controlRelay() {
  if (currentTemp >= maxTemp) { // خاموش کردن رله در دمای بالاتر از حداکثر
    if (relayState) {
      relayState = false;
    }
    digitalWrite(relayPin, LOW);
  } else if (currentTemp < minTemp) { // روشن کردن رله در دمای کمتر از حداقل
    if (!relayState) {
      relayState = true;
    }
    digitalWrite(relayPin, HIGH);
  }
}

void controlHumidifier() {
  if (currentHumidity < minHumidity) {
    if (!humidifierState) {
      humidifierState = true;
      digitalWrite(humidifierPin, HIGH);
    }
  } else if (currentHumidity > maxHumidity) {
    if (humidifierState) {
      humidifierState = false;
      digitalWrite(humidifierPin, LOW);
    }
  }
}

String getHTML() {
  String html = "<html><body><h1>Temperature and Humidity</h1>";
  html += "<p>Temperature: " + String(currentTemp) + " °C</p>";
  html += "<p>Humidity: " + String(currentHumidity) + " %</p>";

  html += "<h2>Settings</h2>";
  html += "<form action=\"/settemp\" method=\"get\">";
  html += "<label for=\"minTemp\">Minimum Temperature (°C):</label>";
  html += "<input type=\"number\" name=\"minTemp\" value=\"" + String(minTemp) + "\" min=\"0\" max=\"80\"><br>";

  html += "<label for=\"maxTemp\">Maximum Temperature (°C):</label>";
  html += "<input type=\"number\" name=\"maxTemp\" value=\"" + String(maxTemp) + "\" min=\"0\" max=\"80\"><br>";

  html += "<label for=\"watt\">Lamp Wattage:</label>";
  html += "<select name=\"watt\" id=\"watt\">";
  for (int i = 100; i <= 1000; i += 100) {
    html += "<option value=\"" + String(i) + "\"" + (i == lampWattage ? " selected" : "") + ">" + String(i) + " W</option>";
  }
  html += "</select><br>";

  html += "<label for=\"minHum\">Minimum Humidity (%):</label>";
  html += "<input type=\"number\" name=\"minHum\" value=\"" + String(minHumidity) + "\" min=\"0\" max=\"100\"><br>";

  html += "<label for=\"maxHum\">Maximum Humidity (%):</label>";
  html += "<input type=\"number\" name=\"maxHum\" value=\"" + String(maxHumidity) + "\" min=\"0\" max=\"100\"><br>";

  html += "<input type=\"submit\" value=\"Update Settings\">";
  html += "</form>";

  html += "<h2>Device Status</h2>";
  html += "<p>Relay: " + String(relayState ? "ON" : "OFF") + "</p>";
  html += "<p>Humidifier: " + String(humidifierState ? "ON" : "OFF") + "</p>";

  html += "</body></html>";
  return html;
}

exit status 1

Compilation error: expected unqualified-id before 'if'

Please pay closer attention to what I ask you to do. If you do not, I will be unable to help you.

paul i use chatgpt to combilne code with your sugestion in 2 seperait page. but in 2 page i lost in put field .

Project 1

Temperature: 814549.00 °C

Humidity: 25514.06 %

Relay: OFF

Humidifier: OFF


Project 2

Fan: ON

Light: OFF


#include <Wire.h>
#include <Thinary_AHT10.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <EEPROM.h>

// AHT10 Sensor
AHT10Class AHT10;

// Web server
AsyncWebServer server(80);

// WiFi settings
const char* ssid = "Combined-Project";
const char* password = "12345678";

// Pins for Project 1
const int relayPin = D5;
const int humidifierPin = D7;

// Pins for Project 2
const int fanPin = D6;
const int lightPin = D0;

// Variables for Project 1
float currentTemp = 0;
float currentHumidity = 0;
int minTemp = 20;
int maxTemp = 25;
int minHumidity = 40;
int maxHumidity = 60;
bool relayState = false;
bool humidifierState = false;

// Variables for Project 2
int fanOnHour = 0, fanOnMin = 1, fanOffHour = 0, fanOffMin = 1;
int lightOnHour = 0, lightOnMin = 1, lightOffHour = 0, lightOffMin = 1;
bool fanState = false, lightState = false;

// EEPROM storage sizes
#define EEPROM_SIZE 20

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

  pinMode(relayPin, OUTPUT);
  pinMode(humidifierPin, OUTPUT);
  pinMode(fanPin, OUTPUT);
  pinMode(lightPin, OUTPUT);

  digitalWrite(relayPin, LOW);
  digitalWrite(humidifierPin, LOW);
  digitalWrite(fanPin, LOW);
  digitalWrite(lightPin, LOW);

  // Initialize AHT10
  if (AHT10.begin(eAHT10Address_Low)) {
    Serial.println("AHT10 Initialized");
  } else {
    Serial.println("AHT10 Initialization Failed");
  }

  // Setup WiFi
  WiFi.softAP(ssid, password);
  Serial.println("Access Point Started");
  Serial.print("SSID: ");
  Serial.println(ssid);
  Serial.print("IP Address: ");
  Serial.println(WiFi.softAPIP());

  // Load settings from EEPROM
  loadSettings();

  // Web server routes
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    String html = "<html><body><h1>Main Menu</h1>";
    html += "<p><a href=\"/project1\">Project 1 (Temperature and Humidity)</a></p>";
    html += "<p><a href=\"/project2\">Project 2 (Fan and Light Timers)</a></p>";
    html += "</body></html>";
    request->send(200, "text/html", html);
  });

  server.on("/project1", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(200, "text/html", getProject1HTML());
  });

  server.on("/project2", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(200, "text/html", getProject2HTML());
  });

  server.begin();
}

void loop() {
  // Periodic updates for sensors and states
  updateProject1();
  updateProject2();
}

// Load settings from EEPROM
void loadSettings() {
  EEPROM.begin(EEPROM_SIZE);
  minTemp = EEPROM.read(0);
  maxTemp = EEPROM.read(1);
  minHumidity = EEPROM.read(2);
  maxHumidity = EEPROM.read(3);
  fanOnHour = EEPROM.read(4);
  fanOnMin = EEPROM.read(5);
  fanOffHour = EEPROM.read(6);
  fanOffMin = EEPROM.read(7);
  lightOnHour = EEPROM.read(8);
  lightOnMin = EEPROM.read(9);
  lightOffHour = EEPROM.read(10);
  lightOffMin = EEPROM.read(11);
  EEPROM.end();
}

// HTML for Project 1
String getProject1HTML() {
  String html = "<html><body><h1>Project 1</h1>";
  html += "<p>Temperature: " + String(currentTemp) + " °C</p>";
  html += "<p>Humidity: " + String(currentHumidity) + " %</p>";
  html += "<p>Relay: " + String(relayState ? "ON" : "OFF") + "</p>";
  html += "<p>Humidifier: " + String(humidifierState ? "ON" : "OFF") + "</p>";
  html += "</body></html>";
  return html;
}

// HTML for Project 2
String getProject2HTML() {
  String html = "<html><body><h1>Project 2</h1>";
  html += "<p>Fan: " + String(fanState ? "ON" : "OFF") + "</p>";
  html += "<p>Light: " + String(lightState ? "ON" : "OFF") + "</p>";
  html += "</body></html>";
  return html;
}

// Update Project 1
void updateProject1() {
  currentTemp = AHT10.GetTemperature();
  currentHumidity = AHT10.GetHumidity();
  relayState = (currentTemp < minTemp);
  digitalWrite(relayPin, relayState ? HIGH : LOW);
  humidifierState = (currentHumidity < minHumidity);
  digitalWrite(humidifierPin, humidifierState ? HIGH : LOW);
}

// Update Project 2
void updateProject2() {
  unsigned long currentMillis = millis() / 60000;  // Convert to minutes
  int currentHour = currentMillis / 60 % 24;
  int currentMinute = currentMillis % 60;

  // Fan control
  if ((currentHour == fanOnHour && currentMinute >= fanOnMin) ||
      (currentHour == fanOffHour && currentMinute < fanOffMin)) {
    fanState = true;
    digitalWrite(fanPin, HIGH);
  } else {
    fanState = false;
    digitalWrite(fanPin, LOW);
  }

  // Light control
  if ((currentHour == lightOnHour && currentMinute >= lightOnMin) ||
      (currentHour == lightOffHour && currentMinute < lightOffMin)) {
    lightState = true;
    digitalWrite(lightPin, HIGH);
  } else {
    lightState = false;
    digitalWrite(lightPin, LOW);
  }
}

how fix that . any sugestion from you , can help .

I will not help you fix code from Chat GPT. But I will help you fix your attempt to merge the code if you do as I asked.

thanks paul i coming back to you after figure out how do your sugestion on code . :smiling_face_with_tear:

i urgently need help my veggies in greenhouse need help . :woozy_face: :woozy_face: :woozy_face:

Hi everyone,

I’m working on a project with an ESP8266 that involves controlling a fan and a light using independent timers. The on/off times for both are configured through a web interface. While the code generally works, I’m encountering an unexpected behavior when setting different on/off durations for the fan and light.

For example:

  • Fan: 1 minute ON, 2 minutes OFF
  • Light: 1 minute ON, 12 minutes OFF

The issue:

  • When the fan turns ON, the light turns OFF, and vice versa.
  • However, if I set the same on/off duration for both (e.g., 1 minute), everything works fine.

I’ve used millis() for timing and tried to keep the timers for the fan and light independent. The settings are also stored in EEPROM.

My questions:

  • Could this be an issue with how the timers are managed?
  • Do I need to adjust how I compare the time or any part of the code logic?

Here’s the code for reference:

cpp

Copy code

#include <Wire.h>
#include <Thinary_AHT10.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <EEPROM.h>  // Include the EEPROM library

AHT10Class AHT10;
AsyncWebServer server(80);

// Network settings
const char* ssid = "ESP8266-Access-Point";  // Set the SSID of the Access Point
const char* password = "123456789";  // Set the password for the Access Point

// Pin definitions
const int fanPin = D6;
const int lightPin = D0;

// On/off times in hours and minutes
int fanOnHour = 0;
int fanOnMin = 1;
int fanOffHour = 0;
int fanOffMin = 1;
int lightOnHour = 0;
int lightOnMin = 1;
int lightOffHour = 0;
int lightOffMin = 1;

// Timer settings
unsigned long startMillis;
unsigned long currentMillis;
int seconds = 0;
int minutes = 0;
int hours = 0;
int days = 0;

// Status of fan and light
bool fanState = false;
bool lightState = false;

// EEPROM storage
void loadSettings() {
  EEPROM.begin(512);
  fanOnHour = EEPROM.read(0);
  fanOnMin = EEPROM.read(1);
  fanOffHour = EEPROM.read(2);
  fanOffMin = EEPROM.read(3);
  lightOnHour = EEPROM.read(4);
  lightOnMin = EEPROM.read(5);
  lightOffHour = EEPROM.read(6);
  lightOffMin = EEPROM.read(7);
  EEPROM.end();
}

void saveSettings() {
  EEPROM.begin(512);
  EEPROM.write(0, fanOnHour);
  EEPROM.write(1, fanOnMin);
  EEPROM.write(2, fanOffHour);
  EEPROM.write(3, fanOffMin);
  EEPROM.write(4, lightOnHour);
  EEPROM.write(5, lightOnMin);
  EEPROM.write(6, lightOffHour);
  EEPROM.write(7, lightOffMin);
  EEPROM.end();
}

// Wi-Fi and Web server setup
void setupWiFi() {
  // Start the Access Point
  WiFi.softAP(ssid, password);  // Set the SSID and password for the AP

  // Print the IP address assigned to the ESP8266
  Serial.println("Access Point Started");
  Serial.print("IP Address: ");
  Serial.println(WiFi.softAPIP());

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    String html = "<html><body>";
    html += "<h1>Control System</h1>";
    html += "<form action='/set' method='POST'>";
    html += "Fan On Time (hours:minutes): <input type='number' name='fanOnHour' min='0' max='23' value='" + String(fanOnHour) + "'> : <input type='number' name='fanOnMin' min='0' max='59' value='" + String(fanOnMin) + "'><br>";
    html += "Fan Off Time (hours:minutes): <input type='number' name='fanOffHour' min='0' max='23' value='" + String(fanOffHour) + "'> : <input type='number' name='fanOffMin' min='0' max='59' value='" + String(fanOffMin) + "'><br>";
    html += "Light On Time (hours:minutes): <input type='number' name='lightOnHour' min='0' max='23' value='" + String(lightOnHour) + "'> : <input type='number' name='lightOnMin' min='0' max='59' value='" + String(lightOnMin) + "'><br>";
    html += "Light Off Time (hours:minutes): <input type='number' name='lightOffHour' min='0' max='23' value='" + String(lightOffHour) + "'> : <input type='number' name='lightOffMin' min='0' max='59' value='" + String(lightOffMin) + "'><br>";
    html += "<input type='submit' value='Set'>";
    html += "</form>";

    // Show the status of the fan and light
    html += "<h2>Status:</h2>";
    html += "<p>Fan: " + String(fanState ? "ON" : "OFF") + "</p>";
    html += "<p>Light: " + String(lightState ? "ON" : "OFF") + "</p>";

    // Display timer information
    html += "<h2>Timer Status:</h2>";
    html += "<p>Seconds: " + String(seconds) + "</p>";
    html += "<p>Minutes: " + String(minutes) + "</p>";
    html += "<p>Hours: " + String(hours) + "</p>";
    html += "<p>Days: " + String(days) + "</p>";
    html += "</body></html>";

    request->send(200, "text/html", html);  // Send the response to the client
  });

  server.on("/set", HTTP_POST, [](AsyncWebServerRequest *request){
    fanOnHour = request->arg("fanOnHour").toInt();
    fanOnMin = request->arg("fanOnMin").toInt();
    fanOffHour = request->arg("fanOffHour").toInt();
    fanOffMin = request->arg("fanOffMin").toInt();
    lightOnHour = request->arg("lightOnHour").toInt();
    lightOnMin = request->arg("lightOnMin").toInt();
    lightOffHour = request->arg("lightOffHour").toInt();
    lightOffMin = request->arg("lightOffMin").toInt();
    saveSettings();

    // Redirect to the main page after saving settings
    request->redirect("/");  // Use request->redirect to redirect the user to the main page
  });

  server.begin();
}

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

  pinMode(fanPin, OUTPUT);
  pinMode(lightPin, OUTPUT);

  loadSettings();  // Load settings from EEPROM

  setupWiFi();

  startMillis = millis();
}

void loop() {
  currentMillis = millis();

  // Calculate time
  if (currentMillis - startMillis >= 1000) {
    startMillis = currentMillis;
    seconds++;

    if (seconds >= 60) {
      seconds = 0;
      minutes++;
    }
    if (minutes >= 60) {
      minutes = 0;
      hours++;
    }
    if (hours >= 24) {
      hours = 0;
      days++;
    }
  }

  // Fan control logic
  static bool fanState = false;
  static unsigned long lastFanChangeMillis = 0;

  if (fanState) {
    if (currentMillis - lastFanChangeMillis >= (fanOnHour * 3600000 + fanOnMin * 60000)) {
      fanState = false;
      lastFanChangeMillis = currentMillis;
    }
  } else {
    if (currentMillis - lastFanChangeMillis >= (fanOffHour * 3600000 + fanOffMin * 60000)) {
      fanState = true;
      lastFanChangeMillis = currentMillis;
    }
  }

  digitalWrite(fanPin, fanState ? HIGH : LOW);

  // Light control logic
  static bool lightState = false;
  static unsigned long lastLightChangeMillis = 0;

  if (lightState) {
    if (currentMillis - lastLightChangeMillis >= (lightOnHour * 3600000 + lightOnMin * 60000)) {
      lightState = false;
      lastLightChangeMillis = currentMillis;
    }
  } else {
    if (currentMillis - lastLightChangeMillis >= (lightOffHour * 3600000 + lightOffMin * 60000)) {
      lightState = true;
      lastLightChangeMillis = currentMillis;
    }
  }

  digitalWrite(lightPin, lightState ? HIGH : LOW);
}

I’d greatly appreciate any advice or suggestions from those with experience in similar projects. Thanks in advance for your help!

int fanOnHour = 0;

An int on an ESP8266 is stored in 4 bytes of memory

fanOnHour = EEPROM.read(0);

EEPROM.read() reads a single byte into memory

Can you see a problem ?

Consider using EEPROM.get() to read the int value but be careful when storing the int data that you have spaced the variables apart in EEPROM to avoid variables overlapping

Would it work using bytes instead of ints ?

It looks like it should but I didn't examine the code in detail

thanks i think its works , kind of but i must test on 8266 for a day until i am be sure about .

#include <Wire.h>
#include <Thinary_AHT10.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <EEPROM.h>  // Include the EEPROM library

AHT10Class AHT10;
AsyncWebServer server(80);

// Network settings
const char* ssid = "ESP8266-Access-Point";  // Set the SSID of the Access Point
const char* password = "123456789";  // Set the password for the Access Point

// Pin definitions
const int fanPin = D6;
const int lightPin = D0;

// On/off times in hours and minutes
int fanOnHour = 0;
int fanOnMin = 1;
int fanOffHour = 0;
int fanOffMin = 1;
int lightOnHour = 0;
int lightOnMin = 1;
int lightOffHour = 0;
int lightOffMin = 1;

// Timer settings
unsigned long startMillis;
unsigned long currentMillis;
int seconds = 0;
int minutes = 0;
int hours = 0;
int days = 0;

// Status of fan and light
bool fanState = false;
bool lightState = false;

// EEPROM storage
void loadSettings() {
  EEPROM.begin(512);
  EEPROM.get(0, fanOnHour);
  EEPROM.get(4, fanOnMin);
  EEPROM.get(8, fanOffHour);
  EEPROM.get(12, fanOffMin);
  EEPROM.get(16, lightOnHour);
  EEPROM.get(20, lightOnMin);
  EEPROM.get(24, lightOffHour);
  EEPROM.get(28, lightOffMin);
  EEPROM.end();
}

void saveSettings() {
  EEPROM.begin(512);
  EEPROM.put(0, fanOnHour);
  EEPROM.put(4, fanOnMin);
  EEPROM.put(8, fanOffHour);
  EEPROM.put(12, fanOffMin);
  EEPROM.put(16, lightOnHour);
  EEPROM.put(20, lightOnMin);
  EEPROM.put(24, lightOffHour);
  EEPROM.put(28, lightOffMin);
  EEPROM.commit();
  EEPROM.end();
}


// Wi-Fi and Web server setup
void setupWiFi() {
  // Start the Access Point
  WiFi.softAP(ssid, password);  // Set the SSID and password for the AP

  // Print the IP address assigned to the ESP8266
  Serial.println("Access Point Started");
  Serial.print("IP Address: ");
  Serial.println(WiFi.softAPIP());

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    String html = "<html><body>";
    html += "<h1>Control System</h1>";
    html += "<form action='/set' method='POST'>";
    html += "Fan On Time (hours:minutes): <input type='number' name='fanOnHour' min='0' max='23' value='" + String(fanOnHour) + "'> : <input type='number' name='fanOnMin' min='0' max='59' value='" + String(fanOnMin) + "'><br>";
    html += "Fan Off Time (hours:minutes): <input type='number' name='fanOffHour' min='0' max='23' value='" + String(fanOffHour) + "'> : <input type='number' name='fanOffMin' min='0' max='59' value='" + String(fanOffMin) + "'><br>";
    html += "Light On Time (hours:minutes): <input type='number' name='lightOnHour' min='0' max='23' value='" + String(lightOnHour) + "'> : <input type='number' name='lightOnMin' min='0' max='59' value='" + String(lightOnMin) + "'><br>";
    html += "Light Off Time (hours:minutes): <input type='number' name='lightOffHour' min='0' max='23' value='" + String(lightOffHour) + "'> : <input type='number' name='lightOffMin' min='0' max='59' value='" + String(lightOffMin) + "'><br>";
    html += "<input type='submit' value='Set'>";
    html += "</form>";

    // Show the status of the fan and light
    html += "<h2>Status:</h2>";
    html += "<p>Fan: " + String(fanState ? "ON" : "OFF") + "</p>";
    html += "<p>Light: " + String(lightState ? "ON" : "OFF") + "</p>";

    // Display timer information
    html += "<h2>Timer Status:</h2>";
    html += "<p>Seconds: " + String(seconds) + "</p>";
    html += "<p>Minutes: " + String(minutes) + "</p>";
    html += "<p>Hours: " + String(hours) + "</p>";
    html += "<p>Days: " + String(days) + "</p>";
    html += "</body></html>";

    request->send(200, "text/html", html);  // Send the response to the client
  });

  server.on("/set", HTTP_POST, [](AsyncWebServerRequest *request){
    fanOnHour = request->arg("fanOnHour").toInt();
    fanOnMin = request->arg("fanOnMin").toInt();
    fanOffHour = request->arg("fanOffHour").toInt();
    fanOffMin = request->arg("fanOffMin").toInt();
    lightOnHour = request->arg("lightOnHour").toInt();
    lightOnMin = request->arg("lightOnMin").toInt();
    lightOffHour = request->arg("lightOffHour").toInt();
    lightOffMin = request->arg("lightOffMin").toInt();
    saveSettings();

    // Redirect to the main page after saving settings
    request->redirect("/");  // Use request->redirect to redirect the user to the main page
  });

  server.begin();
}

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

  pinMode(fanPin, OUTPUT);
  pinMode(lightPin, OUTPUT);

  loadSettings();  // Load settings from EEPROM

  setupWiFi();

  startMillis = millis();
}

void loop() {
  currentMillis = millis();

  // Calculate time
  if (currentMillis - startMillis >= 1000) {
    startMillis = currentMillis;
    seconds++;

    if (seconds >= 60) {
      seconds = 0;
      minutes++;
    }
    if (minutes >= 60) {
      minutes = 0;
      hours++;
    }
    if (hours >= 24) {
      hours = 0;
      days++;
    }
  }

  // Fan control logic
  static bool fanState = false;
  static unsigned long lastFanChangeMillis = 0;

  if (fanState) {
    if (currentMillis - lastFanChangeMillis >= (fanOnHour * 3600000 + fanOnMin * 60000)) {
      fanState = false;
      lastFanChangeMillis = currentMillis;
    }
  } else {
    if (currentMillis - lastFanChangeMillis >= (fanOffHour * 3600000 + fanOffMin * 60000)) {
      fanState = true;
      lastFanChangeMillis = currentMillis;
    }
  }

  digitalWrite(fanPin, fanState ? HIGH : LOW);

  // Light control logic
  static bool lightState = false;
  static unsigned long lastLightChangeMillis = 0;

  if (lightState) {
    if (currentMillis - lastLightChangeMillis >= (lightOnHour * 3600000 + lightOnMin * 60000)) {
      lightState = false;
      lastLightChangeMillis = currentMillis;
    }
  } else {
    if (currentMillis - lastLightChangeMillis >= (lightOffHour * 3600000 + lightOffMin * 60000)) {
      lightState = true;
      lastLightChangeMillis = currentMillis;
    }
  }

  digitalWrite(lightPin, lightState ? HIGH : LOW);
}

@1tondar2025 ,

Your two or more topics on the same or similar subject have been merged.

Please do not duplicate your questions as doing so wastes the time and effort of the volunteers trying to help you as they are then answering the same thing in different places.

Please create one topic only for your question and choose the forum category carefully. If you have multiple questions about the same project then please ask your questions in the one topic as the answers to one question provide useful context for the others, and also you won’t have to keep explaining your project repeatedly.

Repeated duplicate posting could result in a temporary or permanent ban from the forum.

Could you take a few moments to Learn How To Use The Forum

It will help you get the best out of the forum in the future.

Thank you.

Good progress @1tondar2025.

It would be more easy and safe to use a struct to hold all the configuration data.

// On/off times in hours and minutes
struct configuration {
  int fanOnHour = 0;
  int fanOnMin = 1;
  int fanOffHour = 0;
  int fanOffMin = 1;
  int lightOnHour = 0;
  int lightOnMin = 1;
  int lightOffHour = 0;
  int lightOffMin = 1;
}

// EEPROM storage
void loadSettings() {
  EEPROM.begin(512);
  EEPROM.get(0, configuration);
  EEPROM.end();
}

void saveSettings() {
  EEPROM.begin(512);
  EEPROM.put(0, configuration);
  EEPROM.commit();
  EEPROM.end();
}

Everywhere else, need to access those variables from the struct, for example:

  server.on("/set", HTTP_POST, [](AsyncWebServerRequest *request){
    configuration.fanOnHour = request->arg("fanOnHour").toInt();
    fanOnMin = request->arg("fanOnMin").toInt();

Hi everyone,

I’m working on a project with ESP8266 that involves controlling a fan and a light system based on specific time schedules. I’ve used the EEPROM library to store timing settings so the system can restore its state after a power outage.

The main issue I’m facing is that after a power cut and restart, the light system doesn’t restore properly. Even if the scheduled time for the light is not yet over, the light remains off. However, the fan control works perfectly and follows the schedule as expected.

### Time Schedule:

* **Fan On Time (hours:minutes):** 0:1
* **Fan Off Time (hours:minutes):** 0:15
* **Light On Time (hours:minutes):** 6:30
* **Light Off Time (hours:minutes):** 10:19

### Current System Status:

* **Fan:** OFF
* **Light:** ON
* **Timer Status:**
  * **Seconds:** 26
  * **Minutes:** 18
  * **Hours:** 2
  * **Days:** 0

### Observed Issue:

After restarting, even though the current time (2:18) is outside the light's ON schedule (6:30 to 10:19), the light remains off.

I’ve tested the system multiple times with different settings, but the issue persists. Could it be a problem with how the light system’s state is stored or restored from EEPROM?

#include <Wire.h>
#include <Thinary_AHT10.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <EEPROM.h>  // Include the EEPROM library

AHT10Class AHT10;
AsyncWebServer server(80);

// Network settings
const char* ssid = "ESP8266-Access-Point";  // Set the SSID of the Access Point
const char* password = "123456789";  // Set the password for the Access Point

// Pin definitions
const int fanPin = D6;
const int lightPin = D0;

// On/off times in hours and minutes
int fanOnHour = 0;
int fanOnMin = 1;
int fanOffHour = 0;
int fanOffMin = 1;
int lightOnHour = 0;
int lightOnMin = 1;
int lightOffHour = 0;
int lightOffMin = 1;

// Timer settings
unsigned long startMillis;
unsigned long currentMillis;
int seconds = 0;
int minutes = 0;
int hours = 0;
int days = 0;

// Status of fan and light
bool fanState = false;
bool lightState = false;

// EEPROM storage
void loadSettings() {
  EEPROM.begin(512);
  fanOnHour = EEPROM.read(0);
  fanOnMin = EEPROM.read(1);
  fanOffHour = EEPROM.read(2);
  fanOffMin = EEPROM.read(3);
  lightOnHour = EEPROM.read(4);
  lightOnMin = EEPROM.read(5);
  lightOffHour = EEPROM.read(6);
  lightOffMin = EEPROM.read(7);

  // Load current time from EEPROM
  hours = EEPROM.read(8);
  minutes = EEPROM.read(9);
  seconds = EEPROM.read(10);
  fanState = EEPROM.read(11);
  lightState = EEPROM.read(12);

  EEPROM.end();
}

void saveSettings() {
  EEPROM.begin(512);
  EEPROM.write(0, fanOnHour);
  EEPROM.write(1, fanOnMin);
  EEPROM.write(2, fanOffHour);
  EEPROM.write(3, fanOffMin);
  EEPROM.write(4, lightOnHour);
  EEPROM.write(5, lightOnMin);
  EEPROM.write(6, lightOffHour);
  EEPROM.write(7, lightOffMin);

  // Save current time and states
  EEPROM.write(8, hours);
  EEPROM.write(9, minutes);
  EEPROM.write(10, seconds);
  EEPROM.write(11, fanState);
  EEPROM.write(12, lightState);

  EEPROM.end();
}

// Wi-Fi and Web server setup
void setupWiFi() {
  // Start the Access Point
  WiFi.softAP(ssid, password);  // Set the SSID and password for the AP

  // Print the IP address assigned to the ESP8266
  Serial.println("Access Point Started");
  Serial.print("IP Address: ");
  Serial.println(WiFi.softAPIP());

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    String html = "<html><body>";
    html += "<h1>Control System</h1>";
    html += "<form action='/set' method='POST'>";
    html += "Fan On Time (hours:minutes): <input type='number' name='fanOnHour' min='0' max='23' value='" + String(fanOnHour) + "'> : <input type='number' name='fanOnMin' min='0' max='59' value='" + String(fanOnMin) + "'><br>";
    html += "Fan Off Time (hours:minutes): <input type='number' name='fanOffHour' min='0' max='23' value='" + String(fanOffHour) + "'> : <input type='number' name='fanOffMin' min='0' max='59' value='" + String(fanOffMin) + "'><br>";
    html += "Light On Time (hours:minutes): <input type='number' name='lightOnHour' min='0' max='23' value='" + String(lightOnHour) + "'> : <input type='number' name='lightOnMin' min='0' max='59' value='" + String(lightOnMin) + "'><br>";
    html += "Light Off Time (hours:minutes): <input type='number' name='lightOffHour' min='0' max='23' value='" + String(lightOffHour) + "'> : <input type='number' name='lightOffMin' min='0' max='59' value='" + String(lightOffMin) + "'><br>";
    html += "<input type='submit' value='Set'>";
    html += "</form>";

    // Show the status of the fan and light
    html += "<h2>Status:</h2>";
    html += "<p>Fan: " + String(fanState ? "ON" : "OFF") + "</p>";
    html += "<p>Light: " + String(lightState ? "ON" : "OFF") + "</p>";

    // Display timer information
    html += "<h2>Timer Status:</h2>";
    html += "<p>Seconds: " + String(seconds) + "</p>";
    html += "<p>Minutes: " + String(minutes) + "</p>";
    html += "<p>Hours: " + String(hours) + "</p>";
    html += "<p>Days: " + String(days) + "</p>";
    html += "</body></html>";

    request->send(200, "text/html", html);  // Send the response to the client
  });

  server.on("/set", HTTP_POST, [](AsyncWebServerRequest *request){
    fanOnHour = request->arg("fanOnHour").toInt();
    fanOnMin = request->arg("fanOnMin").toInt();
    fanOffHour = request->arg("fanOffHour").toInt();
    fanOffMin = request->arg("fanOffMin").toInt();
    lightOnHour = request->arg("lightOnHour").toInt();
    lightOnMin = request->arg("lightOnMin").toInt();
    lightOffHour = request->arg("lightOffHour").toInt();
    lightOffMin = request->arg("lightOffMin").toInt();
    saveSettings();

    // Redirect to the main page after saving settings
    request->redirect("/");  // Use request->redirect to redirect the user to the main page
  });

  server.begin();
}

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

  pinMode(fanPin, OUTPUT);
  pinMode(lightPin, OUTPUT);

  loadSettings();  // Load settings from EEPROM

  setupWiFi();

  startMillis = millis();
}

void loop() {
  currentMillis = millis();

  // Calculate time
  if (currentMillis - startMillis >= 1000) {
    startMillis = currentMillis;
    seconds++;

    if (seconds >= 60) {
      seconds = 0;
      minutes++;
    }
    if (minutes >= 60) {
      minutes = 0;
      hours++;
    }
    if (hours >= 24) {
      hours = 0;
      days++;
    }

    // Save current time periodically (every minute)
    saveSettings();
  }

  // Fan control logic
  static bool fanState = false;
  static unsigned long lastFanChangeMillis = 0;

  if (fanState) {
    if (currentMillis - lastFanChangeMillis >= (fanOnHour * 3600000 + fanOnMin * 60000)) {
      fanState = false;
      lastFanChangeMillis = currentMillis;
    }
  } else {
    if (currentMillis - lastFanChangeMillis >= (fanOffHour * 3600000 + fanOffMin * 60000)) {
      fanState = true;
      lastFanChangeMillis = currentMillis;
    }
  }

  digitalWrite(fanPin, fanState ? HIGH : LOW);

  // Light control logic
  static bool lightState = false;
  static unsigned long lastLightChangeMillis = 0;

  if (lightState) {
    if (currentMillis - lastLightChangeMillis >= (lightOnHour * 3600000 + lightOnMin * 60000)) {
      lightState = false;
      lastLightChangeMillis = currentMillis;
    }
  } else {
    if (currentMillis - lastLightChangeMillis >= (lightOffHour * 3600000 + lightOffMin * 60000)) {
      lightState = true;
      lastLightChangeMillis = currentMillis;
    }
  }

  digitalWrite(lightPin, lightState ? HIGH : LOW);
}

thank you . i am doing it from now

I seem to remember pointing out previously that an int on the ESP8266 uses 4 bytes of storage but EEPROM.read() reads only a single byte and EEPROM.write() reads only a single byte

Is this a duplicate of another of your topics ?

If so, then please explain why it should not be deleted