So you're a Noob? Post your questions here until you graduate! Don't be shy.

User avatar
By mrlightsman
#74946 Relative noob seeking advice on this code I have adapted form online examples. All advice is appreciated. THANK YOU.

I have working code (running on an ESP8266-01 in Arduino IDE environment) to turn two lights on/off using two pushbuttons and the avd_web_Switch library. This part all works dandy. Now I would like to add a timer to the lights so that if one is left on for an hour it shuts off automatically. I will be using millis() to do this.

For purpose of this question, I have defined pins GPIO_0 and GPIO_2 to control the relays for the lights (active low). (I am toggling these with pushbuttons on RX & TX, but do not plan to use those pins in the timer function and have not included that in the sample sketch. In fact, the sample sketch doesn't show any manual light control... I know. I really just need help with the timer code... I just want to keep the example simple for academic purposes. I realize it cannot work without having a way to manually toggle the states using pushbuttons or other form of control.)

What I want to do is to constantly poll the digitalRead of GPIO_0 and GPIO_2 for a period of one hour. If the state is LOW and has not changed, I want it to automatically switch to high (ie: shut off the lights). However, if, at any time the state has changed (low->high or high->low) I want to reset the timer to zero and start over again.

Here are my global definitions:
Code: Select all//Switch Contols variables
int GPIO_2 = 2; //To control Device 1
int GPIO_0 = 0; //To control Device 2
int GPIO_2State; //State of device 1
int GPIO_0State; //State of device 2

//Define Auto-off Timer variables
unsigned long startMillis0; // timer for GPIO_0 device
unsigned long startMillis2; // timer for GPIO_2 device
unsigned currentMillis;
const unsigned long period = 3600000; // 1 hour period
byte currentGPIO_0State;
byte currentGPIO_2State;
byte previousGPIO_0State;
byte previousGPIO_2State;
int count0 = 0;
int count2 = 0;


Here is the void setup()
Code: Select allvoid setup() {
  //Set up Auto-off Timers
  startMillis0 = millis(); //save the start time for GPIO_0
  startMillis2 = millis(); //save the start time for GPIO_2
}


Now the tricky part (at least for me). Here is the void loop()
Code: Select allvoid loop() {
  //Get the state of pins
  GPIO_2State = digitalRead(GPIO_2); //State of device 1 (on/Off)
  GPIO_0State = digitalRead(GPIO_0); //State of device 2 (on/Off)
 
  //Set timer
  currentMillis = millis();
  previousGPIO_0State = currentGPIO_0State;
  previousGPIO_2State = currentGPIO_2State;

  //Auto-off timer device 2
  if (currentMillis - startMillis0 <= period) {
    currentGPIO_0State = GPIO_0State;
    if (currentGPIO_0State == LOW && previousGPIO_0State == LOW) {
      count0++;
     
    } else if (currentGPIO_0State != previousGPIO_0State) {
      startMillis0 = millis();
      count0 = 0;
    }
  } else {
    startMillis0 = millis();
      if (count0 = 0 && currentGPIO_0State == LOW) {
        digitalWrite (GPIO_0, HIGH);
      }
        count0 = 0;
  }

  //Auto-off device 1
  if (currentMillis - startMillis2 <= period) {
    currentGPIO_2State = GPIO_2State;
    if (currentGPIO_2State == LOW && previousGPIO_2State == LOW) {
      count2++;
     
    }else if (currentGPIO_2State == !previousGPIO_2State) {
      startMillis2 = millis();
      count2 = 0;
    }
   
  } else {
    startMillis2 = millis();
      if (count2 = 0 && currentGPIO_2State == LOW) {
        digitalWrite (GPIO_2, HIGH);
      }
    count2 = 0;
  }


}


What I am not sure is whether I have my if statements correct. I am polling the state of GPIO_0 (and separately GPIO_2) to see if the state has remained low for the period (1 hour). (in other words, have the lights been on for an hour straight?)

- If it has remained low (ie: my son left the lights on), I want to turn them off (Set GPIO_0 or GPIO_2 to high) and reset the timer and count0 (count2) to start checking again.

- If the state has changed (ie: he turned off the light), I do not want to auto change it, but I do want to reset the timer and count so the next time the light is turned on it has a full hour before the timer will turn it off.

Here is the full sketch
Code: Select all//Switch Contols variables
int GPIO_2 = 2; //To control Device 1
int GPIO_0 = 0; //To control Device 2
int GPIO_2State; //State of device 1
int GPIO_0State; //State of device 2

//Define Auto-off Timer variables
unsigned long startMillis0; // timer for GPIO_0 device
unsigned long startMillis2; // timer for GPIO_2 device
unsigned currentMillis;
const unsigned long period = 3600000; // 1 hour period
byte currentGPIO_0State;
byte currentGPIO_2State;
byte previousGPIO_0State;
byte previousGPIO_2State;
int count0 = 0;
int count2 = 0;

void setup() {
  //Set up Auto-off Timers
  startMillis0 = millis(); //save the start time for GPIO_0
  startMillis2 = millis(); //save the start time for GPIO_2

}

void loop() {
  //Get the state of pins
  GPIO_2State = digitalRead(GPIO_2); //State of device 1 (on/Off)
  GPIO_0State = digitalRead(GPIO_0); //State of device 2 (on/Off)
 
  //Set timer
  currentMillis = millis();
  previousGPIO_0State = currentGPIO_0State;
  previousGPIO_2State = currentGPIO_2State;

  //Auto-off timer device 2
  if (currentMillis - startMillis0 <= period) {
    currentGPIO_0State = GPIO_0State;
    if (currentGPIO_0State == LOW && previousGPIO_0State == LOW) {
      count0++;
     
    } else if (currentGPIO_0State != previousGPIO_0State) {
      startMillis0 = millis();
      count0 = 0;
    }
  } else {
    startMillis0 = millis();
      if (count0 = 0 && currentGPIO_0State == LOW) {
        digitalWrite (GPIO_0, HIGH);
      }
        count0 = 0;
  }

  //Auto-off device 1
  if (currentMillis - startMillis2 <= period) {
    currentGPIO_2State = GPIO_2State;
    if (currentGPIO_2State == LOW && previousGPIO_2State == LOW) {
      count2++;
     
    }else if (currentGPIO_2State == !previousGPIO_2State) {
      startMillis2 = millis();
      count2 = 0;
    }
   
  } else {
    startMillis2 = millis();
      if (count2 = 0 && currentGPIO_2State == LOW) {
        digitalWrite (GPIO_2, HIGH);
      }
    count2 = 0;
  }


}