2

I'm trying to simulate dynamic temperature using a small set of data with ESP32. I've just realized that the relay doesn't change the status if there is some variation of the temperature upper or lower the threshold.

If the temperature starts below the modeled temperature, the relay will turn on but, once it reaches the model's temperature or exceeds it, the status doesn't change, and the system will warm up till the next model.

Am I missing something in my code?

#include <OneWire.h>
#include <DallasTemperature.h>
#include <NTPClient.h>
#include <WiFi.h>
#include <WiFiUdp.h>


WiFiUDP ntpUDP;

NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 60000); //UTC+1 (Europe)


unsigned long current_time;

#define WIFI_AP "xxxxx"
#define WIFI_PASSWORD "xxxxx"
//WiFi SETUP
WiFiClient wifiClient;
int status = WL_IDLE_STATUS;
unsigned long lastSend;


const int oneWireBus1 = 0;
OneWire oneWire1 (oneWireBus1);
DallasTemperature sensors1 (&oneWire1);

const int relay1 = 02;


struct SetPoint {
  unsigned long time;
  float temperature;
};


#define DATA_SIZE  17

SetPoint scen1[DATA_SIZE] = {
  {1622652330,26.97},//18h
  {1622652390,25.62},
  {1622678400,24.87},
  {1622689200,24.16},
  {1622700000,23.86},
  {1622710800,25.17},
  {1622721600,26.41},
  {1622732400,27.22},
  {1622743200,26.78},
  {1622754000,25.83},
  {1622764800,25.1},
  {1622775600,24.6},
  {1622786400,24.24},
  {1622797200,26.81},
  {1622808000,29.35},
  {1622818800,29.38},
  {1622829600,30.5}
};

unsigned int pos = 0;


void setup() {
  Serial.begin(115200);
  sensors1.begin();
  pinMode(relay1, OUTPUT);
  InitWiFi();
  lastSend = 0;
  timeClient.begin();

  

void loop() {

  sensors1.requestTemperatures();
  float temperature1 = sensors1.getTempCByIndex(0);

  timeClient.update();

  long current_time =  timeClient.getEpochTime();

  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
    if (temperature1 < scen1[pos].temperature) {
      digitalWrite (relay1, HIGH);
    }
    else if (temperature1 > scen1[pos].temperature) {
      digitalWrite (relay1, LOW);
    }
    pos++;
  }

  Serial.println(timeClient.getEpochTime());
  Serial.println(timeClient.getFormattedTime());
  Serial.println(pos);
  Serial.println(scen1[pos].temperature);
  Serial.println(scen1[pos-1].temperature);
  Serial.print("Temperature Censius - Sensor 1: ");
  Serial.print(temperature1);
  Serial.println(" ºC ");
  delay(3000);


}

(UPDATE)

Replacing the first if with while doesn't change anything.

The code works when taking if / else if out of nested if, but in this case I'm not able to increase time (the pos++ is also commented), and define limits according to the array size.

//  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
    if ((temperature1 < scen1[pos].temperature)&& (current_time >= scen1[pos].time)) {
      digitalWrite (relay1, HIGH);
    }
    else if ((temperature1 > scen1[pos].temperature)&&(current_time >= scen1[pos].time)) {
      digitalWrite (relay1, LOW);
    }
//    pos++;
//  }
8
  • Tried changing if with while at while (pos < DATA_SIZE && current_time >= scen1[pos].time). But no change – s_tatus3 Jun 2 at 15:46
  • The else if can just be an else. I'd start by making sure if if statement is being entered, then sanity-checking the two temperatures in the comparison. might also be beneficial to set up a test rig that compresses time and fakes the sensor data. – Dave Newton Jun 2 at 15:54
  • Thank you @DaveNewton. Yes, changed the else if using just else but seems to work likewise. Also, compressing time (in my case I set up an interval of 1 minute and 2 minutes), the relay doesn't' t change with simulated temp data. – s_tatus3 Jun 2 at 16:39
  • 1
    So I think dumping out temperature1 and scen1[pos].temperature would be a good idea to sanity-check all assumptions. There's nothing obvious jumping out at me at the moment. (Changing from else if to else wasn't a fix, just a simplification.) I'd normalize all time values to unsigned long (you're currently mixing long and unsigned long comparisons, but the high bit isn't set, so shouldn't matter. – Dave Newton Jun 2 at 16:51
  • I've managed discarding the if (pos < DATA_SIZE && current_time >= scen1[pos].time) and using just if and if else/else. I kept both temperature1 and scen1[pos].temperature and the loop is working ok. So, I could identify where is the issue. Obviously I have to see now how to add a statement/loop for time – s_tatus3 Jun 2 at 20:41
1

I have to remove the pos++ from if statement to have digitalWrite working again according to captured temperature:

  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
    if (temperature1 < scen1[pos].temperature) {
    digitalWrite (relay1, HIGH);
    }
    else if (temperature1 > scen1[pos].temperature) {
    digitalWrite (relay1, LOW);
    }
   }

Obviously this isn't updating time and the system gets stuck at time 0 of the array.

(UPDATE)

As well observed by Dave Newton, the previous observation is pointless to really fix the problem.

The problem was fixed taking the if statement that control the relay from inside the one controlling the time.

Now I can simulate a time interval defined with the array and use the temperature (also present in the array) to turn on/off the relay that controls the heater and simulates environment temperature:

First I created a function that will work as a thermostat:

void set_thermostat() {
  sensors1.requestTemperatures();
  float temperature1 = sensors1.getTempCByIndex(0);

  if (temperature1 < scen1[pos].temperature) {
    digitalWrite (relay1, HIGH);
  }
  else if (temperature1 > scen1[pos].temperature) {
    digitalWrite (relay1, LOW);
  }
}

Then I can it at the loop function, outside the statement that increases the time, based on the one defined by the array:

  if (pos < DATA_SIZE && current_time >= scen1[pos].times) {
    pos++;
  }

  set_thermostat(); 

This reproduces exactly what I've been looking for, with real-time control of the temperature comparing the environmental one with the model.

4
  • So it's blowing through the loop, which still means the time comparison is failing. Hence the repeated suggestion to check your assumptions by looking at the times. There's zero way we can help you without knowing what the data values are that are being compared, and you won't share them. This isn't an answer to the problem, it's a work-around that breaks the program. – Dave Newton Jun 3 at 16:30
  • Thanks. Yes, I checked the times. I compared the current_time and the scen1[pos].time. Simplified the code and checked if current_time is equal or bigger of scen1[pos].time. The output is right (using different times and intervals). So I would expect the statement working fine. I don' t know the checking of assumptions means something else of that I've already done. – s_tatus3 Jun 3 at 18:55
  • 1
    My point was that we cannot check your assumptions or provide any meaningful input without knowing what's actually happening. Comparisons generally Just Work, so if removing pos++ "fixes" it (ergo pos < DATA_SIZE forever) it means there's an issue in the time comparison. But we cannot see the any of the values being compared, so all we can do is guess. – Dave Newton Jun 3 at 19:15
  • I see and agree. Have updated the reply with the solution (this one really reproducing what I want). – s_tatus3 Jun 4 at 9:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.