Using millis() to turn off an output after 5 minutes

Hi, I'm doing a project on tinkercad to turn 1 of 2 outputs on depending on an input analogue voltage. I want one of the outputs to turn off if it has been on for 5 minutes.

I'm using the millis function to capture the millis value at the time the output is written HIGH, I'm then trying to use the current millis value minus the time the input went HIGH to count 5 minutes (5 seconds for testing) to then turn off the output. It's not working out for me.

Any guidance would be much appreciated

// the setup routine runs once when you press reset:
void setup()
{
  Serial.begin(9600); // initialize serial communication at 9600 bits per second:
  pinMode(6, OUTPUT); // Set pin 6 to OUTPUT
  pinMode(4, OUTPUT); // Set pin 4 to OUTPUT
}

//The main routine
void loop() 
{  
  digitalWrite(4, LOW); //set pin 4(Exhaust = Green) LOW
  digitalWrite(6, LOW); //set pin 6(Compressor = Red) LOW
  
  //Integer variables
  int sensorValue = analogRead(A1);// read the input on analog pin 1:

  //Floating point variables
  float voltage = sensorValue * (5.0 / 1023.0); // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float limitHigh = 4.75; //Set voltage high limit to 4.75
  float limitLow = 0.25;  //Set voltage low limit to 0.25

  //Unsigned long variables for time
  //unsigned long startMillis;
  //unsigned long previousTime = 0;
  unsigned long CompOn;
  unsigned long currentTime;
  const unsigned long fiveMinutes = 5000;//5 minutes; unit ms 300000
  
  //Boolean variables
  //bool timeRunning = false;//1; // true if still waiting for delay to finish
  
  //Constants that do not change
  const int CompPin = 6;  // the pin that the compressor is attached to
  const int ExPin = 4;    // the pin that the exhaust is attached to
  
  //Current value of millis
  currentTime = millis();
  
  //If voltage is greater than low limit and less than high limit, run code
  if (voltage > limitLow && voltage < limitHigh)
  {
  Serial.println(voltage);// print out the voltage
    
    //If voltage is less than 2.5 run code
    if (voltage < 2.5)
    {   	       	
        digitalWrite(CompPin, HIGH); //set pin 6(compressor) HIGH
        digitalWrite(ExPin, LOW);  //set pin 4(exhaust) LOW
        CompOn = millis(); //CompOn = value of millis when compressor turns on
        delay(1500);
     
      	  //If the current time - compressor on time is greater than or equal to fiveMinutes run code
      	  if (currentTime - CompOn >= fiveMinutes);
          {
            digitalWrite(CompPin, LOW);
          }			  
	   }

    //Else if voltage is greater than 2.5 run code      
    else if (voltage > 2.5)
    {
      	digitalWrite(ExPin, HIGH); //set pin 4(exhaust) HIGH
      	digitalWrite(CompPin, LOW);  //set pin 6(compressor) LOW
        delay(1500);
    }   
  } 	
}

Lose the

;

1 Like

Thanks! That has worked to write the pin LOW after the required time, but because the if statement above it is still true it immediately turns back on, ideally I want it to stay off until the condition is met again

Tell us when this will evaluate ?


       CompOn = millis(); //CompOn = value of millis when compressor turns on
        delay(1500);

      	  //If the current time - compressor on time is greater than or equal to fiveMinutes run code
      	  if (currentTime - CompOn >= fiveMinutes);
          {
            digitalWrite(CompPin, LOW);
          }

The top if statement evaluates when the voltage is less than 2.5.

When this happens the output is written HIGH and the current millis value is written to the CompOn variable

The 1500ms delay is for rudimentary hysteresis between the two outputs.

This nested if statement that should evaluate when the current time minus the time the compressor turned on is greater than or equal to the fiveMinutes value

CompOn is being reset each time thru.

I see that now. Thanks again. If you'd be able to point me in the right direction, is it a case of adding a condition to the top If statement to evaluate if the compressor has turned off due to the timer elapsing. Or should I not be using nested If statements?

What will happen if CompOn sits at 2.2V for an hour ?

Sorry:

What will happen if voltage sits at 2.2V for an hour ?

The intent is that when CompPin is set HIGH, CompOn captures the time.

After 5 minutes if CompPin is still HIGH it will turn off. If it sits at 2.2V for an hour it should have turned off the output after 5 minutes.

The idea is that if this output is controlling a compressor, it's run time should be limited to five minutes. In the event of an air leak it should not run continuously.

But since it is sitting at 2.2V (for the hour) .

 if (voltage < 2.5)
    {   	       	
        digitalWrite(CompPin, HIGH); //set pin 6(compressor) HIGH

The above will make CompPin go HIGH immediately again since voltage is still at 2.2V ?

Yep, I need to add a condition to that if statement to account for the compressor turning off due to time. Thanks for all your help!

Its always best to make a list of cause and effects.

  • if the voltage is > low limit AND voltage is < 2.5V bah bah bah
  • if the 5 minute TIMER expires the output is turned . . . . . .
  • etc.

      digitalWrite(CompPin, HIGH);      //set pin 6(compressor) HIGH
      digitalWrite(ExPin, LOW);         //set pin 4(exhaust) LOW

What does HIGH mean ? example: Start the Compressor :thinking:
What does LOW mean ? example: Close the exhaust port :thinking:

HIGH and LOW here are setting those output pins high or low

When the voltage is <2.5V the compressor should turn on and the Exhaust port should close.

When the voltage is >2.5V the compressor should turn off and the Exhaust port should open.

The intent is to maintain 2.5V.

And is this to happen for 5 minutes OR longer ? i.e. run for at least 5 minutes AND while we still have voltage < 2.5V ?


And this happens immediately ?

What happens if voltage goes > 2.5V when the TIMER is still in the count down time ?


Do you want any hysteresis ?

No, it should happen for no longer than 5 minutes.

If the input goes >2.5V it should switch outputs regardless of the TIMER.

Implementing proper hysteresis is a goal, but that's a challenge for another night.

I'm going to step away from this and take a look with fresh eyes over the weekend.

Thanks for all your help I really appreciate it.

Here is a start of a sketch you can change as needed:


//********************************************^************************************************
#define CLOSED                        LOW
#define OPENED                        HIGH

#define PUSHED                        LOW
#define RELEASED                      HIGH

#define LEDon                         HIGH
#define LEDoff                        LOW

#define RELAYon                       LOW
#define RELAYoff                      HIGH

#define RUNNING                       true
#define notRUNNING                    false

#define ENABLED                       true
#define DISABLED                      false

//When the voltage is <2.5V the compressor should turn ON, Exhaust port should CLOSE.
//When the voltage is >2.5V the compressor should turn OFF, Exhaust port should OPEN.

#define ExhaustOPEN                   HIGH
#define ExhaustCLOSE                  LOW

#define CompressorON                  HIGH
#define CompressorOFF                 LOW

//********************************************^************************************************

const byte heartbeatLED              = 13;
const byte CompPin                   = 6;     //the pin that the compressor is attached to
const byte ExPin                     = 4;     //the pin that the exhaust is attached to

bool CompOnFlag                      = DISABLED;

const float limitHigh                = 4.75;  //Set voltage high limit to 4.75
const float limitLow                 = 0.25;  //Set voltage low limit to 0.25

float voltage;

//****************************
//timing stuff
unsigned long heartbeatTime;
unsigned long CompOnTime;
unsigned long currentTime;

const unsigned long fiveMinutes      = 5000; //5 minutes; unit ms 5 * 60 * 1000ul  (5 seconds for testing)


//********************************************^************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(CompPin, OUTPUT);
  pinMode(ExPin, OUTPUT);

  digitalWrite(CompPin, CompressorOFF);
  digitalWrite(ExPin, ExhaustOPEN);

  pinMode(heartbeatLED, OUTPUT);

} //END of   setup()


//********************************************^************************************************
void loop()
{
  currentTime = millis();

  //*************************************                     heartbeat T I M E R
  //to see if the sketch has blocking code,
  //toggle the heartbeat LED (every 500ms)
  if (millis() - heartbeatTime >= 500ul)
  {
    //restart the TIMER
    heartbeatTime = millis();

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //*************************************                     five minute  T I M E R
  //if enabled, has the TIMER expired ?
  if (CompOnFlag == ENABLED && currentTime - CompOnTime >= fiveMinutes)
  {
    digitalWrite(CompPin, CompressorOFF);
    digitalWrite(ExPin, ExhaustOPEN);
  }

  //*************************************
  int sensorValue = analogRead(A1);
  voltage = sensorValue * (5.0 / 1023.0);

  //are we within the limits ?
  if (voltage >= limitLow && voltage <= limitHigh)
  {
    Serial.println(voltage);

    //***********************
    //When the voltage is <2.5V the compressor should turn ON, Exhaust port should CLOSE.
    if (CompOnFlag == DISABLED && voltage < 2.5)
    {
      digitalWrite(CompPin, CompressorON);
      digitalWrite(ExPin, ExhaustCLOSE);

      //enable the 5 minute TIMER
      CompOnFlag = ENABLED;

      //restart the TIMER
      CompOnTime = millis();
    }

    //***********************
    //When the voltage is >2.5V the compressor should turn OFF, Exhaust port should OPEN.
    else if (voltage > 2.5)
    {
      digitalWrite(CompPin, CompressorOFF);
      digitalWrite(ExPin, ExhaustOPEN);

      //reseting the TIMER flag
      CompOnFlag = DISABLED;
    }
  }

} //END of   loop()



1 Like

Wow, thanks so much! That's such a help with understanding how to implement the timer.

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