still working on first release. ( simple release - home kind )

CODE:






#include <time.h>
// Define globals
const float VCC = 3.3; // ESP32 supply voltage
const int ADC_MAX = 4095; // 12-bit ADC resolution
// Thermal sensor variables
const float THERM_R0 = 78000.0; // Thermistor resistance at T0 (e.g., 10kΩ)
const float THERM_T = 298.15; // T0 in Kelvin (25°C + 273.15)
const float THERM_B_VALUE = 4100.0; // Thermistor's Beta value (from datasheet)
const float THERM_SERIES_RESISTOR = 50000; // Fixed resistor value
//
const int PIN_THERM = 34; // ADC pin for thermal sensor/diode / analog input
const int PIN_MOISTURE = 35; // ADC pin for moisture sensor / analog input
const int PIN_PUMP = 25; // water pump / digital output
const int PIN_ESTUFA = 23;
const int PIN_LED = 27;
const int PIN_FAN = 26;
//
int ct = 0; // current time in seconds
int ctDay = 3600*24; // seconds of day
int curDay = 0; // 0 = day1, 1=day2... until 6=day7 and repeat to 0
int cntDay = 0, chkDay=0;
int delayValue = 50; // sleep of main loop 20-1000ms
// statistic counting variables
int cnt = 0;
int cnt_delay = 0;
int cnt_loop = 0;
int pos=0;
//
int cntFailTemp = 0;
//
int heat_start = false;
int heat_done = false;
int heat_count = 0;
int heat_last = 0; // ct
//
int fan_start = false;
int fan_done = false;
int fan_count = 0;
int fan_last = 0;
//
time_t currentTime;
struct tm timeinfo;

//
struct FanRun {
 int timeON = 0;
 int timeOFF = 0;
    int ct_start = -1;
    //bool start = false;
    //bool done = false;
    //int count = 0;
};
struct FanRun afr[10];

//
struct Days {
  int dayHours = 18; // hours of light per day
  int dayTemperature = 28; // celsious at day
  int nightTemperature = 25; // celsious at night
};
struct Days timetable[6]; // time table for 7days in a week
//--
//
void get_moisture() {
  int val = analogRead(PIN_MOISTURE);
  Serial.print("Moisture val: ");
  Serial.println(val);
}
//
float get_thermal() {
  int val = analogRead(PIN_THERM);
  
  // 1. Calculate Voltage at ADC Pin (Vout)
  float vout = (float)val * (VCC / ADC_MAX);

  // 2. Calculate Thermistor Resistance (Rth) using Voltage Divider
  // Rth = R_series * (Vout / (VCC - Vout))
  float r_th = THERM_SERIES_RESISTOR * (vout / (VCC - vout));
  
  // 3. Calculate Temperature (Kelvin) using Beta Equation
  // 1/T = 1/T0 + (1/B) * ln(Rth/R0)
  float temp_kelvin = 1.0 / ((1.0 / THERM_T) - (1.0 / THERM_B_VALUE) * log(r_th / THERM_R0));

  // 4. Convert Kelvin to Celsius
  float temp_celsius = temp_kelvin - 273.15;
  return temp_celsius;
}

//
void fan_on(int timeON, int timeOFF) {
  //
  if( fan_count==0 ) {
 // Turn fan on
 Serial.println("Turn fan on for Xsec");
 fan_count = ct+timeON;
 fan_start = true;
 fan_done = false;
 digitalWrite(PIN_FAN,LOW);
  }
  else if( fan_count < 0 ) {
 Serial.println("Waiting for fan...");
 if( cnt_delay>=1000) fan_count++;
  }
  else if( fan_count > ct ) {
 Serial.println("Waiting for fan to turn it off...");
  }
  else if( fan_count <= ct && fan_done==false ) {
 Serial.println("Turning off fan...");
 fan_off();
  }
  else if( ct >= fan_count ) {
 // Turn fan off
 Serial.println("Setting Turn fan off for Xsec");
 fan_count = timeOFF;
  }
}
//
void fan_off() {
 fan_done = true;
 fan_start = false;
 fan_count = 0;
 fan_last = ct;
 digitalWrite(PIN_FAN,HIGH);
}

//
void heat_on(int timeON, int timeOFF) {
  //
  if( heat_count==0 ) {
 // Turn fan on
 Serial.println("Turn heat on for Xsec");
 heat_count = ct+timeON;
 heat_start = true;
 heat_done = false;
 digitalWrite(PIN_ESTUFA,LOW);
  }
  else if( heat_count < 0 ) {
 Serial.println("Waiting for heat...");
 if( cnt_delay>=1000) heat_count++;
  }
  else if( heat_count > ct ) {
 Serial.println("Waiting for heat to turn it off...");
  }
  else if( heat_count <= ct && heat_done==false ) {
   Serial.println("Turning off heat...");
   heat_off();
  }
  else if( ct >= heat_count ) {
 // Turn heat off
 Serial.println("Setting Turn heat off for Xsec");
 heat_count = timeOFF;
  }
}
//
void heat_off() {
 heat_done = true;
 heat_start = false;
 heat_count = 0;
 heat_last = ct;
 digitalWrite(PIN_ESTUFA,HIGH);
}
// Configure setup
void setup() {
  delay(500);
  //
  Serial.begin(115200);
  //--
  //
  pinMode(PIN_FAN,OUTPUT); // led
  digitalWrite(PIN_FAN,HIGH); // off

  // Light LED
  pinMode(PIN_LED,OUTPUT);
  digitalWrite(PIN_LED,HIGH);

  // WATER PUMP - off
  pinMode(PIN_PUMP,OUTPUT);
  digitalWrite(PIN_PUMP,HIGH);

  // ESTUFA - HEATER
  pinMode(PIN_ESTUFA,OUTPUT);
  digitalWrite(PIN_ESTUFA,HIGH); // HIGH = Off for Relay
  //digitalWrite(PIN_ESTUFA,LOW);
  // MOISTURE SensOr - problem!
  /*analogWrite(32,500);
  pinMode(32,OUTPUT); // led
  digitalWrite(32,LOW); // off*/

  // Define timetable for a week
  timetable[0] = (Days){18,28,25};
  timetable[1] = (Days){18,28,25};
  timetable[2] = (Days){18,28,25};
  timetable[3] = (Days){18,28,25};
  timetable[4] = (Days){18,28,25};
  timetable[5] = (Days){18,28,25};
  timetable[6] = (Days){18,28,25};
  // start_ts, start, done
  afr[0] = (FanRun){10, false, false};
  
  /*
   * time_t t = mktime(&TimeInfo);
    struct timeval tnow = { .tv_sec = t };
    settimeofday(&tnow, NULL);
    localtime_r(&t, &timeinfo);
    * */
    /*timeinfo.tm_hour = 10;
    timeinfo.tm_min = 10;
    timeinfo.tm_sec = 0;
    currentTime = mktime(&timeinfo);
    //struct timeval tnow = { .tv_sec = currentTime };
    //settimeofday(&tnow, NULL);
    localtime_r(&currentTime, &timeinfo);
    char buffer[64];
 strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeinfo);
 Serial.println(buffer);*/
}



// Program loop
void loop() {
 // Get current time as seconds since the Unix epoch (January 1, 1970)
 //time_t currentTime = time(nullptr); // Note: nullptr is valid in Arduino for C++11+
 currentTime = time(&currentTime); // Note: nullptr is valid in Arduino for C++11+
 ct = currentTime;
 cntDay = (ct/ctDay);
 // reset current time to zerro after day 7 is finished
 if( curDay>6 ) {
  Serial.println("Weekend is over. Roots should be out...");
  curDay = 0;
 }
 if( chkDay!=cntDay) {
  chkDay=cntDay;
  curDay++;
 }
 //
 Days ttable = timetable[curDay];
 // Print by second
 if( cnt_delay==1000 ) {
  // calculate secunds of light per day depend on dayHours
  int sol = (60*60)*ttable.dayHours; // 60sec * 60sec = 1hour of sec * dayHours
  int dtemp = ttable.dayTemperature;
  int ntemp = ttable.nightTemperature;
  
  // day ct. Useful for days 2-7
  //int dct = (curDay * ctDay)-ct;
  int dct = ct;
  if( curDay>0 ) dct = (curDay * ctDay)-ct;
  
  // Convert to local time
  struct tm *timeInfo = localtime(&currentTime);
  
  // Format the timestamp
  char buffer[64];
  strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeInfo);
  
  Serial.println(buffer);
  Serial.println(currentTime);
  
  //
  float temp = get_thermal();
  
  // DEBUG
  char tmp[100];
  sprintf(tmp,"Loop cft: %i, cd: %i, sol: %i, t: %f, dct: %i, ct: %i, pos: %i, cnt: %i, cnt_loop: %i", cntFailTemp, curDay, sol, temp, dct, ct, pos, cnt, cnt_loop);
  Serial.println(tmp);
  
  // CHECK SOL
  if( dct<sol ) { // Should be LIGHT
   
  }
  else { // Should be NIGHT
   
  }
  // TEST HEAT
  if( heat_last==0 || ct<=100 ) {
   heat_on(100,-100);
   if( (fan_last+3)<ct ) {
    fan_on(2,-3);
   }
  }
  // STOP HEAT if STILL RUNNING (to be sure)
  if( ct>100 ) {
   if( !heat_done ) {
    heat_off();
   }
   if( !fan_done ) {
    fan_off();
   }
  }
 }
  
  // Reset cnd on 25 or X
  if( cnt==(1000/delayValue) ) {
 pos+=1;
 cnt=0;
 cnt_loop=0;
  }

  // Count cnt every second. Important variables: cnt_delay and delayValue
  if( cnt_delay>= 1000 ) {
 cnt_delay = 0;
 cnt += 1;
  }
  cnt_delay += delayValue;
  cnt_loop+=1;
  //
  delay(delayValue);
}