Synchronizing relay with RTC

Hello,

Recently, I've built my first project which includes Arduino UNO, RTC1302 and LCD display, it works as a sort of clock with glitch. After advice on project that I got here, I've added relay module just for clicking/ticking purpose, so it would be on for one second and off for the other. I also would like it to be silent at 9 second (eg. :09, :29, :59 etc.). As a newbie, I have some hard time with coding.
Here is the sketch of my project:


And here is my code:

#include "virtuabotixRTC.h"//Library used
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
virtuabotixRTC myRTC(2, 3, 4); //The order here is DAT,CLK,RST. You can change this depending on the wiring

char timeChar [8]; //number of digits for the format
uint8_t prevSeconds = 0; //

void setup() 
{
  
  Serial.begin(9600);
  
  lcd.init();
  lcd.backlight();


  
  // Set the current date, and time in the following format:
  // seconds, minutes, hours, day of the week, day of the month, month, year
  //myRTC.setDS1302Time(30, 21, 00, 5, 07, 01, 2021); //Here you write your actual time/date as shown above
  //but remember to "comment/remove" this function once you're done
  //The setup is done only one time and the module will continue counting it automatically
}
void loop() 
{

  
  myRTC.updateTime();
  
  if(myRTC.seconds != prevSeconds)  // Only update display if seconds have changed
  {
    prevSeconds = myRTC.seconds;
    
    // Start printing elements as individuals
    
    if(myRTC.seconds %10)
    {
      sprintf(timeChar, "%02d:%02d:%02d",myRTC.hours, myRTC.minutes, myRTC.seconds);
      if(myRTC.seconds == 9 || myRTC.seconds == 19 || myRTC.seconds == 29 || myRTC.seconds == 39 || myRTC.seconds == 49 || myRTC.seconds == 59)
      {
        // timeChar[0] = 'Z';
        // timeChar[4] = 'X';
        timeChar[0] = random("32, 128");
        timeChar[4] = random("32, 128");
      }
    }
    else
    {
      sprintf(timeChar, "D0:0M:%02d", myRTC.seconds);
    }
    
    lcd.print(timeChar);
  }
}

Firstly, I tried to run the relay independently from the clock with this code:

#include "virtuabotixRTC.h"//Library used
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
virtuabotixRTC myRTC(2, 3, 4); //The order here is DAT,CLK,RST. You can change this depending on the wiring

char timeChar [8]; //number of digits for the format
uint8_t prevSeconds = 0; //

int Relaypin= 12;

void setup()
{
 
  Serial.begin(9600);
 
  lcd.init();
  lcd.backlight();


 
  // Set the current date, and time in the following format:
  // seconds, minutes, hours, day of the week, day of the month, month, year
  //myRTC.setDS1302Time(30, 21, 00, 5, 07, 01, 2021); //Here you write your actual time/date as shown above
  //but remember to "comment/remove" this function once you're done
  //The setup is done only one time and the module will continue counting it automatically
  pinMode(Relaypin, OUTPUT); // Define the Relaypin as output pin

}
void loop()
{
digitalWrite(Relaypin, HIGH); // Sends high signal
delay(1000); // Waits for 1 second
digitalWrite(Relaypin, LOW); // Makes the signal low
delay(1000); // Waits for 1 second

 
  myRTC.updateTime();
 
  if(myRTC.seconds != prevSeconds)  // Only update display if seconds have changed
  {
    prevSeconds = myRTC.seconds;
   
    // Start printing elements as individuals
   
    if(myRTC.seconds %10)
    {
      sprintf(timeChar, "%02d:%02d:%02d",myRTC.hours, myRTC.minutes, myRTC.seconds);
      if(myRTC.seconds == 9 || myRTC.seconds == 19 || myRTC.seconds == 29 || myRTC.seconds == 39 || myRTC.seconds == 49 || myRTC.seconds == 59)
      {
        // timeChar[0] = 'Z';
        // timeChar[4] = 'X';
        timeChar[0] = random("32, 128");
        timeChar[4] = random("32, 128");
      }
    }
    else
    {
      sprintf(timeChar, "D0:0M:%02d", myRTC.seconds);
    }
   
    lcd.print(timeChar);
  }
}

But it turned out to be a failure, as it interrupts the work of clock and LCD - it was running for some seconds and others not, and the relay didn't make the click (I've checked the relay on a separate basic code for relay and it worked properly). Would be really grateful for help or advice.

Best regards

I think random just takes numbers. You have it taking a string as an argument.
timeChar[0] = random("32, 128");

And you could use if (myRTC.seconds %10 == 9)
instead of if(myRTC.seconds == 9 || myRTC.seconds == 19 || myRTC.seconds == 29 || myRTC.seconds == 39 || myRTC.seconds == 49 || myRTC.seconds == 59)

Skipping on the 9's would be:

    if( (myRTC.seconds % 10) != 9)

Then just get rid of this:

      if(myRTC.seconds == 9 || myRTC.seconds == 19 || myRTC.seconds == 29 || myRTC.seconds == 39 || myRTC.seconds == 49 || myRTC.seconds == 59)
      {

Oh yeah, I get it now, but still I have no idea how to use RTC instead of millis for relay clicking repetitively. I figured I can't use delay in my code, because it stops the rest (it's probably common knowledge, but I'm just learning) and millis seems to complicate things since I could just use the RTC code. I've seen some other threads on that, but I still don't get it how to adapt it to my code, since I have some other if() functions. Here it is, after a slight change:

#include "virtuabotixRTC.h"//Library used
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
virtuabotixRTC myRTC(2, 3, 4); //The order here is DAT,CLK,RST. You can change this depending on the wiring

char timeChar [8]; //number of digits for the format
uint8_t prevSeconds = 0; //

int Relaypin= 12; 

int RelayState = LOW;   
  

void setup() 
{
  
  Serial.begin(9600);
  
  lcd.init();
  lcd.backlight();

  pinMode(Relaypin, OUTPUT);


  
  // Set the current date, and time in the following format:
  // seconds, minutes, hours, day of the week, day of the month, month, year
  //myRTC.setDS1302Time(30, 21, 00, 5, 07, 01, 2021); //Here you write your actual time/date as shown above
  //but remember to "comment/remove" this function once you're done
  //The setup is done only one time and the module will continue counting it automatically
}
void loop() 
{

  
  myRTC.updateTime();
  
  if(myRTC.seconds != prevSeconds)  // Only update display if seconds have changed
  {
    prevSeconds = myRTC.seconds;
    
    // Start printing elements as individuals
    
    if(myRTC.seconds %10)
    {
      sprintf(timeChar, "%02d:%02d:%02d",myRTC.hours, myRTC.minutes, myRTC.seconds);
      if(myRTC.seconds %10 == 9)
      {
        // timeChar[0] = 'Z';
        // timeChar[4] = 'X';
        timeChar[0] = random("32, 128");
        timeChar[4] = random("32, 128");
      }
    }
    else
    {
      sprintf(timeChar, "D0:0M:%02d", myRTC.seconds);
    }
    
    lcd.print(timeChar);
    }
    
  
}

I've also seen the "Blinking without delay" one, but I am slightly confused about "ledState" (in my case relayState) part, does it define the starting point for the relay?

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }

I've tried to adapt it in multiple ways, unfortunately I need some guidance on that.

Weird because you are using the RTC for printing time. Why not just click the relay when you do that?

We can't guess the multiple ways you tried, for input on that you need to post them.

Oh, okay, nevermind, I figured that out. Thanks!

This is the code:

#include "virtuabotixRTC.h"//Library used
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
virtuabotixRTC myRTC(2, 3, 4); //The order here is DAT,CLK,RST. You can change this depending on the wiring

char timeChar [8]; //number of digits for the format
uint8_t prevSeconds = 0; //

int relayPin= 12; 

int relayState= LOW;   

unsigned long previousMillis = 0;

const long interval = 1000; 
  

void setup() 
{
  
  Serial.begin(9600);
  
  lcd.init();
  lcd.backlight();

  pinMode(relayPin, OUTPUT);


  
  // Set the current date, and time in the following format:
  // seconds, minutes, hours, day of the week, day of the month, month, year
  //myRTC.setDS1302Time(30, 21, 00, 5, 07, 01, 2021); //Here you write your actual time/date as shown above
  //but remember to "comment/remove" this function once you're done
  //The setup is done only one time and the module will continue counting it automatically
}
void loop() 
{

  unsigned long currentMillis = millis();

  
  myRTC.updateTime();
  
  if(myRTC.seconds != prevSeconds)  // Only update display if seconds have changed
  {
    prevSeconds = myRTC.seconds;
    
    // Start printing elements as individuals
    
    if(myRTC.seconds %10)
    {
      sprintf(timeChar, "%02d:%02d:%02d",myRTC.hours, myRTC.minutes, myRTC.seconds);
      if(myRTC.seconds %10 == 9)
      {
        // timeChar[0] = 'Z';
        // timeChar[4] = 'X';
        timeChar[0] = random("32, 128");
        timeChar[4] = random("32, 128");
      }
    }
    else
    {
      sprintf(timeChar, "D0:0M:%02d", myRTC.seconds);
    }
    
    lcd.print(timeChar);
    }

   
  
    if( (myRTC.seconds % 10) != 9) 
    {
       if (currentMillis - previousMillis >= interval) {

    previousMillis = currentMillis;


    if (relayState == LOW) {
      relayState = HIGH;
    } else {
      relayState = LOW;
    }

    digitalWrite(relayPin, relayState);
  }
    }

    
    
  
}

This one works, as I wanted it to.

1 Like

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