Problem with Millis() on/off delay on event

Hello

I have been putting together a little project that switches a relay with a delay on/off when a sensor reading hits a certain value.

The first part of the code, when there is heat demand, record the time

if (Heat_Demand == 0 && check == 0)             // no demand, and the time hasnt been recorded 
  {
    Output_Ready = 0;                                         // Ouput can be turned off
    check = 1;                                                   // Says the time has been recorded
    OutputMillis = millis();                                   // record the time
  }
  else if (Heat_Demand == 1 && check == 0)        // Same as above but for when there is a demand
  {
    Output_Ready = 1;
    check = 1;
    OutputMillis = millis();
  }

The next part is the code for the delay on/off

 if ((currentMillis - OutputMillis >= DelayON) && Output_Ready == 1)  
  {
    Output_Status = 1;                // state that the output is on
    digitalWrite(Output, LOW);     // switch the relay on 
    check = 0;                           // reset the value so the time can be recorded again
  }
  else if ((currentMillis - OutputMillis >= DelayOFF) && Output_Ready == 0)
  {
    Output_Status = 0;              // state that the output is off
    digitalWrite(Output, HIGH);    // switch the relay off
    check = 0;                          // reset the value so the time can be recorded again
  }

This code did seem to work for a while now that i have added more bits too it (adding more relay outputs etc.) the delay on/off doesnt work. When writing (currentMillis - OutputMillis) to the serial monitor, the value given is 4294967282, even though e.g. current = 79713, Output = 79726. ( It seems to do this when writing to serial after the above if statements has been performed)

I was just wondering whether it was my code or anyone has any ideas on how to solve this issues?

Thanks

Please post the complete program.

The problem is usually in the part that you are not looking at, which is why you have not found it.

...R

Best guess: wrong variable type.

This code did seem to work for a while now that i have added more bits too it (adding more relay outputs etc.)

Where is currentMillis set, you need to post all your code?
Comment out the bits you added so that you have a working program.
Then uncomment small bits till you find the statements that break the sketch.
Add print statements into the code so that you know exactly where it is going and what it is doing.

Hello

Thanks for the replies, I have been having a little play around with the code to try and debug the problem.

ardly:
Where is currentMillis set...

The currentMillis was called pretty much at the start of the loop after 2 simple sensor reading function, and the DateTime now. The rest of the code is as previously posted

void loop()
{ 
  //----Input Readings----
  Sens1= Sensors(Temp1_AI);          
  Sens2 = Sensors(Temp2_AI);

  currentMillis = millis();
  DateTime now = rtc.now();

I moved the currentMillis just before the 2nd part where the outputs are turned on, and I am no longer getting the massive number and the code seems to work correctly

I was just wondering does anyone know why this may have caused the problem, or was it because i was setting the currentmillis before the outputmillis, so I know for next time?

thanks

Spider361:
The rest of the code is as previously posted

Where? It's not in this thread. Only snippets here.

Hello

Sorry about that, here is the whole code, i have also add 2 extra ouputs that interlock together

The problem seems to occur when the currentMillis = millis() is at the start of the code underneath the sensor reading function.

Thanks

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"

RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

LiquidCrystal_I2C lcd(0x3F, 20, 4);
//----Defines----
#define TempMIN 20
#define TempMAX 80
#define TempX1 0
#define TempY1 80
#define TempX2 20
#define TempY2 20

//----Inputs----
int Temp1_AI = A2;
int Temp2_AI = A3;

//----Outputs----
int Output1 = 2;
int Output2 = 3;
int Output3 = 4;

//----Varibles----
//---Varible to store Sensor Reading
int Sens1 = 0;
int Sens2 = 0;

//---Varible to store Calculations/misc
int Req_Flow = 20;                  //Required Flow Temperature
int Req_flow_lower = 3;             //Required Flow Temperature lower hysteresis
int Req_flow_Upper = 3;             //Required Flow Temperature uppper hysteresis
int TempSlope;                         // Vt Slop Gradient
int Heat_Demand = 0;                // Heat demand Status
unsigned long currentMillis = 0;
//----------Output Variable----------
int Output1_Ready = 0;
int Output1_Status = 0;
int check1 = 0;
unsigned long Output1Millis = 0;
long Output1ON = 10000;
long Output1OFF = 10000;

int Output2_Ready = 0;
int Output2_Status = 0;
int check2 = 0;
unsigned long Output2Millis = 0;
long Output2ON = 1000;
long Output2OFF = 10000;

int Output3_Ready = 0;
int Output3_Status = 0;
int check3 = 0;
unsigned long Output3Millis = 0;
long Output3ON = 1000;
long Output3OFF = 1000;

void setup() {
  lcd.init();
  lcd.backlight();
#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif
  //----Pin Setup----
  Serial.begin(9600);
  pinMode(2, OUTPUT);                 // Pin setup
  pinMode(3, OUTPUT);                 
  pinMode(4, OUTPUT);                 
    
  digitalWrite(2, HIGH);              // Set All outputs off 
  digitalWrite(3, HIGH);              //   
  digitalWrite(4, HIGH);              // 
  
  if (! rtc.begin()) {    
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
   rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    
}
}
void loop()
{ 
//----Input Readings----
  Sens1= Sensors(Temp1_AI);          
  Sens2 = Sensors(Temp2_AI);

  //currentMillis = millis(); // moved from here corrected the problem

  DateTime now = rtc.now(); 
  Req_Flow = Heating_Temp(Sens1,TempX1,TempY1,TempX2,TempY2,TempMIN,TempMAX);
  Heat_Demand = HeatDemand(Sens2, Req_Flow, Req_flow_lower, Req_flow_Upper, Heat_Demand);
//----Output1
if (Heat_Demand == 0 && check1 == 0)             // no demand, and the time hasnt been recorded 
  {
    Output1_Ready = 0;                                         // Ouput can be turned off
    check1 = 1;                                                   // Says the time has been recorded
    Output1Millis = millis();                                   // record the time
  }
  else if (Heat_Demand == 1 && check1 == 0)        // Same as above but for when there is a demand
  {
    Output1_Ready = 1;
    check1 = 1;
    Output1Millis = millis();
  }
//----Output2
if (Heat_Demand == 0 && check2 == 0 && Output1_Status == 0)   // no demand, and the time hasnt been recorded 
  {
    Output2_Ready = 0;                                         // Ouput can be turned off
    check2 = 1;                                                    // Says the time has been recorded
    Output2Millis = millis();                                   // record the time
  }
  else if (Heat_Demand == 1 && check2 == 0 && Output3_Status == 1)        // Same as above but for when there is a demand
  {
    Output2_Ready = 1;
    check2 = 1;
    Output2Millis = millis();
  }
//----Output 3------
if (Heat_Demand == 0 && check3 == 0 && Output2_Status == 0)             // no demand, and the time hasnt been recorded 
  {
    Output3_Ready = 0;                                         // Ouput can be turned off
    check3 = 1;                                                    // Says the time has been recorded
    Output3Millis = millis();                                   // record the time
  }
  else if (Heat_Demand == 1 && check3 == 0)        // Same as above but for when there is a demand
  {
    Output3_Ready = 1;
    check3 = 1;
    Output3Millis = millis();
  }


//------Output Table
currentMillis = millis();
if ((currentMillis - Output1Millis >= Output1ON) && Output1_Ready == 1)  
  {
    Output1_Status = 1;                // state that the output is on
    digitalWrite(Output1, LOW);     // switch the relay on 
    check1 = 0;                           // reset the value so the time can be recorded again
  }
  else if ((currentMillis - Output1Millis >= Output1OFF) && Output1_Ready == 0)
  {
    Output1_Status = 0;              // state that the output is off
    digitalWrite(Output1, HIGH);    // switch the relay off
    check1 = 0;                          // reset the value so the time can be recorded again
  }

if ((currentMillis - Output2Millis >= Output2ON) && Output2_Ready == 1)  
  {
    Output2_Status = 1;                // state that the output is on
    digitalWrite(Output2, LOW);     // switch the relay on 
    check2 = 0;                           // reset the value so the time can be recorded again
  }
  else if ((currentMillis - Output2Millis >= Output2OFF) && Output2_Ready == 0)
  {
    Output2_Status = 0;              // state that the output is off
    digitalWrite(Output2, HIGH);    // switch the relay off
    check2 = 0;                          // reset the value so the time can be recorded again
  } 

if ((currentMillis - Output3Millis >= Output3ON) && Output3_Ready == 1)  
  {
    Output3_Status = 1;                // state that the output is on
    digitalWrite(Output3, LOW);     // switch the relay on 
    check3 = 0;                           // reset the value so the time can be recorded again
  }
  else if ((currentMillis - Output3Millis >= Output3OFF) && Output3_Ready == 0)
  {
    Output3_Status = 0;              // state that the output is off
    digitalWrite(Output3, HIGH);    // switch the relay off
    check3 = 0;                          // reset the value so the time can be recorded again
  } 

  lcd.setCursor(0,0);
  lcd.print("S1=");
  lcd.print(Sens1);
  lcd.print(" ");

  lcd.setCursor(7,0);
  lcd.print("Req.=");
  lcd.print(Req_Flow);
  lcd.print(" ");
  lcd.setCursor(15,0);
  lcd.print("F=");
  lcd.print(Sens2);
  lcd.print(" ");

  if (Output1_Status == 1)
  {
  lcd.setCursor(0,1);
  lcd.print("1 ON ");
  }
  else if (Output1_Status == 0)
  {
  lcd.setCursor(0,1);
  lcd.print("1 OFF");
  }

  if (Output2_Status == 1)
  {
  lcd.setCursor(6,1);
  lcd.print("2 ON ");
  }
  else if (Output2_Status == 0)
  {
  lcd.setCursor(6,1);
  lcd.print("2 OFF");
  }
  if (Output3_Status == 1)
  {
  lcd.setCursor(11,1);
  lcd.print("3 ON ");
  }
  else if (Output3_Status == 0)
  {
  lcd.setCursor(11,1);
  lcd.print("3 OFF");
  }



  if (Heat_Demand == 0)
  {
  lcd.setCursor(5,2);
  lcd.print("    ");
  }
  else if (Heat_Demand == 1)
  {
  lcd.setCursor(5,2);
  lcd.print("Heat");
  }
  


}


int Sensors(int pin)
{
  int reading = 0;
  reading = analogRead(pin);
  reading = map(reading, 0, 1023, -10, 80);
  return reading;
}


int Heating_Temp(int Outside, int x1,int y1,int x2,int y2, int MIN, int MAX)
{
  int temp = 0;  

  temp = ((y2 - y1)/(x2 - x1)) * Outside + y1;
    if (temp <= MIN)              
    {
      temp = MIN;
    } 
    else if(temp >= MAX)
    {
      temp = MAX;
    }
  
   return temp;
}

int HeatDemand (int Flow, int ReqFlow,int Lower,int Upper, int Demand)
{
  
  if (Flow  < (ReqFlow - Lower) ) 
  {
    Demand = 1;
  }
  else if (Flow >= (ReqFlow + Upper))
  {
    Demand = 0;
  }
 return Demand;
}

If you enable line 95 then on lines 105, 111 etc you should probably change

Output1Millis = millis();

to

Output1Millis = currentMillis;

so everything is working from the same value - which is the whole point of having currentMillis in the first place

If that does not solve the problem post your updated program and explain exactly how it behaves.

...R

Robin2:
If you enable line 95 then on lines 105, 111 etc you should probably change

Output1Millis = millis();

to

Output1Millis = currentMillis;

so everything is working from the same value - which is the whole point of having currentMillis in the first place

If that does not solve the problem post your updated program and explain exactly how it behaves.

...R

Excellent, this has solved the problem, thank you.

However, i have noticed that the delays are sometimes longer than others and not very precise, especially when I simulate the temperature rising above the setpoint then falling again shortly after and as it doesn't reset the time it can add extra time on actually switching

So my question what would be the best method to reset the time if the condition changes during the on/off delay times, is it just going to be another if statement or is there a simpler method?

Spider361:
However, i have noticed that the delays are sometimes longer than others and not very precise,

Post the latest version of your program in your next Reply and give as much detail as possible about which parts of the timing are not doing what you want.

...R