Using data from DS1307 RTC to trigger event

Hi

I am attemting to build an led clock which acts like a analog clock except without the hands. I have set up several shift registers to drive all the leds around the clock face. Now that part is working fine I am just having trouble getting the data from the RTC and using that to trigger the next led to turn on.

For example very second I want one more led to turn on. To do that I want to use the second output of the RTC and compare that to a pre stored RTC second value and if it is different then turn on the next led. Is this the best way to approach this? Or maybe I could put that in an interrupt which sets a flag high every time the second value from the RTC changes?

Here is the code I am using to get the data from the RTC. It works fine, I can set the time and view the time/date over the serial connection.

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib

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

RTC_DS1307 RTC;

void setup () {
    Serial.begin(57600);
    Wire.begin();
    RTC.begin();

  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
}

void loop () {
    DateTime now = RTC.now();
    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();

    delay(1000);
}

Here is the code I am using just as a proof of concept at the moment. It controls eight shift registers connected together with 64 leds. It steps through each one lighting them all up in sequence. It is just using the delay() function to get the one second delay. I would like the RTC to do this instead.

//Pin Definitions
// 7HC595N has three pins
int data = 11; // where we send the bits to control outputs 
int clock = 12; // keeps the data in sync
int latch = 8; // tells the shift register when to activate the output sequence

byte numbers[10] = {B00000000,B00000001,B00000011,B00000111,B00001111,B00011111,B00111111,B01111111,B11111111};

byte one   = B00000001;
byte two   = B00000011;
byte three = B00000111;
byte four  = B00001111;
byte five  = B00011111;
byte six   = B00111111;
byte seven = B01111111;
byte eight = B11111111;
byte nine  = B00000111;
byte blank = B00000000;

int flag = 0;
int time = 1000; // delay between each led step i.e. 1 second
int timezero = 0; // sets the delay to zero so that changing between the blocks of code for each shift register are smooth
int timesave = 1000; //Resets the time back to the actual value of delay between each step. i.e. 1 second
void setup()
{
   // set the three control pins to output
  pinMode(data, OUTPUT);
  pinMode(clock, OUTPUT);  
  pinMode(latch, OUTPUT);  


}
void loop(){
  
 
  for(int i=flag;i<=8;i++){
   digitalWrite (latch, LOW);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, numbers[i]);
   digitalWrite (latch, HIGH);
   if(i==8){
     time=timezero;
   }
   delay(time);
   }
   time=timesave;
 
  for(int i=0;i<=8;i++){
   digitalWrite (latch, LOW);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, numbers[i]);
   shiftOut (data, clock, MSBFIRST, eight);
   digitalWrite (latch, HIGH);
   if(i==8){
     time=timezero;
    }
   
   delay(time);
   time=timesave;
   }
   
    for(int i=0;i<=8;i++){
   digitalWrite (latch, LOW);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, numbers[i]);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   digitalWrite (latch, HIGH);
   if(i==8){
    time=timezero;
    flag = 1;
   }
   delay(time);
   }
   time=timesave;
   
  
   
      for(int i=0;i<=8;i++){
   digitalWrite (latch, LOW);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, numbers[i]);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   digitalWrite (latch, HIGH);
   if(i==8){
    time=timezero;
    flag = 1;
   }
   delay(time);
   }
   time=timesave;
 
 
  
     for(int i=0;i<=8;i++){
   digitalWrite (latch, LOW);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, numbers[i]);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   digitalWrite (latch, HIGH);
   if(i==8){
    time=timezero;
    flag = 1;
   }
   delay(time);
   }
   time=timesave;
  
 
    for(int i=0;i<=8;i++){
   digitalWrite (latch, LOW);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, numbers[i]);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   digitalWrite (latch, HIGH);
   if(i==8){
    time=timezero;
    flag = 1;
   }
   delay(time);
   }
   time=timesave;
   
      for(int i=0;i<=8;i++){
   digitalWrite (latch, LOW);
   shiftOut (data, clock, MSBFIRST, blank);
   shiftOut (data, clock, MSBFIRST, numbers[i]);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   digitalWrite (latch, HIGH);
   if(i==8){
    time=timezero;
    flag = 1;
   }
   delay(time);
   }
   time=timesave;
 
    for(int i=0;i<=9;i++){
   digitalWrite (latch, LOW);
   shiftOut (data, clock, MSBFIRST, numbers[i]);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   shiftOut (data, clock, MSBFIRST, eight);
   digitalWrite (latch, HIGH);
   if(i==9){
    time=timezero;
    flag = 1;
   }
   delay(time);
   }
   time=timesave;

This is my first post so please bear with me. Thanks

To do that I want to use the second output of the RTC and compare that to a pre stored RTC second value and if it is different then turn on the next led.

And change the stored value.

Is this the best way to approach this?

It's a relatively simple way. The other is just to update the display based on "now" every pass through loop.

Or maybe I could put that in an interrupt which sets a flag high every time the second value from the RTC changes?

What else is the Arduino doing, that it needs to be interrupted? There is, as far as I know, no way for the RTC to generate an interrupt when the second value changes.

You can program the DS1307 to output a 1Hz square wave on Pin 7. Connect that pin to Arduino digital pin 2 and then attach interrupt zero (set to trigger on FALLING edge) to a routine which does what you want each second.

Pete

To do that I want to use the second output of the RTC and compare that to a pre stored RTC second value and if it is different then turn on the next led. And change the stored value.

I will try this method I think. Could you give me a quick example of how you would take, for example the second output from the RTC and store it as a value and then compare it.

If I take this function here:

Serial.print(now.second(), DEC);

It prints out the value of the seconds from the RTC in decimal.

Can I just take the now.second() out and store it in a value like this:

storedval= now.second();

What do I declare storedval as? Is it a byte?

if this works then I can just compare it to another value. Say storedval1 and if it is different to storedval then step the leds by one second.

Sorry if this is a bit of a dumb question but I just can't quite grasp how it works at the moment

Can I just take the now.second() out and store it in a value like this:

storedval= now.second();

You won't break anything trying that.

What do I declare storedval as? Is it a byte?

The possible range of valid values tells you the type of variable that you need to use. Since the range of valid values is 0 to 60, and the upper and lower limits fit in a byte, then, yes, byte is a good type to use.

if this works then I can just compare it to another value. Say storedval1 and if it is different to storedval then step the leds by one second.

Yes, but use names that make sense, like currSec and prevSec.

Sorry if this is a bit of a dumb question but I just can't quite grasp how it works at the moment

byte currSec = now.second();
if(currSec != prevSec)
{
   // Clock ticked over another second
   // Update the display
   prevSec = currSec;
}

Presumably, once you get beyond the proof of concept stage, you're going to want to set your leds to show the current time you're reading from the RTC. To do that, you're going to need a routine that grabs the time and sets the leds accordingly that you'll use when you power the system up. Consider then, as PaulS suggested earlier, just using that routine on every iteration of loop - then there's no need to keep track of when any portion of the time data ticks over.