RTC relay control with button

Hi all

I’ve managed to find code to trigger a relay at a certain time, and I added code to manually trigger it with a button .The RTC code worked fine even with code to turn it off but I changed that to be turned on and off not just off Now the serial text says it’s on but the relay does not trigger but the button works fine. Any help would be appreciated.

PS I’ve noticed, when it does work, it will only trigger after the set time not on the set time.

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

int ButtonPin = 3;
int stateRelay = LOW;
int stateButton;
int previous = LOW;
long time = 0;
long debounce = 500;

// PIN definitions
#define RELAY_PIN 2


// FSM states
#define STATE_OFF  0
#define STATE_ON   1

// Timer settings
#define START_TIME  2007
#define END_TIME    2115

// variables
RTC_DS1307 RTC;
int fsm_state;

void setup() {
  
  Serial.begin(57600);
  Serial.println("SimpleTimer running...");
  Serial.println();

  Wire.begin();
  RTC.begin();  

  
}

void loop() {

  DateTime now = RTC.now();
  int nowHourMinute = now.hour() * 100 + now.minute();

  // FSM states
  switch(fsm_state) {
    
    case STATE_OFF:
      if(nowHourMinute > START_TIME && nowHourMinute < END_TIME) {
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        Serial.print(now.minute(), DEC);
        Serial.println(", it's time to wake up!");
        digitalWrite(RELAY_PIN, HIGH);
        fsm_state = STATE_ON;
      }
      break;
    
    case STATE_ON:
      if(nowHourMinute > END_TIME) {
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        Serial.print(now.minute(), DEC);        
        Serial.println(", it's time to go to sleep!");
        digitalWrite(RELAY_PIN, LOW);
        fsm_state = STATE_OFF;
      }    
      break;
  }

 
  
  stateButton = digitalRead(ButtonPin);  
  if(stateButton == HIGH && previous == LOW && millis() - time > debounce) {
    if(stateRelay == HIGH){
      stateRelay = LOW; 
      Serial.println("Relay Off");
    } else {
       stateRelay = HIGH; 
       Serial.println("Relay On");
    }
    time = millis();
  }
  digitalWrite(RELAY_PIN, stateRelay);
  previous == stateButton;
  }

Also please excuse any code layout rules I’ve broken, I am new to this.
Thanks in advance

You need to maintain only on variable otherwise the triggering by the RTC will get your other variable confused. get rid of stateRelay.

--> don't use stateRelay = LOW, use fsm_state = STATE_OFF and don't use if(stateRelay == HIGH){ but     if(fsm_state == STATE_ON){

--> maintain the coherence between your states.

J-M-L:
You need to maintain only on variable otherwise the triggering by the RTC will get your other variable confused. get rid of stateRelay.

→ don’t use stateRelay = LOW, use fsm_state = STATE_OFF and don’t use if(stateRelay == HIGH){ but    if(fsm_state == STATE_ON){

→ maintain the coherence between your states.

Hi J-M-L

Thanks for the reply
I managed to get it to work but with a new problem, I know why but don’t know how to fix it, that when it is within the set time and I press the button it will switch off and come straight back on again, what should I add to only switch off if I haven’t manually switched it off?

I think I can figure it out myself, will let you know.
here is the code that I have used from your solution:

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



// PIN definitions
#define RELAY_PIN 2


// FSM states
#define STATE_OFF  0
#define STATE_ON   1

int ButtonPin = 3;
int fsm_state = STATE_OFF;
int stateButton;
int previous = LOW;
long time = 0;
long debounce = 500;

// Timer settings
#define START_TIME  1338
#define END_TIME    2115

// variables
RTC_DS1307 RTC;


void setup() {
  
  Serial.begin(57600);
  Serial.println("SimpleTimer running...");
  Serial.println();

  Wire.begin();
  RTC.begin();  

  
}

void loop() {

  DateTime now = RTC.now();
  int nowHourMinute = now.hour() * 100 + now.minute();

  // FSM states
  switch(fsm_state) {
    
    case STATE_OFF:
      if(nowHourMinute > START_TIME && nowHourMinute < END_TIME) {
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        Serial.print(now.minute(), DEC);
        Serial.println(", Relay On by time");
        digitalWrite(RELAY_PIN, HIGH);
        fsm_state = STATE_ON;
      }
      break;
    
    case STATE_ON:
      if(nowHourMinute > END_TIME) {
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        Serial.print(now.minute(), DEC);        
        Serial.println(", Relay Off by time");
        digitalWrite(RELAY_PIN, LOW);
        fsm_state = STATE_OFF;
      }    
      break;
  }

 
  
  stateButton = digitalRead(ButtonPin);  
  if(stateButton == HIGH && previous == LOW && millis() - time > debounce) {
    if(fsm_state == STATE_ON){
      digitalWrite(RELAY_PIN,LOW); 
      Serial.println("Relay Off by Button press");
      fsm_state = STATE_OFF;
    } else {
       digitalWrite(RELAY_PIN,HIGH); 
       Serial.println("Relay On by Button press");
       fsm_state = STATE_ON;
    }
    time = millis();
  }
  //digitalWrite(RELAY_PIN, stateRelay);
  //previous == stateButton;
  }

Ok so I took out the End time part, doesn't solve the entire problem but at least it works now.

 case STATE_OFF:
      if(nowHourMinute == START_TIME ) // It would only work with "==" not "=" 
        {
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        Serial.print(now.minute(), DEC);
        Serial.println(", Relay On by time");
        digitalWrite(RELAY_PIN, HIGH);
        fsm_state = STATE_ON;
      }
      break;
    
   /* case STATE_ON:
      if(nowHourMinute > END_TIME) {
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        Serial.print(now.minute(), DEC);        
        Serial.println(", Relay Off by time");
        digitalWrite(RELAY_PIN, LOW);
        fsm_state = STATE_OFF;
      }    
      break;*/