loading
Few, yes very few things that I have encountered from playing with Arduino has given me as much grief as the DS1307 modules.  On the surface, these clock-calendar chips and associated break-out boards seem to be a great idea if you are dealing with sketches that must output reasonably accurate time/date over some long periods.  Most breakout boards even come with a backup battery to keep the DS1307 happy when the external power source is off.

But these little marvels come completely brain-dead!  Ignorant... like a battery powered watch, they are useless until set.  But Arduino users generally must load a sketch into their boards, connect the DS1307, and then run the sketch to program the time and date registers.  Which is OK except a month later when you go to check and find that the DS1307 has drifted a couple of minutes.  Well, maybe that is not a big deal for some, but I'm anal and I want my data loggers to have time more accurate than the inexpensive DS1307 modules will support.

I tried buying some quality crystals and replacing the stock crystal.  That actually worked and this is where the 20 seconds every 24 hours shifted to 4 seconds every 24 hours.  Not bad.  But sometimes I do not use the data logger for a few months.  Now, I have to load the Arduino sketch, set the time and date, and then reload my data logger sketch.  Pretty annoying and even though it was just a little thing, it really grated on my psyche.

So, I decided to write my own set routine where I could set the date once and set the time anytime or just "hack" the seconds if that was all that was necessary.  I did not want to deal with keyboards or terminals, so I rewrote a sketch I found for the ATtiny85 which can host an Infrared detector.  With this less-than-$2 circuit, I can now use a $1 universal controller from the "dollar store" and my UNO and Mega sketches do not have to poll for IR since the IR activity is handled separately and the normally unused hardware serial input is used to identify that the remote control has activated the Power Button and IR commands are awaiting.  If the user presses Power on the remote again, the UNO sketch simply returns to doing what it was doing.  The ONLY wasted instruction in the main sketch is just to check the serial buffer:

if (Serial.available() > 0)    // Something from IR is in the serial buffer
 
Most sketches can live with that!  The test sketch that follows compiles to 13,664 Bytes on an UNO with 32,256 Bytes of flash, or about 42%.  However, much of the code is "library" code and not specific to the DS1307, or to put it into prospective, 23% of the 42% is library code for serial and I2C.



 

Step 1: ATtiny85 Code

There are two (2) sets of code: one for the ATtiny85 and one for the ATmega328P (UNO).  I have also tested the code with minor modifications on the ATMega2560, the Mini, and the Nano.  Please use the PDF versions to copy code since I have found a few source code characters "eaten alive" by the Instructables editor (that is, <PRE> and </PRE> codes not completely respected... especially in the #include <library> statements.

ATtiny85
This code can be compiled and loaded into the "tiny85" chip using ISP.  Check Instructables as there are several articles on how to do this easily, or see: http://hlt.media.mit.edu/?p=1695

/*
  IR remote control (Sony) detection for Arduino, M. Burnette
  Binary sketch size: 2,794 bytes (of a 8,192 byte maximum)
  :  20130103 MRB Modified for interface to Mega2560
      Europa codebase for menu system
     
  :  20121230 MRB Modified for Tiny85 Google Tiny library
      Tiny85 Internal RC 16MHz
  :  20121230 MRB modifications to adapt to numeric input, avoid dupes,
      and to generally "behave" consistently
  :  Used with Electronic Goldmine IR detector MIM 5383H4
      http://www.goldmine-elec-products.com/prodinfo.asp?number=G16737
  :  IR detector:
      Pin 1: To pin D4 on Arduino ATtiny85
      Pin 2: GND
      Pin 3: 5V through 33 Ohm resistor
:  This is based on pmalmsten's code found on the Arduino forum from 2007:
      http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1176098434/0
*/
// Pins 2/3 used for Software serial
int irPin     = 4;       //Sensor pin 1 wired to Arduino's pin D4
int statLED   = 0;       //Toggle the status LED every time Power is pressed
int start_bit = 2200;    //Start bit threshold (Microseconds)
int bin_1     = 1000;    //Binary 1 threshold (Microseconds)
int bin_0     = 400;     //Binary 0 threshold (Microseconds)
void setup() {
  pinMode(statLED, OUTPUT);
  digitalWrite(statLED, LOW);
  pinMode(irPin, INPUT);
  Serial.begin(9600);
  Serial.println("IR/Serial Initialized: ");
}
void loop() {
  int key = getIRKey();   //Fetch the key
 
  if(key != 0)            //Ignore keys that are zero
  {
    switch(key)
    {
      case 128: Serial.print("1"); break;
      case 129: Serial.print("2"); break;
      case 130: Serial.print("3"); break;
      case 131: Serial.print("4"); break;
      case 132: Serial.print("5"); break;
      case 133: Serial.print("6"); break;
      case 134: Serial.print("7"); break;
      case 135: Serial.print("8"); break;
      case 136: Serial.print("9"); break;
      case 137: Serial.print("0"); break;
            case 144: Serial.print("A"); break;  // CH Up
      case 145: Serial.print("B"); break;  // CH Down
      case 146: Serial.print("C"); break;  // VOL Right
      case 147: Serial.print("D"); break;  // VOL Left
      case 148: Serial.print("E"); break;  // Mute
      case 165: Serial.print("F"); break;  // AV/TV
      case 149: Serial.print("P");         // Power == MENU ACTIVE
        //This toggles the statLED every time power button is hit
        if(digitalRead(statLED) != 1)
          digitalWrite(statLED, HIGH);
        else
          digitalWrite(statLED, LOW);
        break;
      //default: Serial.println(key); // for inspection of keycode
    }
    delay(400);    // avoid double key logging (adjustable)
  }
}
int getIRKey() {
  int data[12];
  int i;
  while(pulseIn(irPin, LOW) < start_bit); //Wait for a start bit
 
  for(i = 0 ; i < 11 ; i++)
    data[i] = pulseIn(irPin, LOW);      //Start measuring bits, I only want low pulses
  for(i = 0 ; i < 11 ; i++)             //Parse them
  {    
    if(data[i] > bin_1)                 //is it a 1?
      data[i] = 1;
    else if(data[i] > bin_0)            //is it a 0?
      data[i] = 0;
    else
      return -1;                        //Flag the data as invalid; I don't know what it is! Return -1 on invalid data
  }
  int result = 0;
  for(i = 0 ; i < 11 ; i++)             //Convert data bits to integer
    if(data[i] == 1) result |= (1<<i);
  return result;                        //Return key number
}

I have shown in the graphic that a AX-1838HS was used for the IR detector.  I have also used MIM-5383H4 which is also 38KHz.  But please note that the MIM device is a different pinout!

The circuit for the ATtiny85 is very simple:
ATtiny PIN #1     Reset (this should be connected to the main Arduino RESET)
ATtiny PIN #2     Not used
ATtiny PIN #3     Leg #1 of the AX-1838 IR detector
ATtiny PIN #4     Connect to Arduino Gnd (ground)
ATtiny PIN #5     anode of optional LED
ATtiny PIN #6     Not used
ATtiny PIN #7     9600 BAUD serial output TO Arduino D0 (Rx0) *
ATtiny PIN #8     Connect to Arduino +5V

* Note: You MUST disconnect this line (suggest a simple switch or jumper) to program the Arduino UNO.  This is because the onboard USB-serial converter also drives the Rx0 line through a 1K resistor.


ATtiny85 Board and Core Selection:
From this link: http://code.google.com/p/arduino-tiny/downloads/detail?name=arduino-tiny-0100-0015.zip

Step 2: UNO Code

The UNO Sketch to manage reading the Rx0 status and then accepting serial input from the ATtiny85.
Please use the PDF versions to copy code since I have found a few source code characters "eaten alive" by the Instructables editor (that is, <PRE> and </PRE> codes not completely respected... especially in the #include <library> statements.

// (c) 2013 M. Ray. Burnette, Atlanta, GA
// Arduino UNO Compiler version 1.0.1+
// Binary sketch size: 13,664 bytes (of a 32,256 byte maximum)
// #include  // default lib searched in 1.0+
#include            // Library
#include "Wire.h"              // System library for I2C
#define DS1307_I2C_ADDRESS 0x68 // Realtime Clock module
// Type Variable Declarations
int incomingByte = 0;   // for incoming serial data
int OLED_Tx     =  3;   // Serial out for OLED
// DS1307 variables
byte second = 0, minute = 0, hour = 0, dayOfWeek = 0, dayOfMonth = 0, month = 0,
year = 0;
AXE133Y OLED =  AXE133Y(OLED_Tx);
// Private function: from http://arduino.cc/playground/Code/AvailableMemory 
int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)  {
  return ( (val/10*16) + (val%10) );
  }
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)  {
  return ( (val/16*10) + (val%16) );
  }
// Gets the date and time from the ds1307
void getDataDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
  {
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write((byte)0);
  Wire.endTransmission();
 
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour
am/pm
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
  }void setDataDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
  {
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.write(0);
   Wire.write(decToBcd(second));   // 0 to bit 7 starts the clock
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));     // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
  }
// Arduino-specific configuration code initialization section
void setup() {
  Wire.begin();
  Serial.begin(9600);    // Hardware serial port to PC, port for Rx from IR
controller ATtiny85
  Serial.println("Coming online...");
  while (Serial.available() > 0) Serial.read();    // Pseudo .flush() to clear input
buffer R1x garbage for IR
  OLED.clearScreen();
  OLED.splash("Coming online...");
  delay(500);
  OLED.clearScreen();
}
// Main Program Loop
void loop() {
  //
____________________________________________________________________________________
_________________
  getDataDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  Serial.print(hour, DEC);
  Serial.print(":");
  Serial.print(minute, DEC);
  Serial.print(":");
  Serial.print(second, DEC);
  Serial.print("  ");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.println(year, DEC);
//
____________________________________________________________________________________
_________________
    if (Serial.available() > 0)    // Something from IR is in the serial buffer
    {
       while(true)                  // Big loop ensures similar behavior for Time
and Date setup
       {
            // read the incoming byte:
            incomingByte = Serial.read();            // log what was extracted to system log:
            Serial.print("IR keycode received: ");
            Serial.println(incomingByte, DEC);
            if (incomingByte != 80) break;  // Only interested in Menu request
(ON/off)
            {
              Serial.println("Menu request received on IR link");
              while (Serial.available() > 0) Serial.read();    // Pseudo 1.flush()
              Serial.println("Serial receive buffer 1 cleared");
              Serial.println("Entering DS1307 set menu");
              restartMenu:
                OLED.clearScreen();
                OLED.cursorPosition(1,0);
                OLED.print("Press 1 for TIME");
                OLED.cursorPosition(2,0);
                OLED.print("Press 2 for CAL");
                while (Serial.available() > 0) Serial.read();    // Pseudo 1.flush()
                while (Serial.available() == 0) ;  // wait for digit on IR
                incomingByte = Serial.read() ;
                if (incomingByte == 80) { goto menuexit; }        // on/OFF
                if (incomingByte == 50) { goto calendarSet; }    // #2
                if (incomingByte == 49) { goto timeSet; }        // #1
                goto restartMenu;
                //byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
            }
            timeSet:
            {
                OLED.clearScreen();
                OLED.cursorPosition(1,0);
                OLED.print("Enter 2 Digits:");
                seconds:
                OLED.cursorPosition(2,0);
                OLED.print("Seconds hh-mm-SS");            // SS position 14, 15
                while (Serial.available() == 0) ;          // wait for digit on IR
                incomingByte = Serial.read() ;
                if (incomingByte == 80) { goto menuexit; }
                int temp = (incomingByte - 48) * 10;        // "tens" digit
                if (temp > 50) { goto seconds; }            // bad input
                OLED.cursorPosition(2, 14);
                OLED.printFloat(incomingByte - 48, 1, 0);  // show the high-order
seconds digit
                while (Serial.available() == 0) ;          // wait for digit on IR
channel
                incomingByte = Serial.read();
                temp += (incomingByte - 48);                // add tens digit to
unit digit
                if(temp >59) { goto seconds; }              // error check
                // read the RTC, modify seconds, write it quickly back to RTC
                getDataDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth,
&month, &year);
                second = temp;
                setDataDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month,
year);
                OLED.cursorPosition(2, 14);
                OLED.printFloat(temp, 2, 0);  // display seconds
                // write to system log stream
                Serial.print("Seconds have been set to: ");
                Serial.println(temp, DEC);
                minutes:
                OLED.cursorPosition(2,0);
                OLED.print("Minutes hh-MM");              // MM position 11, 12
                while (Serial.available() == 0);          // wait for digit on IR                incomingByte = Serial.read() ;
                if (incomingByte == 80) { goto menuexit; }  // on/OFF?
                temp = (incomingByte - 48) * 10;            // "tens" digit
                if (temp > 50) { goto minutes; }            // error check
                OLED.cursorPosition(2, 11);
                OLED.printFloat(incomingByte - 48, 1, 0);  // show the high-order
minutes digit
                while (Serial.available() == 0) ;          // wait for digit on IR
serial channel
                incomingByte = Serial.read();
                temp += (incomingByte - 48);                // unit digit added to
tens digit
                if(temp >59) { goto minutes; }              // error check
                // read the RTC, modify seconds, write it quickly back to RTC
                getDataDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth,
&month, &year);
                minute = temp;
                setDataDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month,
year);
                OLED.cursorPosition(2, 11);
                OLED.printFloat(temp, 2, 0);  // display minutes
                // Write to system log stream
                Serial.print("Minutes have been set to: ");
                Serial.println(temp, DEC);
                hours:
                OLED.cursorPosition(2, 0);
                OLED.print("Hours   HH");                  // HH position 8, 9
                while (Serial.available() == 0) ;          // wait for digit on IR
                incomingByte = Serial.read() ;
                if (incomingByte == 80) { goto menuexit; }  // on/OFF ?
                temp = (incomingByte - 48) * 10;            // 'tens' digit
                if (temp > 20) { goto hours; }              // error check
                OLED.cursorPosition(2, 8);
                OLED.printFloat(incomingByte - 48, 1, 0);   // show the high-order
minutes digit
                while (Serial.available() == 0) ;           // wait for digit on IR
                incomingByte = Serial.read();
                temp += (incomingByte - 48);
                if(temp >23) { goto hours; }        // error check
                // read the RTC, modify seconds, write it quickly back to RTC
                getDataDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth,
&month, &year);
                hour = temp;
                setDataDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month,
year);
                OLED.cursorPosition(2, 0);
                OLED.print("Time:     ");  // HH position 8, 9
                OLED.cursorPosition(2, 8);
                OLED.printFloat(temp, 2, 0);
                // send status information over system log link
                Serial.print("Hours have been set to: ");
                Serial.println(temp, DEC);
                while (Serial.available() > 0) Serial.read();    // Pseudo 1.flush()
                OLED.cursorPosition(1,0);
                OLED.print("Press Remote OFF");
                incomingByte = Serial.read();
            }
              // Display the real-time second-by-second while remote power ON/off is
ON
              do
                {
                getDataDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth,
&month, &year);
                OLED.cursorPosition(2, 0);                OLED.print("Time:     ");  // HH position 8, 9  MM position 11, 12 
SS position 14, 15
                OLED.cursorPosition(2, 8);
                OLED.printFloat(hour, 2, 0);
                OLED.cursorPosition(2, 11);
                OLED.printFloat(minute, 2, 0);
                OLED.cursorPosition(2, 14);
                OLED.printFloat(second, 2, 0);
                delay(1000);
                incomingByte = Serial.read();
                }  while( incomingByte != 80);
                goto menuexit;
                // User pressed "2" in response to 1/2 menu choice
                calendarSet:
                {
                  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
                  int temp;
                  OLED.clearScreen();
                  OLED.cursorPosition(1,0);
                  OLED.print("Enter Day Of Mn");
                  // dayOfMonth
 
                  dayMonth:
                  OLED.cursorPosition(2,0);
                  OLED.print("Date:   yy-mm-DD");              // DD position 14, 15
                  while (Serial.available() == 0) ;            // wait for digit on
IR
                  incomingByte = Serial.read() ;
                  if (incomingByte == 80) { goto menuexit; }    // on/OFF pressed?
                  temp = (incomingByte - 48) * 10;
                  if (temp > 30) { goto dayMonth; }
                  OLED.cursorPosition(2, 14);
                  OLED.printFloat(incomingByte - 48, 1, 0);    // show the highorder digit
                  while (Serial.available() == 0) ;            // wait for digit on
IR
                  incomingByte = Serial.read();
                  temp += (incomingByte - 48);
                  if(temp > 31) { goto dayMonth; }
                  // read the RTC, modify dayOfMonth, write it quickly back to RTC
                  getDataDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth,
&month, &year);
                  dayOfMonth = temp;
                  setDataDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month,
year);
                  OLED.cursorPosition(2, 14);
                  OLED.printFloat(temp, 2, 0);                  // display day-ofmonth
                  Serial.print("Day Of Month has been set to: ");
                  Serial.println(temp, DEC);
 
                  // Month
                  Month:
                  OLED.cursorPosition(2, 0);
                  OLED.print("Date:   yy-MM-");                // MM position 11, 12
                  while (Serial.available() == 0) ;            // wait for digit on
IR
                  incomingByte = Serial.read() ;
                  if (incomingByte == 80) { goto menuexit; }    // on/OFF pressed?
                  temp = (incomingByte - 48) * 10;
                  if (temp > 10) { goto Month; }
                  OLED.cursorPosition(2, 11);
                  OLED.printFloat(incomingByte - 48, 1, 0);    // show the highorder digit                  while (Serial.available() == 0);             // wait for digit on
IR
                  incomingByte = Serial.read();
                  temp += (incomingByte - 48);
                  if(temp > 31) { goto Month; }
                  // read the RTC, modify month, write it quickly back to RTC
                  getDataDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth,
&month, &year);
                  month = temp;
                  setDataDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month,
year);
                  OLED.cursorPosition(2, 11);
                  OLED.printFloat(temp, 2, 0);  // display month
                  Serial.print("Month has been set to: ");
                  Serial.println(temp, DEC);
 
                  // Year
                  Year:
                  OLED.cursorPosition(2,0);
                  OLED.print("Date:   YY-");                // YY position 8, 9
                  while (Serial.available() == 0) ;         // wait for digit on IR
                  incomingByte = Serial.read() ;
                  if (incomingByte == 80) { goto menuexit; }
                  temp = (incomingByte - 48) * 10;
                  if (temp > 10) { goto Year; }
                  OLED.cursorPosition(2, 8);
                  OLED.printFloat(incomingByte - 48, 1, 0);  // show the high-order
digit
                  while (Serial.available() == 0) ;          // wait for digit on IR
                  incomingByte = Serial.read();
                  temp += (incomingByte - 48);                // any year from 00 to
99 OK
                  // read the RTC, modify year, write it quickly back to RTC
                  getDataDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth,
&month, &year);
                  year = temp;
                  setDataDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month,
year);
                  OLED.cursorPosition(2, 8);
                  OLED.printFloat(temp, 2, 0);                // display year
                  Serial.print("Year has been set to: ");
                  Serial.println(temp, DEC);
                  while (Serial.available() > 0) Serial.read(); // Pseudo 1.flush()
                  OLED.cursorPosition(1,0);
                  OLED.print("Press Remote OFF");
                  incomingByte = Serial.read();
                  // Display the date while remote power ON/off is ON
                  getDataDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth,
&month, &year);
 
                  do                                  // loop date until on/OFF
pressed
                    {
                    OLED.cursorPosition(2, 0);
                    OLED.print("Date: 20  -  -  ");  // 20YY position 6, 7, 8, 9  MN
position 11, 12  DOM position 14, 15
                    OLED.cursorPosition(2, 8);
                    OLED.printFloat(year, 2, 0);
                    OLED.cursorPosition(2, 11);
                    OLED.printFloat(month, 2, 0);
                    OLED.cursorPosition(2, 14);
                    OLED.printFloat(dayOfMonth, 2, 0);
                    incomingByte = Serial.read();
                    }  while( incomingByte != 80);
                }              menuexit:
              while (Serial.available() > 0) Serial.read();    // Pseudo 1.flush()
              OLED.clearScreen();
       }
    }
    delay(1000);    // Wait 1 second, then update the display
}

Connections to the Arduino:
DS1307 BAT     not connected
DS1307 GND   connect to Arduino Gnd
DS1307 VCC    connect to Arduino +5V
DS1307 SDA    connect to UNO A4 *
DS1307 SDC   connect to UNO A5 *
DS1307 DS      not connected
DS1307 SQ     not connected

* Note: for the UNO, these are the defaults.  Mega2560 uses different pins for SDA/SDC

Step 3: Smoke Test

Remember, either load the sketch into your UNO, remove power, connect, restore power OR you must at least open the ATtiny85 connection to Rx0 to program the UNO.  I strongly recommend using a shorting jumper or switch if you plan of making changes to the sketch and uploading for testing.

Here is a sample terminal session from the Arduino terminal (via the USB serial connection):

Coming online...

IR keycode received: 80
Menu request received on IR link
Serial receive buffer 1 cleared
Entering DS1307 set menu
Day Of Month has been set to: 19
Month has been set to: 2
Year has been set to: 13
IR keycode received: -1

Coming online...
12:12:19  2/19/13
12:12:20  2/19/13

IR keycode received: 80
Menu request received on IR link
Serial receive buffer 1 cleared
Entering DS1307 set menu
Seconds have been set to: 40
Minutes have been set to: 14
IR keycode received: -1
12:14:49  2/19/13
12:14:50  2/19/13
12:14:51  2/19/13
Your universal remote should be set to "SONY" default/TV mode.  Some Sony entertainment codes will not work, but I have used several cheap universal remotes and the Sony TV (default or 1st listed) have worked for me.

If you have enabled the LED on the ATtiny85, the LED should turn On/Off with the Remote Control Power button.

With the ATtiny85 serial signal (9600BAUD) connected to the UNO PIN D0 (Rx0) and the Arduino reset, the LED / OLED display should show Coming online... and the same text should be seen on the Arduino serial terminal (over USB.)

After the initialization, the UNO will display the time & date every second as shown in the above listing.  The last instruction in the above sketch sets the timing:  delay(1000);    // Wait 1 second, then update the display

Pressing the remote power button should immediately illuminate the ATtiny85 LED.  Within 1 second the UNO should respond on the Arduino terminal:
IR keycode received: 80
Menu request received on IR link
Serial receive buffer 1 cleared
Entering DS1307 set menu

Select 1 or 2 on the Universal remote to enter the Time Set or the Calendar Set menu.  With the time set menu, you can "hack" the seconds by entering the seconds (both digits) and then turning OFF the remote.  The UNO will update the seconds in the DS1307 and return to the running program.

Have fun.

- Ray
Most Excellent Instructable Ray !! <br>A truly Awesome insight into the lazy operation of these DS1307 RTC Modules !! <br> <br>Im really annoyed at their ability to lose so much time per 24 hours too and am now collecting the parts needed for your great instructable !!! <br> <br>May i kindly ask you what the frequency crystal is that you used to replace the stock crystal on these modules that eliminated the time-wastage from 20 seconds every 24 hours to about 4 seconds as i would also like to replace the crystal too but clueless as to what frequency crystal should be used ! <br> <br>The DS1307 datasheet says to use a specific 32.768 Khz Quartz Crystal - is this the one you used by any chance ?!? <br> <br>many thanks in advance for this help ! <br> <br>kindest regards !
I had a few of these from another project in my parts bin:<br>http://www.newark.com/ael-crystals/x32k768l104/watch-crystal-32-768khz-12-5pf/dp/96K4261<br><br>These are 20 ppm and seem to be a a great replacement. I'm sure competitive devices can be sourced from numerous vendors.<br><br>Ray
Absolutely AWESOME Info - thanks so much ! <br> <br> so sorry about the delay in reply, 20 ppm is the info i never knew about to look for in the crystal specs, are there more accurate than that easily available if you know ?!?
NP... generally I have found that the &quot;ppm&quot; will have some impact on pricing... the lower the ppm the higher the quality and the higher the price. This is just a rule-of-thumb and does not always apply since volume manufacturing also plays a part. We hobbyists enjoy lower prices on parts that are used in general high volume electronics.
Neat set up and I like your approach. I am anal about accurate time also (why bother keeping track otherwise?). I ended up building one without a clock module using only a network shield attached to a small wireless access point that routinely checks the timeservers every 6 hours... I will post it soon once I feel it is ready, still testing it and it seems pretty stable so far...

About This Instructable

1,414views

10favorites

License:

Bio: Ray Burne is my pseudonym, I sometimes write on various Blogs and Sites. Effective 12 June 2013, Ray has decided to no longer participate as ... More »
More by RayBurne:Minty Magic Morse - Arduino Style PICAXE Pitcher Perfect Thermometer A PICAXE Infrared "logging" Thermometer 
Add instructable to: