One pushbutton relay with timer

I am working on a simple controller to replace a timer switch with a one pushbutton, fixed-time, relay device. when button is pressed it starts the sequence and the relay will be turned on for a given time. ( 15 minutes) and after the time has passed the relay will turn off. I have the intension of adding a RESET button that would make the system be back on standby, relay off, waiting for a start signal from button.

Signals come from an optocoupler since control voltage is 24vdc.
What would be the best way to re-set using a LOW signal to this input pin " RESET=4; "

// sketch was taken from web, modified to suit my needs. 
const byte BUTTON=2; // OPTOCOUPLER SIGNAL TO START 
const byte RESET=4; // OPTOCOUPLER SIGNAL TO RESET COUNTDOWN 
const byte RELAY=13; // 5V RELAY TO ENERGIZE COIL OF A 8 PIN RELAY TO DO THE HEAVY LIFTING 

unsigned long buttonPushedMillis; // when button was released
unsigned long ledTurnedOnAt; // when led was turned on
unsigned long turnOnDelay = 50; // wait to turn on relay
unsigned long turnOffDelay = 10000; // turn off relay after this time
bool ledReady = false; // flag for when button is let go
bool ledState = false; // for relay is on or not.

void setup() {
pinMode(BUTTON, INPUT_PULLUP);
pinMode(RESET, INPUT_PULLUP);
pinMode(RELAY, OUTPUT);
digitalWrite(RELAY, LOW);
}

void loop() {
// get the time at the start of this loop()
unsigned long currentMillis = millis();

// check the button
if (digitalRead(BUTTON) == LOW) {
// update the time when button was pushed
buttonPushedMillis = currentMillis;
ledReady = true;
}

// make sure this code isn't checked until after button has been let go
if (ledReady) {
//this is typical millis code here:
if ((unsigned long)(currentMillis - buttonPushedMillis) >= turnOnDelay) {
// okay, enough time has passed since the button was let go.
digitalWrite(RELAY, HIGH);
// setup our next "state"
ledState = true;
// save when the LED turned on
ledTurnedOnAt = currentMillis;
// wait for next button press
ledReady = false;
}
}

// see if we are watching for the time to turn off LED
if (ledState) {
// okay, led on, check for now long
if ((unsigned long)(currentMillis - ledTurnedOnAt) >= turnOffDelay) {
ledState = false;
digitalWrite(RELAY, LOW);
}
}
}

Thanks in advance

does the signal behave like a momentary button or more like an ON-OFF switch? what about bouncing?

The signal is from a momentary pushbutton. I haven't had trouble with bouncing but I guess it is a possibility. I am not very familiar with debouncing and I was trying to keep the code simple enough for me

best then is to use a button library

there are many choices, like Button in easyRun or OneButton or Toggle from @dlloyd.

here is an example you can try with the OneButton library.

The green button starts your process and the red button is the "emergency stop"


here is the code for reference, should be straightforward to follow once you know that with the OneButton library you define a callback function that is called when the button is pressed and to check the buttons, you need to call tick() frequently in the loop.

#include <OneButton.h> // tps://github.com/mathertel/OneButton]

const byte buttonPin = 2;    // OPTOCOUPLER SIGNAL TO START
const byte resetPin = 4;     // OPTOCOUPLER SIGNAL TO RESET COUNTDOWN
const byte relayPin = 13;    // 5V RELAY TO ENERGIZE COIL OF A 8 PIN RELAY TO DO THE HEAVY LIFTING

OneButton startButton(buttonPin);
OneButton resetButton(resetPin);

const unsigned long duration = 5000ul; // for testing purpose, only 5 seconds 
// const unsigned long duration = 900000ul; // in ms => 15 minutes = 15*60 = 900 seconds

unsigned long chrono;
bool relayIsOn = false;

void relayOff() {
  digitalWrite(relayPin, LOW);
  relayIsOn = false;
}

void relayOn() {
  digitalWrite(relayPin, HIGH);
  chrono = millis();
  relayIsOn = true;
}

void start() {
  if (!relayIsOn) relayOn();
}

void stop() {
  relayOff();
}

void setup() {
  pinMode(relayPin, OUTPUT);
  relayOff();
  Serial.begin(115200);
  startButton.attachClick(start);
  resetButton.attachClick(stop);
}

void loop() {
  startButton.tick();
  resetButton.tick();
  if (relayIsOn && (millis() - chrono >= duration)) relayOff();
}

1 Like

Thank you, I will implement and report back !

Works perfectly

great news :slight_smile:

Would it be possible, without redoing the code, to display the countdown on a i2c lcd display? I have used on other projects to display "states" of the relays and such but never tried to actually have a countdown and for what I have been reading the chunk of code would look like this if itwas only seconds.

 while(millis()<=20000){
    
    lcd.setCursor(0, 1);
    
    lcd.print(20- millis() / 1000);

is this something that could work?

Thanks

It is possible but not like this

You need an if() and another chrono like variable that ticks every second for example

if (relayIsOn && (millis() - chronoDisplay >= 1000ul)) {
  // update display 
  chronoDisplay = millis();
}
1 Like

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