Time field return with problems

Guys... I'm having a lot of trouble solving a problem. In this loop, I need to count the remaining time for the phase but I am not able to. In this part:

      unsigned long elapsedTimeInSeconds = (targetTime - millis()) / 1000UL;
      Serial.println("Time passing: ");
      Serial.println(elapsedTimeInSeconds);

the return is being a big number:
4294905

I've tried everything but it doesn't work. What could be wrong?

This is the complete code:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <FS.h>
#include "secrets.h"

const char* ssid = STASSID;
const char* pass = STAPSK;

// Sensor de temperatura conectado na GPIO 4 / D2
#define ONE_WIRE_BUS 4

// Pinos do relê
#define HEATER_RELAY_PIN 5
#define COOLER_RELAY_PIN 4

// Hysteresis da temperatura
#define HYSTERESIS 0.4

// Web server
ESP8266WebServer server(80);

// Sensor de temperatura
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Temperaturas e tempos
struct TemperatureData {
  float temperature;
  unsigned long time;
};

const int MAX_TEMPERATURES = 15; // Limite de 15 passos
TemperatureData temperatureData[MAX_TEMPERATURES];
int numTemperatures = 0;
int currentTemperatureIndex = 0;
bool fermentationStarted = false;
unsigned long targetTime;
unsigned long remainingTime;
unsigned long elapsedTime;
  
// Helper function to convert float to string with given precision
String floatToString(float value, int precision) {
  char buffer[20];
  sprintf(buffer, "%.*f", precision, value);
  return String(buffer);
}

// Load temperature data from file
void loadTemperatureData() {
  if (SPIFFS.begin()) {
    if (SPIFFS.exists("/temperatures.txt")) {
      File file = SPIFFS.open("/temperatures.txt", "r");
      if (file) {
        numTemperatures = 0;
        while (file.available() && numTemperatures < MAX_TEMPERATURES) {
          String line = file.readStringUntil('\n');
          int separatorIndex = line.indexOf(',');
          if (separatorIndex != -1) {
            temperatureData[numTemperatures].temperature = line.substring(0, separatorIndex).toFloat();
            temperatureData[numTemperatures].time = line.substring(separatorIndex + 1).toInt();
            numTemperatures++;
          }
        }
        file.close();
      }
    }
    SPIFFS.end();
  }
}

// Save temperature data to file
void saveTemperatureData() {
  if (SPIFFS.begin()) {
    File file = SPIFFS.open("/temperatures.txt", "w");
    if (file) {
      for (int i = 0; i < numTemperatures; i++) {
        file.println(floatToString(temperatureData[i].temperature, 2) + "," + String(temperatureData[i].time));
      }
      file.close();
    }
    SPIFFS.end();
  }
}

// Script da página html
void handleRootPage() {
  String html = "<html><head><title>Controle de Temperatura</title></head><body>";
  html += "<h1>Controle de Temperatura</h1>";
  html += "<h2>Temperaturas Cadastradas:</h2>";
  html += "<ul>";
  for (int i = 0; i < numTemperatures; i++) {
    html += "<li>";
    html += "Temperatura: " + floatToString(temperatureData[i].temperature, 2) + " °C, ";
    html += "Tempo: " + String(temperatureData[i].time) + " segundos";
    html += " [<a href='/delete?index=" + String(i) + "'>Deletar</a>]";
    html += "</li>";
  }
  html += "</ul>";

  html += "<p>Temperatura Atual: <span id='current-temp'></span> °C</p>";
  html += "<p>Temperatura Alvo: <span id='target-temp'></span> °C</p>";
  html += "<p>Tempo na Temperatura Alvo: <span id='targetTime'>" + String(targetTime) + "</span> segundos</p>";
  html += "<p>Tempo Restante para a próxima etapa: <span id='remaining-time'></span> segundos</p>";

  // Adicione o botão de iniciar
  html += "<h2>Iniciar Controle de Temperatura:</h2>";
  html += "<form action='/start' method='POST'>";
  html += "<input type='submit' value='Iniciar' onclick='startTemperatureControl(event)'>";
  html += "</form>";

  html += "<script>";
  html += "function startTemperatureControl(event) {";
  html += "  event.preventDefault();";
  html += "  var xhr = new XMLHttpRequest();";
  html += "  xhr.open('GET', '/start', true);";
  html += "  xhr.send();";
  html += "}";
  html += "setInterval(function() {";
  html += "  var currentTemp = document.getElementById('current-temp');";
  html += "  var targetTemp = document.getElementById('target-temp');";
  html += "  var remainingTime = document.getElementById('remaining-time');";
  html += "  var targetTime = document.getElementById('targetTime');";
  html += "  var xhr = new XMLHttpRequest();";
  html += "  xhr.onreadystatechange = function() {";
  html += "    if (xhr.readyState === 4 && xhr.status === 200) {";
  html += "      var data = JSON.parse(xhr.responseText);";
  html += "      currentTemp.innerText = data.currentTemperature.toFixed(2);";
  html += "      targetTemp.innerText = data.targetTemperature.toFixed(2);";
  html += "      remainingTime.innerText = data.remainingTime;";
  html += "      targetTime.innerText = data.targetTime;";
  html += "    }";
  html += "  };";
  html += "  xhr.open('GET', '/temperature', true);";
  html += "  xhr.send();";
  html += "}, 1000);";
  html += "</script>";

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

  server.send(200, "text/html", html);
}

// Script para adicionar nova temperatura/tempo
void handleAddTemperature() {
  float temperature = server.arg("temperature").toFloat();
  unsigned long time = server.arg("time").toInt();

  if (numTemperatures < MAX_TEMPERATURES) {
    temperatureData[numTemperatures].temperature = temperature;
    temperatureData[numTemperatures].time = time;
    numTemperatures++;
    saveTemperatureData();
  }

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

// Script para deletar temperature/tempo
void handleDeleteTemperature() {
  int index = server.arg("index").toInt();

  if (index >= 0 && index < numTemperatures) {
    for (int i = index; i < numTemperatures - 1; i++) {
      temperatureData[i] = temperatureData[i + 1];
    }
    numTemperatures--;
    saveTemperatureData();
  }

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

// Leitura da temperatura do sensor DS18B20
float readTemperature() {
  sensors.requestTemperatures();
  return sensors.getTempCByIndex(0);
}

// Initialização dos relays
void initializeRelays() {
  pinMode(HEATER_RELAY_PIN, OUTPUT);
  digitalWrite(HEATER_RELAY_PIN, LOW);
  pinMode(COOLER_RELAY_PIN, OUTPUT);
  digitalWrite(COOLER_RELAY_PIN, LOW);
}

// Controle dos relays basedo na temperatura corrente e temperatura alvo
void controlRelays(float currentTemperature, float targetTemperature) {
  static unsigned long lastCoolerOffTime = 0;
 
  bool heaterState = digitalRead(HEATER_RELAY_PIN);
  bool coolerState = digitalRead(COOLER_RELAY_PIN);

  if (currentTemperature < targetTemperature - HYSTERESIS) {
    digitalWrite(HEATER_RELAY_PIN, HIGH);
    heaterState = true;
    Serial.println("Aquecedor ligado");
    Serial.println("Temperatura alvo: ");
    Serial.println(targetTemperature);
    Serial.println("Tempo alvo: ");
    Serial.println(targetTime);
  } else if (currentTemperature > targetTemperature + HYSTERESIS) {
    if (!coolerState && millis() - lastCoolerOffTime >= 5 * 60 * 1000) {
      digitalWrite(COOLER_RELAY_PIN, HIGH);
      Serial.println("Geladeira ligada");
      coolerState = true;
    }
  }

  if (targetTemperature - HYSTERESIS <= currentTemperature && currentTemperature <= targetTemperature + HYSTERESIS && coolerState) {
    digitalWrite(COOLER_RELAY_PIN, LOW);
    Serial.println("Geladeira desligada");
    coolerState = false;
    lastCoolerOffTime = millis();
  }

  if (targetTemperature - HYSTERESIS <= currentTemperature && currentTemperature <= targetTemperature + HYSTERESIS && heaterState) {
    digitalWrite(HEATER_RELAY_PIN, LOW);
    Serial.println("Aquecedor desligado");
    heaterState = false;
  }
}

// Verifica se o processo de fermentatação está completo
bool isFermentationComplete() {
  return currentTemperatureIndex == numTemperatures;
}

// Recebe o comando para iniciar a fermentação alterando para true, que vai ser lido no loop
void handleStartTemperatureControl() {
  fermentationStarted = true;
  server.send(200, "text/plain", "Fermentação Iniciada");
}

// Envia para html indicação de fermentação completa
void handleFermentationComplete() {
  String html = "<html><head><title>Fermentação Concluída</title></head><body>";
  html += "<h1>Fermentação Concluída!</h1>";
  html += "<p>A fermentação atingiu todas as temperaturas alvo.</p>";
  html += "</body></html>";

  server.send(200, "text/html", html);
}

// Script de envio de dados de temperatura/tempo para o html
void handleTemperatureData() {
  float currentTemperature = readTemperature();
  float targetTemperature = temperatureData[currentTemperatureIndex].temperature;
  targetTime = temperatureData[currentTemperatureIndex].time;
  elapsedTime = millis() / 1000 - temperatureData[currentTemperatureIndex].time;
//  remainingTime = (temperatureData[currentTemperatureIndex].time > elapsedTime) ? temperatureData[currentTemperatureIndex].time - elapsedTime : 0;

  // Create JSON response
  String jsonResponse = "{";
  jsonResponse += "\"currentTemperature\": " + floatToString(currentTemperature, 2) + ",";
  jsonResponse += "\"targetTemperature\": " + floatToString(targetTemperature, 2) + ",";
  jsonResponse += "\"remainingTime\": " + String(remainingTime) + ",";
  jsonResponse += "\"targetTime\": " + String(targetTime);
  jsonResponse += "}";

  server.send(200, "application/json", jsonResponse);
}

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

  // Connecta ao Wi-Fi
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // Inicia o servidor web
  server.on("/", handleRootPage);
  server.on("/add", handleAddTemperature);
  server.on("/delete", handleDeleteTemperature);
  server.on("/temperature", handleTemperatureData);
  server.on("/start", handleStartTemperatureControl);
  server.begin();

  // Inicializa o sensor de temperatura
  sensors.begin();

  // Lê o arquivo de temperatura/tempo
  loadTemperatureData();

  // Inicializa os relays
  initializeRelays();

  // Seta o currentTemperatureIndex para 0 inicialmente
  currentTemperatureIndex = 0;
}

void loop() {
  server.handleClient();

  // Lê a temperatura atual
  float currentTemperature = readTemperature();

  // Controla o início e término da fermentação
  if (isFermentationComplete()) {
    handleFermentationComplete();
  } else if (fermentationStarted && currentTemperatureIndex < numTemperatures) {
    float targetTemperature = temperatureData[currentTemperatureIndex].temperature;
    controlRelays(currentTemperature, targetTemperature);

    if (currentTemperature >= targetTemperature - HYSTERESIS && currentTemperature <= targetTemperature + HYSTERESIS) {
      Serial.println("Temperatura alvo atingida! Início da contagem do tempo!");

      unsigned long elapsedTimeInSeconds = (targetTime - millis()) / 1000UL;
      Serial.println("Time passing: ");
      Serial.println(elapsedTimeInSeconds);

      if (elapsedTimeInSeconds <= 0) {
        Serial.println("Tempo no alvo alcançado. Passando para a próxima etapa!");
        currentTemperatureIndex++;
      }
    }
  }
}

If targetTime is in seconds, then I'm thinking that should be
unsigned long elapsedTimeInSeconds = targetTime - (millis() / 1000UL);

This change seems logical but still has an error. I put another print to see the targetTime and it is correct. In this case, set to 10 seconds.

      unsigned long elapsedTimeInSeconds = targetTime - (millis() / 1000UL);
      Serial.println(targetTime);
      Serial.println("Time passing: ");
      Serial.println(elapsedTimeInSeconds);

But the return after calculation is as follows:

10
Time passing:
4294967223

Print the value of millis()/1000UL, you will find that it is larger than the value of targetTime.
An unsigned long cannot have a negative value, it underflows and produces a very large positive number.

1 Like

:dizzy_face:

I hadn't realized that millis counts since the beginning of esp and it can't be reset... i'll rewrite the code

This sketch works to count the passage of time. Perfectly.

void loop() {
  server.handleClient();

  // Read the current temperature
  float currentTemperature = readTemperature();

  // Controls the start and end of fermentation
  if (isFermentationComplete()) {
    handleFermentationComplete();
  } else if (fermentationStarted && currentTemperatureIndex < numTemperatures) {
    float targetTemperature = temperatureData[currentTemperatureIndex].temperature;
    controlRelays(currentTemperature, targetTemperature);

    if (currentTemperature >= targetTemperature - HYSTERESIS && currentTemperature <= targetTemperature + HYSTERESIS) {
      Serial.println("Target temperature reached! Time counting starts!");
      updateTarget = true;
    }
    
    if (updateTarget == true){
      currentTime = millis() / 1000;
      Serial.println("Target time: ");
      Serial.println(targetTime);
      Serial.println("Current time: ");
      Serial.println(currentTime);
      phaseTime = currentTime + targetTime;
      updateTarget = false;
      countTime = true;
    }
      
    if (phasetime > millis()/1000) {
      unsigned long elapsed = ((millis()/1000) - currentTime);
      unsigned long elapsedTime = (targetTime - elapsed);
      Serial.println("Time elapsed: ");
      Serial.println(elapsed);
      Serial.println("Remaining time: ");
      Serial.println(elapsedTime);
    }

    if (elapsedTime <= 1 && countTime == true)
    {
      Serial.println("Time on target achieved. Moving on to the next step!");
      currentTemperatureIndex++;
      countTime = false;
    }

    }
  delay(500);
  }

But for some reason I can't figure it out, this part doesn't work!!!

if (elapsedTime <= 1 && countTime == true)
    {
      Serial.println("Time on target achieved. Moving on to the next step!");
      currentTemperatureIndex++;
      countTime = false;
    }

I've tried everything possible! I suspect it's something basic but I can't find it

It worked like this:

void loop() {
  server.handleClient();

  // Read the current temperature
  float currentTemperature = readTemperature();

  // Controls the start and end of fermentation
  if (isFermentationComplete()) {
    handleFermentationComplete();
  } else if (fermentationStarted && currentTemperatureIndex < numTemperatures) {
    float targetTemperature = temperatureData[currentTemperatureIndex].temperature;
    controlRelays(currentTemperature, targetTemperature);

    if (currentTemperature >= targetTemperature - HYSTERESIS && currentTemperature <= targetTemperature + HYSTERESIS) {
      Serial.println("Target temperature reached! Time counting starts!");
      updateTarget = true;
    }
    
    if (updateTarget == true){
      currentTime = millis() / 1000;
      Serial.println("Target time: ");
      Serial.println(targetTime);
      Serial.println("Current time: ");
      Serial.println(currentTime);
      phaseTime = currentTime + targetTime;
      updateTarget = false;
      countTime = true;
    }

    if (phasetime < (millis()/1000) && countTime == true) {
      Serial.println("Time on target achieved. Moving on to the next step!");
      currentTemperatureIndex++;
      countTime = false;
    }
    
    }
  delay(500);
  }

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