Set the default relay turn OFF state into 3 seconds

I have a problem where, after setting the time, the relay only lights its LED and makes a buzzing sound when the set time arrives. I think this is an issue in the code. Can you help me?

Objectives:

  • I want the relay to turn ON when the set time arrives
  • The relay should turn OFF after 3 seconds
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <virtuabotixRTC.h>

// Relay pin
#define relay1      10

// RTC module pins
#define rtcVCC      A5
#define rtcGND      A4
#define rtcSCLK     A3
#define rtcIO       A2
#define rtcCE       A1

// RTC object
virtuabotixRTC myRTC(rtcSCLK, rtcIO, rtcCE);

// Keypad
#define btnRIGHT    0
#define btnUP       1
#define btnDOWN     2
#define btnLEFT     3
#define btnSELECT   4
#define btnNONE     5

// Mode 
#define modeSETUP   1
#define modeNORMAL  2

int mode = 1; // Default mode

// EEPROM addressing
#define adr1ON    2
#define adr2ON    6
#define adr3ON    10
#define adr4ON    14
#define adr5ON    18
#define adr6ON    22
#define adr7ON    26
#define adr8ON    30

byte name0x1[] = { B11111, B10000, B10000, B10100, B10110, B11111, B00110, B00100 };
byte name0x2[] = { B11000, B00100, B00010, B00010, B11010, B00010, B00100, B11000 };
byte name0x3[] = { B00011, B00100, B01001, B01001, B01001, B01000, B00100, B00011 };

// UP
byte name1x4[] = { B00000, B00100, B01110, B11111, B01110, B01110, B01110, B00000 };
// DOWN
byte name1x5[] = { B00000, B01110, B01110, B01110, B11111, B01110, B00100, B00000 };

int eepromMin = 0;
int eepromHour = 0;

int eepromHourON = 0;
int eepromMinON = 0;

// LCD keypad shield pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int lcd_key     = 0;
int adc_key_in  = 0;

void setup() {

  lcd.createChar(0, name0x1);
  lcd.createChar(1, name0x2);
  lcd.createChar(2, name0x3);
  lcd.createChar(3, name1x4);
  lcd.createChar(4, name1x5);

	// Set all digital pins as output
	for (int i = 0; i <= 13; i++) {
		pinMode(i, OUTPUT);
	}

	// RTC module activation
	pinMode(rtcVCC,  OUTPUT);
	pinMode(rtcGND,  OUTPUT);
	pinMode(rtcSCLK, OUTPUT);
	pinMode(rtcIO,   OUTPUT);
	pinMode(rtcCE,   OUTPUT);
	digitalWrite(rtcVCC, HIGH);
	digitalWrite(rtcGND, LOW);

	delay(500);

	// LCD initialization
	lcd.begin(16, 2);
}

void loop() {

	lcd.setCursor(4, 0);

	// Display hours:minutes:seconds
	displayTime();

	// Set & display relay based on EEPROM data
	lcd.setCursor(0, 1); 
	lcd.print("1");
	relayAction(adr1ON, 1, relay1);
	lcd.setCursor(2, 1); 
	lcd.print("2");
	relayAction(adr2ON, 3, relay1);
	lcd.setCursor(4, 1); 
	lcd.print("3");
	relayAction(adr3ON, 5, relay1);
	lcd.setCursor(6, 1); 
	lcd.print("4");
	relayAction(adr4ON, 7, relay1);
	lcd.setCursor(8, 1); 
	lcd.print("5");
	relayAction(adr5ON, 9, relay1);
	lcd.setCursor(10, 1); 
	lcd.print("6");
	relayAction(adr6ON, 11, relay1);
	lcd.setCursor(12, 1); 
	lcd.print("7");
	relayAction(adr7ON, 13, relay1);
	lcd.setCursor(14, 1); 
	lcd.print("8");
	relayAction(adr8ON, 15, relay1);

	// If the user presses the SELECT button, enter the settings menu
	if (read_LCD_buttons() == btnSELECT) {
		while (read_LCD_buttons() == btnSELECT);
		lcd.clear();
		lcd.setCursor(0, 0);
    lcd.write(byte(3));
		lcd.print("   TIME SETTING");
		lcd.setCursor(0, 1);
    lcd.write(byte(4));
		lcd.print("  CYCLE SETTING");
		while (read_LCD_buttons() == btnNONE);
		if (read_LCD_buttons() == btnUP) {
			while (read_LCD_buttons() == btnUP);
			setRTC();   // If the user presses the UP button, enter RTC settings menu
		}
		else if (read_LCD_buttons() == btnDOWN) {
			while (read_LCD_buttons() == btnDOWN);
			setPin();   // If the user presses the DOWN button, enter PIN settings menu
		}
	}
}

void relayAction(int adrON, int pos, int pin) {
	myRTC.updateTime();
	int MinToday = (myRTC.hours * 60) + myRTC.minutes;
	int MinEprON = (EEPROM.read(adrON) * 60) + EEPROM.read(adrON + 1);

	lcd.setCursor(pos, 1);
	if (MinToday != MinEprON) {
		lcd.print("-");
		digitalWrite(pin, HIGH);
	}
	else if (MinToday = MinEprON) {
		if (myRTC.seconds >= 3) {
			lcd.print("-");
			digitalWrite(pin, HIGH);
		}
		else {
			lcd.print("*");
			digitalWrite(pin, LOW);
		}
	}
}

// Setup function
void setRTC() {

	lcd.clear();
	lcd.setCursor(0, 0);
	lcd.print("TIME SETTING");
	delay(1000);

	lcd.clear();
	lcd.setCursor(0, 0);
	lcd.print("CURRENT ");
	setupShowValue2(myRTC.hours, myRTC.minutes, 0);

	lcd.setCursor(0, 1);
	lcd.print("NEW ");

	myRTC.updateTime();
	setupShowValue(myRTC.hours, myRTC.minutes, 1);
	while (read_LCD_buttons() == btnNONE);
	setupChooseValueSetRTC(myRTC.hours, myRTC.minutes, 1);
	lcd.setCursor(0,0);
	lcd.print("SETTINGS SAVED   ");
	delay(1000);
	lcd.clear();
}

void setPin() {

	lcd.clear();
	lcd.setCursor(0, 0);
	lcd.print(" CYCLE SETTING");
	delay(3000);

	lcd.clear();
  
	lcd.setCursor(3, 0);
  lcd.write(byte(0));
  lcd.setCursor(0, 1);
	lcd.print("CYCLE 1 :");
	eepromHour = EEPROM.read(adr1ON);
	eepromMin = EEPROM.read(adr1ON + 1);
	if (eepromHour >= 24) eepromHour = 0;
	if (eepromMin  >= 60) eepromMin  = 0;
  lcd.setCursor(13, 0);
  lcd.write(byte(2));
  lcd.setCursor(14, 0);
  lcd.write(byte(1));
	setupShowValue(eepromHour, eepromMin, 0);
	while (read_LCD_buttons() == btnNONE);
	setupChooseValue(eepromHour, eepromMin, adr1ON, 0);

	lcd.clear();

	lcd.setCursor(3, 0);
  lcd.write(byte(0));
	lcd.setCursor(0, 1);
	lcd.print("CYCLE 2 :");
	eepromHour = EEPROM.read(adr2ON);
	eepromMin = EEPROM.read(adr2ON + 1);
	if (eepromHour >= 24) eepromHour = 0;
	if (eepromMin  >= 60) eepromMin  = 0;
  lcd.setCursor(13, 0);
  lcd.write(byte(2));
  lcd.setCursor(14, 0);
  lcd.write(byte(1));
	setupShowValue(eepromHour, eepromMin, 0);
	while (read_LCD_buttons() == btnNONE);
	setupChooseValue(eepromHour, eepromMin, adr2ON, 0);

	lcd.clear();

	lcd.setCursor(3, 0);
  lcd.write(byte(0));
	lcd.setCursor(0, 1);
	lcd.print("CYCLE 3 :");
	eepromHour = EEPROM.read(adr3ON);
	eepromMin = EEPROM.read(adr3ON + 1);
	if (eepromHour >= 24) eepromHour = 0;
	if (eepromMin  >= 60) eepromMin  = 0;
  lcd.setCursor(13, 0);
  lcd.write(byte(2));
  lcd.setCursor(14, 0);
  lcd.write(byte(1));
	setupShowValue(eepromHour, eepromMin, 0);
	while (read_LCD_buttons() == btnNONE);
	setupChooseValue(eepromHour, eepromMin, adr3ON, 0);

	lcd.clear();

	lcd.setCursor(3, 0);
  lcd.write(byte(0));
	lcd.setCursor(0, 1);
	lcd.print("CYCLE 4 :");
	eepromHour = EEPROM.read(adr4ON);
	eepromMin = EEPROM.read(adr4ON + 1);
	if (eepromHour >= 24) eepromHour = 0;
	if (eepromMin  >= 60) eepromMin  = 0;
  lcd.setCursor(13, 0);
  lcd.write(byte(2));
  lcd.setCursor(14, 0);
  lcd.write(byte(1));
	setupShowValue(eepromHour, eepromMin, 0);
	while (read_LCD_buttons() == btnNONE);
	setupChooseValue(eepromHour, eepromMin, adr4ON, 0);

	lcd.clear();

	lcd.setCursor(3, 0);
  lcd.write(byte(0));
	lcd.setCursor(0, 1);
	lcd.print("CYCLE 5 :");
	eepromHour = EEPROM.read(adr5ON);
	eepromMin = EEPROM.read(adr5ON + 1);
	if (eepromHour >= 24) eepromHour = 0;
	if (eepromMin  >= 60) eepromMin  = 0;
  lcd.setCursor(13, 0);
  lcd.write(byte(2));
  lcd.setCursor(14, 0);
  lcd.write(byte(1));
	setupShowValue(eepromHour, eepromMin, 0);
	while (read_LCD_buttons() == btnNONE);
	setupChooseValue(eepromHour, eepromMin, adr5ON, 0);

	lcd.clear();

	lcd.setCursor(3, 0);
  lcd.write(byte(0));
	lcd.setCursor(0, 1);
	lcd.print("CYCLE 6 :");
	eepromHour = EEPROM.read(adr6ON);
	eepromMin = EEPROM.read(adr6ON + 1);
	if (eepromHour >= 24) eepromHour = 0;
	if (eepromMin  >= 60) eepromMin  = 0;
  lcd.setCursor(13, 0);
  lcd.write(byte(2));
  lcd.setCursor(14, 0);
  lcd.write(byte(1));
	setupShowValue(eepromHour, eepromMin, 0);
	while (read_LCD_buttons() == btnNONE);
	setupChooseValue(eepromHour, eepromMin, adr6ON, 0);

	lcd.clear();

	lcd.setCursor(3, 0);
  lcd.write(byte(0));
	lcd.setCursor(0, 1);
	lcd.print("CYCLE 7 :");
	eepromHour = EEPROM.read(adr7ON);
	eepromMin = EEPROM.read(adr7ON + 1);
	if (eepromHour >= 24) eepromHour = 0;
	if (eepromMin  >= 60) eepromMin  = 0;
  lcd.setCursor(13, 0);
  lcd.write(byte(2));
  lcd.setCursor(14, 0);
  lcd.write(byte(1));
	setupShowValue(eepromHour, eepromMin, 0);
	while (read_LCD_buttons() == btnNONE);
	setupChooseValue(eepromHour, eepromMin, adr7ON, 0);

	lcd.clear();

	lcd.setCursor(3, 0);
  lcd.write(byte(0));
	lcd.setCursor(0, 1);
	lcd.print("CYCLE 8 :");
	eepromHour = EEPROM.read(adr8ON);
	eepromMin = EEPROM.read(adr8ON + 1);
	if (eepromHour >= 24) eepromHour = 0;
	if (eepromMin  >= 60) eepromMin  = 0;
  lcd.setCursor(13, 0);
  lcd.write(byte(2));
  lcd.setCursor(14, 0);
  lcd.write(byte(1));
	setupShowValue(eepromHour, eepromMin, 0);
	while (read_LCD_buttons() == btnNONE);
	setupChooseValue(eepromHour, eepromMin, adr8ON, 0);
	lcd.clear();
}

void setupChooseValue(int HourNew, int MinNew, byte Address, byte Pos) {
	while (read_LCD_buttons() != btnSELECT) {
		if (read_LCD_buttons() == btnRIGHT) {
			if (HourNew < 23) {
				HourNew++;
			}
		}
		else if (read_LCD_buttons() == btnLEFT) {
			if (HourNew > 0) {
				HourNew--;
			}
		}
		else if (read_LCD_buttons() == btnUP) {
			if (MinNew < 59) {
				MinNew++;
			}
		}
		else if (read_LCD_buttons() == btnDOWN) {
			if (MinNew > 0) {
				MinNew--;
			}
		}
		setupShowValue(HourNew, MinNew, Pos);
		delay(150);
	}
	while (read_LCD_buttons() != btnNONE);  // Wait until the button is released
	EEPROM.write(Address, HourNew);
	EEPROM.write(Address + 1, MinNew);
	delay(150);
}

void setupChooseValueSetRTC(int HourNew, int MinNew, byte Pos) {
	while (read_LCD_buttons() != btnSELECT) {
		if (read_LCD_buttons() == btnRIGHT) {
			if (HourNew < 23) {
				HourNew++;
			}
		}
		else if (read_LCD_buttons() == btnLEFT) {
			if (HourNew > 0) {
				HourNew--;
			}
		}
		else if (read_LCD_buttons() == btnUP) {
			if (MinNew < 59) {
				MinNew++;
			}
		}
		else if (read_LCD_buttons() == btnDOWN) {
			if (MinNew > 0) {
				MinNew--;
			}
		}
		setupShowValue(HourNew, MinNew, Pos);
		delay(150);
	}
	while (read_LCD_buttons() != btnNONE);  // Wait until the button is released
	myRTC.setDS1302Time(00, MinNew, HourNew, 6, 10, 1, 2014);
	delay(150);
}

void setupShowValue(int Hour, int Min, int Pos) {
	//lcd.setCursor(11, Pos);
  lcd.setCursor(11, 1);
	print2digits(Hour);
	lcd.print(":");
	print2digits(Min);
}

void setupShowValue2(int Hour, int Min, int Pos) {
	lcd.setCursor(11, Pos);
	print2digits(Hour);
	lcd.print(":");
	print2digits(Min);
}

// LCD funtions
int read_LCD_buttons()
{
	adc_key_in = analogRead(0); // Read the value from the sensor

	if (adc_key_in > 1000) return btnNONE; 
	if (adc_key_in < 50)   return btnRIGHT;  
	if (adc_key_in < 150)  return btnUP; 
	if (adc_key_in < 300)  return btnDOWN; 
	if (adc_key_in < 500)  return btnLEFT; 
	if (adc_key_in < 850)  return btnSELECT;  
	return btnNONE; // When all others fail, return this.
}

void eeprom_write_int(int p_address, int p_value) {
	byte lowByte = ((p_value >> 0) & 0xFF);
	byte highByte = ((p_value >> 8) & 0xFF);

	EEPROM.write(p_address, lowByte);
	EEPROM.write(p_address + 1, highByte);
}

unsigned int eeprom_read_int(int p_address) {
	byte lowByte = EEPROM.read(p_address);
	byte highByte = EEPROM.read(p_address + 1);

	return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}

void displayTime() {
	myRTC.updateTime();
	print2digits(myRTC.hours);
	lcd.print(":");
	print2digits(myRTC.minutes);
	lcd.print(":");
	print2digits(myRTC.seconds);
}

void print2digits(int number) {
	if (number >= 0 && number < 10)
		lcd.print('0');
	lcd.print(number, DEC);
}

The issue is in the logic of the relayAction function. Here’s what I think is happening:

  1. The relay turns ON (LOW) only when the current time (MinToday) exactly matches the set time (MinEprON) AND the seconds are less than 3.
  2. In all other cases, including when the seconds are 3 or more, the relay turns OFF (HIGH).

This causes the relay to turn on for only the first 3 seconds of the minute when the set time is reached. To remedy, modify the logic to keep the relay on for 3 seconds regardless of when it’s activated within a minute

void relayAction(int adrON, int pos, int pin) {
	myRTC.updateTime();
	int MinToday = (myRTC.hours * 60) + myRTC.minutes;
	int MinEprON = (EEPROM.read(adrON) * 60) + EEPROM.read(adrON + 1);

	lcd.setCursor(pos, 1);
	if (MinToday == MinEprON) {
		static unsigned long startTime = 0;
		if (startTime == 0) {
			startTime = millis();
		}
		
		if (millis() - startTime < 3000) {
			lcd.print("*");
			digitalWrite(pin, LOW);  // Turn ON the relay
		} else {
			lcd.print("-");
			digitalWrite(pin, HIGH);  // Turn OFF the relay
			startTime = 0;  // Reset the start time
		}
	} else {
		lcd.print("-");
		digitalWrite(pin, HIGH);  // Ensure the relay is OFF at other times
	}
}

To implement:

  1. Replace the relayAction function in your code with this version
  2. Make sure to include #include <Arduino.h> at the top of your file if it’s not already there, as this uses millis()