[solved] Problems setting DS1307 RTC clock

I have a DS1307 RTC clock chip. I can read the time fine, but can’t seem to set the clock. Any idea what I’m doing wrong?

The code below just has some random numbers to check the set functions, but if you type ‘s’ to set the chip, then ‘r’ to read it, nothing’s changed.

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68  // This is the I2C address

int command = 0;
int i;
long prevMillis = 0;
byte second = 0;
byte minute = 0;
byte hour = 0;
byte dayOfWeek = 1;
byte dayOfMonth = 1;
byte month = 1;
byte year = 13;
byte zero = 0x00;

void setup() {
  Wire.begin();
  Serial.begin(9600); 
  Serial.println("S to set time, R to read time, D to display current time");
}

void loop(){
  if (Serial.available()){
    command = Serial.read();
    Serial.print("Command: ");
    Serial.println(command);
    if (command == 83 || command == 115){  // S or s to set time
      Serial.println("Setting time...");
      setRTC();
      printTime();
    }
    else if (command == 82 || command == 114){
      Serial.println("Getting RTC time...");
      readRTC();
      printTime();
    }
    else if (command == 68 || command == 100){
      Serial.println("Printing time...");
      printTime();
    }
  }
  command = 0;
  delay(100);

}

void printTime(){
  if (hour < 10)
    Serial.print("0");
  Serial.print(hour, DEC);
  Serial.print(":");
  if (minute < 10)
    Serial.print("0");
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second < 10)
    Serial.print("0");
  Serial.print(second, DEC);
  Serial.print("  ");
  Serial.print(dayOfWeek);
  Serial.print(", ");
  Serial.print(month);
  Serial.print("/");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.println(year, DEC);
}

// Gets the date and time from the ds1307 and prints result
void readRTC()
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(zero);
  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 setRTC()                
{
  second = 30; // Use of (byte) type casting and ascii math to achieve result.  
  minute = 22; // (ascii 48 = "0"; use Serial.read to read the date from the 
  hour = 10;  // serial port
  dayOfWeek = 2;
  dayOfMonth = 14;
  month = 3;
  year= 12;
  
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.write(0);
  Wire.endTransmission();
}

// 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) );
}

When you say "nothing changed" do you mean that it remains as the value that you set (ie, clock is not changing) or that setting the clkock did not work?

Is the clock running (there is a command register bit to set the clock to run, and it is not set by default)?

I have in my library code repository (link below) a library for the DS1307 that I wrote some time ago. It has an example program that allows you to explore the registers, set and read the clock, through the serial monitor. Maybe use that initially to see what the different memory registers of the clock chip are set to.

    if (command == 83 || command == 115){  // S or s to set time

could be:

    if (command == 'S' || command == 's'){  // No comment needed
  command = 0;
  delay(100);

Do nothing unless there is serial input. Wait 1/10 of a second before checking again. OK. Why?

Are you sure that it is necessary to tell the clock what day of the week the date is?

marco_c: When you say "nothing changed" do you mean that it remains as the value that you set (ie, clock is not changing) or that setting the clkock did not work?

Is the clock running (there is a command register bit to set the clock to run, and it is not set by default)?

I have in my library code repository (link below) a library for the DS1307 that I wrote some time ago. It has an example program that allows you to explore the registers, set and read the clock, through the serial monitor. Maybe use that initially to see what the different memory registers of the clock chip are set to.

Sorry if I was unclear; by unchanged I meant that setting the clock did not work.

Thanks for the code. The clock is running, as I can read the time just fine (and it is changing appropriately). I'm even more confused now. I can set the clock using the control code you provided, but my code still doesn't work. (there was an extra Wire.write(0); command at the end, but deleting that doesn't help. I've actually verified that the values being written are exactly the same. In the process, I found that adding Serial.print commands in the library prevented proper writing (? d/t interrupts or the serial buffer). Perhaps there's something about it being in the main code and not in a library that makes a difference?

PaulS: granted those changes will make the code more readable, but do they explain why I can't write to the chip?

PaulS: granted those changes will make the code more readable, but do they explain why I can't write to the chip?

The code changes won't. Perhaps the answer to the last question I asked would.

Modified version of code .

#include "Wire.h"
#define DS1307_ADDRESS 0x68
byte zero = 0x00; //workaround for issue #527

void setup(){
  Wire.begin();
  Serial.begin(9600);
  setDateTime(); //MUST CONFIGURE IN FUNCTION
}

void loop(){
  printDate();
  delay(1000);
}

void setDateTime(){

  byte second =      45; //0-59
  byte minute =49; //0-59
  byte hour = 10; //0-23
  byte weekDay =2; //1-7
  byte monthDay =23; //1-31
  byte month = 1; //1-12
  byte year  =       14; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero); //stop Oscillator

  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(weekDay));
  Wire.write(decToBcd(monthDay));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));

  Wire.write(zero); //start

  Wire.endTransmission();

}

byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}

void printDate(){

  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

   int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

 /*  int second = 11;
  int minute =18;
  int hour = 18;
  int weekDay = 1;
  int monthDay = 2;
  int month = 11;
  int year = 12;
*/
  //print the date EG   3/1/11 23:59:59
  Serial.print(monthDay);
  Serial.print("/");
  
  
  Serial.print(month);
  Serial.print("/");
  
  Serial.print(year);
  Serial.print(" ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);
  
 // Serial.print("Week Day Of week");
//  Serial.println(weekDay);
  

}

There's a good spec sheet at:

http://www.pridopia.co.uk/pi-doc/ds1307.pdf

and page 9 details the timekeeper registers. In your code:

  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.write(0);
  Wire.endTransmission();

The DS1307 maintains a pointer to each of the registers that hold the time-date data. This pointer auto-increments each time you do a read or a write and "wraps around" if you try to increment past the last register. The statement:

  Wire.write(0);

does not stop anything. It simply resets the register pointer so that it points to the first data register within the DS1307. You can pass in a value and set the pointer to read or write that register. For example, if you passed in 3, you would be able to read or write the Day-of-the-Week value.

If you have the first Wire.write() call in the code each time you write data to the chip, the last Wire-write() really isn't needed because the first calls resets the pointer to the first register anyway. The PDF file does a good job of explaining how the pointer and registers work.

Finally, unless you have some reason to do otherwise, you can use your Serial link to initialize the DS1307 registers to the host PC's current data and time. That call should be done in setup() and not called again. Most RTC modules come with a coin battery that holds the data when power is removed.

Thanks for the suggestions.

PaulS: Sorry - missed the last line. I don't need the day of the week and you technically don't have to, but since the values are written to the DS1307 sequentially, and the day-of-week byte is in the middle, it's easiest to just read or write a value, even if you don't need it.

Amps-N: Thanks for the code. I tried using it and it fails to change the clock as well. (The write routines are basically the same as in my original code, so it's not unexpected that they give the same result.)

econjack: Agreed the last Wire.write(0) statement doesn't do anything. Rather than wrap around, I think the pointer actually proceeds to the memory registers, but either way I tried removing the last Wire.write(0) statement and it made no difference.

Regarding setting through the serial port, that works for the initial setting, but it is eventually going to part of a stand-alone controller. As the DS1307 tends to drift a bit with time, I wanted the ability to actually set it from the controller without hooking it up to a computer. (besides that, not being able to set the clock is just bugging me!)

Sleepydoc: Amps-N: Thanks for the code. I tried using it and it fails to change the clock as well. (The write routines are basically the same as in my original code, so it's not unexpected that they give the same result.)

I could not able to understand it fails to change the clock as well. statement.can you put images so i can understand what ur doing with my code. I think r u doing this. Initially you updated my code to board open the serial port checked time is working.Later you open serial port it started from starting where you initially set . IS correct or something else???

A ran the code which should set the clock to 23.1.2014 10:49:45, day of week 2 (I pasted the setDateTime routine below for reference.)

void setDateTime(){
  byte second =      45; //0-59
  byte minute =49; //0-59
  byte hour = 10; //0-23
  byte weekDay =2; //1-7
  byte monthDay =23; //1-31
  byte month = 1; //1-12
  byte year  =       14; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero); //stop Oscillator
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(weekDay));
  Wire.write(decToBcd(monthDay));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.write(zero); //start
  Wire.endTransmission();
}

Here is the output - the clock remains set at 3.2.10, 10:12:xx

3/2/10 10:12:18 3/2/10 10:12:20 3/2/10 10:12:21 3/2/10 10:12:22 3/2/10 10:12:23 3/2/10 10:12:24 3/2/10 10:12:25

So I’m getting more confused. I wrote the sketch below, which is pretty much a bare minimum to read/write to the RTC. It reads just fine, but fails to write the time.

#include "Wire.h"
#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin();
  Serial.begin(9600);
  Serial.println("---------------");
  }

void loop(){
  Serial.print("reading: ");
  readTime();
  Serial.println("setting...");
  setTime();
  Serial.print("reading: ");
  readTime();
  Serial.println();
  while(1);
}

void readTime(){
  Wire.beginTransmission(DS1307_ADDRESS); //open communication with RTC
  Wire.write(0x00);                       // set memory pointer to 0
  Wire.endTransmission();
  
  Wire.requestFrom(DS1307_ADDRESS, 7);
  
  byte second = bcdToDec(Wire.read());
  byte minute = bcdToDec(Wire.read());
  byte hour = bcdToDec(Wire.read());
  byte weekDay = bcdToDec(Wire.read());
  byte date = bcdToDec(Wire.read());
  byte month = bcdToDec(Wire.read());
  byte year = bcdToDec(Wire.read());
  
  Serial.print((2000+year));
  Serial.print("-");
  Serial.print(month);
  Serial.print("/");
  Serial.print(date);
  Serial.print("  ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.print(second);
  Serial.print("  day of week ");
  Serial.println(weekDay);
}

void setTime(){
  byte second = decToBcd(22);
  byte minute = decToBcd(9);
  byte hour = decToBcd(8);
  byte weekDay = decToBcd(7);
  byte date = decToBcd(6);
  byte month = decToBcd(5);
  byte year = decToBcd(4);
  
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(0x00);
  Wire.write(second);
  Wire.write(minute);
  Wire.write(hour);
  Wire.write(weekDay);
  Wire.write(date);
  Wire.write(month);
  Wire.write(year);
  Wire.endTransmission();
  
}


byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}

I downloaded Marco_c’s code (see the first reply to my original post, above) It will set the time on the clock. Opening up the library he uses (MD_DS1307.cpp), my code appears to be identical to the writeDevice routine in the library. So why will it work in a library, but not in my code??? Is there any reason code would work in a library but not in the main file?

Write device extracted from library:

uint8_t writeDevice(uint8_t addr, uint8_t* buf, uint8_t len)
{
  Wire.beginTransmission(DS1307_ID);
  Wire.write(addr);				// set register address                 
  for (uint8_t i=0; i<len; i++) // Send x data from given address upwards...
  {
    Wire.write(buf[i]);         // ... and send it from buffer
  }
  Wire.endTransmission();
  return(len);
}

… here’s the entire .cpp library for reference:

/*
  MD_DS1307 - Library for using a DS1307 Real Time Clock.
  
  Created by Marco Colli May 2012
  
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
 */
#include "MD_DS1307.h"
#include <Wire.h>

class DS1307	RTC;	// one instance created when library is included

// Useful definitions
#define	DS1307_ID	0x68	// I2C/TWI device address, coded into the device

#define	RAM_BASE_READ	0	// smallest read address
#define	RAM_BASE_WRITE	8	// smallest write address

// Addresses for the parts of the date/time in RAM
#define	ADDR_SEC	0x0
#define	ADDR_MIN	0x1
#define	ADDR_HR		0x2
#define	ADDR_DAY	0x3
#define	ADDR_DATE	0x4
#define	ADDR_MON	0x5
#define	ADDR_YR		0x6

// Address for the special control bytes
#define	ADDR_CTL_CH		0x0
#define	ADDR_CTL_12H	0x2
#define	ADDR_CTL_OUT	0x7
#define	ADDR_CTL_SQWE	0x7
#define	ADDR_CTL_RS		0x7

// Bit masks for the control/testable bits
#define	CTL_CH		0x80
#define	CTL_12H		0x40
#define	CTL_PM		0x20
#define	CTL_OUT		0x80
#define	CTL_SQWE	0x10
#define	CTL_RS		0x03

// Define a global buffer we can use in thses functions
#define	MAX_BUF		8			// time message is the biggest message we need to handle (7 bytes)
uint8_t	bufRTC[MAX_BUF];

void dumpBuffer()
{
	for (int i=0; i<MAX_BUF; i++)
	{
		Serial.print(bufRTC[i], HEX);
		Serial.print(", ");
	}
	Serial.println();
}

// BCD to binary number packing/unpacking functions
static uint8_t BCD2bin(uint8_t v) { return v - 6 * (v >> 4); }
static uint8_t bin2BCD (uint8_t v) { return v + 6 * (v / 10); }

// Interface functions for the RTC device
uint8_t readDevice(uint8_t addr, uint8_t* buf, uint8_t len)
{
  Wire.beginTransmission(DS1307_ID);
  Wire.write(addr);				// set register address                  
  if (Wire.endTransmission() != 0)
    return(0);
	
  Wire.requestFrom(DS1307_ID, (int)len);
  while (!Wire.available()) ;	// wait
  for (uint8_t i=0; i<len; i++) // Read x data from given address upwards...
  {
    buf[i] = Wire.read();       // ... and store it in the buffer
  }
  
  return(len);
}

uint8_t writeDevice(uint8_t addr, uint8_t* buf, uint8_t len)
{
  Wire.beginTransmission(DS1307_ID);
  Wire.write(addr);				// set register address                 
  for (uint8_t i=0; i<len; i++) // Send x data from given address upwards...
  {
    Wire.write(buf[i]);         // ... and send it from buffer
  }
  Wire.endTransmission();
  return(len);
}

// Class functions
DS1307::DS1307()
{
	yyyy = mm = dd = 0;
	h = m = s = 0;
	dow = 0;
	Wire.begin();
}
 
void DS1307::ReadTime(void)
// Read the current time from the RTC and unpack it into the object variables
{
	readDevice(RAM_BASE_READ, bufRTC, 7);		// get the data
	
	// unpack it
	s = BCD2bin(bufRTC[ADDR_SEC] & ~CTL_CH);	// mask off the 'CH' bit
	m = BCD2bin(bufRTC[ADDR_MIN]);
	if (bufRTC[ADDR_HR] & CTL_12H) 			// 12 hour clock
	{
		h = BCD2bin(bufRTC[ADDR_HR] & 0x1f);
		pm = (bufRTC[ADDR_HR] & CTL_PM);
	} else {
		h = BCD2bin(bufRTC[ADDR_HR] & 0x3f);
		pm = 0;
	}
	dow = BCD2bin(bufRTC[ADDR_DAY]);
	dd = BCD2bin(bufRTC[ADDR_DATE]);
	mm = BCD2bin(bufRTC[ADDR_MON]);
	yyyy = BCD2bin(bufRTC[ADDR_YR]) + 2000;
}

void DS1307::WriteTime(void)
// Pack up and write the time stored in the object variables to the RTC
// Note: Setting the time will also start the clock of it is halted
{
	uint8_t	mode12;
	
	// check what time mode is current
	readDevice(ADDR_HR, &mode12, 1);		
	mode12 &= CTL_12H;
	
	// pack it up in the current space
	bufRTC[ADDR_SEC] = bin2BCD(s);
	bufRTC[ADDR_MIN] = bin2BCD(m);
	if (mode12)				// 12 hour clock
	{
		uint8_t	hour = bin2BCD(h);
		
		pm = (hour > 12);
		if (pm) hour -= 12;
		bufRTC[ADDR_HR] = bin2BCD(hour);
		if (pm) bufRTC[ADDR_HR] |= CTL_PM;
		bufRTC[ADDR_HR] |= CTL_12H;
	}
	else
		bufRTC[ADDR_HR] = bin2BCD(h);
	bufRTC[ADDR_DAY] = bin2BCD(dow);
	bufRTC[ADDR_DATE] = bin2BCD(dd);
	bufRTC[ADDR_MON] = bin2BCD(mm);
	bufRTC[ADDR_YR] = bin2BCD(yyyy - 2000);
	
	writeDevice(RAM_BASE_READ, bufRTC, 7);
}

uint8_t DS1307::ReadRAM(uint8_t addr, uint8_t* buf, uint8_t len)
// Read len bytes from the RTC, starting at address addr, and put them in buf
// Reading includes all bytes at addresses RAM_BASE_READ to DS1307_RAM_MAX
{
	if ((NULL == buf) || (addr < RAM_BASE_READ) || (len == 0) ||(addr + len - 1 > DS1307_RAM_MAX))
		return(0);
		
	return(readDevice(addr, buf, len));		// read all the data once
}

uint8_t DS1307::WriteRAM(uint8_t addr, uint8_t* buf, uint8_t len)
// Write len bytes from buffer buf to the RTC, starting at address addr
// Writing addresses excludes the RTC registers, so valid addresses are 
// RAM_BASE_WRITE to DS1307_RAM_MAX
{
	if ((NULL == buf) || (addr < RAM_BASE_WRITE) || (len == 0) || (addr + len - 1 >= DS1307_RAM_MAX))
		return(0);

	return(writeDevice(addr, buf, len));	// write all the data at once
}

void DS1307::Control(uint8_t item, uint8_t value)
// Perform a control action on item, using the value
{
	uint8_t	mask;		// mask used to clear the bits being set (ANDed)
	uint8_t cmd;		// value used to set new nit value (ORed)
	uint8_t addr;		// address of the byte to change
	
	switch (item)
	{
		case DS1307_CLOCK_HALT:
			addr = ADDR_CTL_CH;
			mask = ~CTL_CH;
			switch (value)
			{
				case DS1307_ON:  cmd = CTL_CH; break;
				case DS1307_OFF: cmd = 0; break;
				default: return; // wrong - just go back
			}
		break;
		
		case DS1307_SQW_RUN:
			addr = ADDR_CTL_SQWE;
			mask = ~CTL_SQWE;
			switch (value)
			{
				case DS1307_ON:	 cmd = CTL_SQWE; break;
				case DS1307_OFF: cmd = 0; break;
				default: return; // wrong - just go back
			}
		break;
		
		case DS1307_SQW_TYPE_ON:
			addr = ADDR_CTL_RS;
			mask = ~CTL_RS;
			switch (value)
			{
				case DS1307_SQW_1HZ:  cmd = 0x00;	break;
				case DS1307_SQW_4KHZ: cmd = 0x01;	break;
				case DS1307_SQW_8KHZ: cmd = 0x02;	break;
				case DS1307_SQW_32KHZ:cmd = 0x03;	break;
				default: return; // wrong - just go back
			}
		break;
		
		case DS1307_SQW_TYPE_OFF:
			addr = ADDR_CTL_OUT;
			mask = ~CTL_OUT;
			switch (value)
			{
				case DS1307_SQW_LOW:  cmd = 0;	break;
				case DS1307_SQW_HIGH: cmd = CTL_OUT;	break;
				default: return; // wrong - just go back
			}
		break;
		
		case DS1307_12H:
			addr = ADDR_CTL_12H;
			mask = ~CTL_12H;
			switch (value)
			{
				case DS1307_ON:	 cmd = CTL_12H; break;
				case DS1307_OFF: cmd = 0; break;
				default: return; // wrong - just go back
			}
		break;

		default:
			return;	// parameters were wrong - make no fuss and just go back
	}
	
	// now read the address from the RTC
	readDevice(addr, bufRTC, 1);

	// do any special processing here
	if (item == DS1307_12H)		// changing 12/24H clock - special handling of hours conversion
		switch(value)
		{
			case DS1307_ON:	// change to 12H ...
				if (!(bufRTC[0] & CTL_12H))	// ... and not in 12H mode
				{
					uint8_t	hour = BCD2bin(bufRTC[0] & 0x3f);
					
					if (hour > 12)			// adjust the time, otherwise it looks the same as it does
					{
						bufRTC[0] = bin2BCD(hour - 12);
						bufRTC[0] |= CTL_PM;
					}
				}
			break;
		
			case DS1307_OFF:	// change to 24H ...
				if ((bufRTC[0] & CTL_12H) && (bufRTC[0] & CTL_PM)) 	// ... not in 24H mode and it is PM
				{
					uint8_t	hour = BCD2bin(bufRTC[0] & 0x1f);
					bufRTC[0] = bin2BCD(hour + 12);
				}
			break;
		}
	
	// Mask off the new status, set the value and then write it back
	bufRTC[0] &= mask;
	bufRTC[0] |= cmd;
	writeDevice(addr, bufRTC, 1);
	
	return;
}

uint8_t DS1307::Status(uint8_t item)
// Obtain the status of the controllable item and return it.
// Return DS1307_ERROR otherwise.
{
	readDevice(RAM_BASE_READ, bufRTC, 8);		// read all the data once
	
	switch (item)
	{
		case DS1307_CLOCK_HALT:		return(bufRTC[ADDR_CTL_CH] & CTL_CH ? DS1307_ON : DS1307_OFF);
		case DS1307_SQW_RUN:		return(bufRTC[ADDR_CTL_SQWE] & CTL_SQWE ? DS1307_ON : DS1307_OFF);
		case DS1307_SQW_TYPE_ON:
			switch (bufRTC[ADDR_CTL_RS] & CTL_RS)
			{
				case 0: return(DS1307_SQW_1HZ);
				case 1: return(DS1307_SQW_4KHZ);
				case 2: return(DS1307_SQW_8KHZ);
				case 3: return(DS1307_SQW_32KHZ);
			}
			break;	// in case of error
		case DS1307_SQW_TYPE_OFF:	return(bufRTC[ADDR_CTL_OUT] & CTL_OUT ? DS1307_SQW_HIGH : DS1307_SQW_LOW);
		case DS1307_12H:			return(bufRTC[ADDR_CTL_12H] & CTL_12H ? DS1307_ON : DS1307_OFF);
	}
	
	return(DS1307_ERROR);	// parameters were wrong - make no fuss and just go back
}

Sleepydoc: A ran the code which should set the clock to 23.1.2014 10:49:45, day of week 2 (I pasted the setDateTime routine below for reference.)

void setDateTime(){
  byte second =      45; //0-59
  byte minute =49; //0-59
  byte hour = 10; //0-23
  byte weekDay =2; //1-7
  byte monthDay =23; //1-31
  byte month = 1; //1-12
  byte year  =       14; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);   Wire.write(zero); //stop Oscillator   Wire.write(decToBcd(second));   Wire.write(decToBcd(minute));   Wire.write(decToBcd(hour));   Wire.write(decToBcd(weekDay));   Wire.write(decToBcd(monthDay));   Wire.write(decToBcd(month));   Wire.write(decToBcd(year));   Wire.write(zero); //start   Wire.endTransmission(); }




Here is the output - the clock remains set at 3.2.10, 10:12:xx


> 3/2/10 10:12:18
> 3/2/10 10:12:20
> 3/2/10 10:12:21
> 3/2/10 10:12:22
> 3/2/10 10:12:23
> 3/2/10 10:12:24
> 3/2/10 10:12:25

What is problem Here . You are getting Proper Date and time what you set it. It just continue . ya it should be check time format hour: min : sec after 60second you can find changing in minute.

Also keep in mind that once you set date/time in setup .has to be commented out upload again . Because if you don't comment every time it start with date/time you being seted.

Sleepydoc:
So I’m getting more confused. I wrote the sketch below, which is pretty much a bare minimum to read/write to the RTC. It reads just fine, but fails to write the time.

#include "Wire.h"

#define DS1307_ADDRESS 0x68

void setup(){
 Wire.begin();
 Serial.begin(9600);
 Serial.println("---------------");
 }

void loop(){
 Serial.print("reading: ");
 readTime();
 Serial.println(“setting…”);
 setTime();
 Serial.print("reading: ");
 readTime();
 Serial.println();
 while(1);
}

void readTime(){
 Wire.beginTransmission(DS1307_ADDRESS); //open communication with RTC
 Wire.write(0x00);                       // set memory pointer to 0
 Wire.endTransmission();
 
 Wire.requestFrom(DS1307_ADDRESS, 7);
 
 byte second = bcdToDec(Wire.read());
 byte minute = bcdToDec(Wire.read());
 byte hour = bcdToDec(Wire.read());
 byte weekDay = bcdToDec(Wire.read());
 byte date = bcdToDec(Wire.read());
 byte month = bcdToDec(Wire.read());
 byte year = bcdToDec(Wire.read());
 
 Serial.print((2000+year));
 Serial.print("-");
 Serial.print(month);
 Serial.print("/");
 Serial.print(date);
 Serial.print("  “);
 Serial.print(hour);
 Serial.print(”:");
 Serial.print(minute);
 Serial.print(":");
 Serial.print(second);
 Serial.print("  day of week ");
 Serial.println(weekDay);
}

void setTime(){
 byte second = decToBcd(22);
 byte minute = decToBcd(9);
 byte hour = decToBcd(8);
 byte weekDay = decToBcd(7);
 byte date = decToBcd(6);
 byte month = decToBcd(5);
 byte year = decToBcd(4);
 
 Wire.beginTransmission(DS1307_ADDRESS);
 Wire.write(0x00);
 Wire.write(second);
 Wire.write(minute);
 Wire.write(hour);
 Wire.write(weekDay);
 Wire.write(date);
 Wire.write(month);
 Wire.write(year);
 Wire.endTransmission();
 
}

byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
 return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
 return ( (val/16*10) + (val%16) );
}




I downloaded Marco_c's code (see the first reply to my original post, above) It *will* set the time on the clock. Opening up the library he uses (MD_DS1307.cpp), my code appears to be identical to the writeDevice routine in the library. So why will it work in a library, but not in my code????? Is there any reason code would work in a library but not in the main file?

Write device extracted from library:


uint8_t writeDevice(uint8_t addr, uint8_t* buf, uint8_t len)
{
 Wire.beginTransmission(DS1307_ID);
 Wire.write(addr); // set register address                
 for (uint8_t i=0; i<len; i++) // Send x data from given address upwards…
 {
   Wire.write(buf[i]);         // … and send it from buffer
 }
 Wire.endTransmission();
 return(len);
}

Here in loop ur calling readtime,then set time and then readtime again.
So it initially read default time or previously settime() . then it set time to new time . again read time ,So this will keep on setting time which being called again and again

AMPS-N:
What is problem Here . You are getting Proper Date and time what you set it. It just continue . ya it should be check time format hour: min : sec after 60second you can find changing in minute.

Also keep in mind that once you set date/time in setup .has to be commented out upload again . Because if you don’t comment every time it start with date/time you being seted.

No - the code should set the RTC to Jan 23, 2014, 10:49:45. Although the clock is running, the time/date remained at Feb 3, 2010, 10:12:xx, (the same time it had before running the sketch,) so the routine to set the clock did not work. I recognize that the code should set the clock each time it is run (or that the Arduino is reset,) but it’s not setting it at all.

AMPS-N:
Here in loop ur calling readtime,then set time and then readtime again.
So it initially read default time or previously settime() . then it set time to new time . again read time ,So this will keep on setting time which being called again and again

Yes - that was the intent. I called readTime to check the time, then tried to write a new time, and then check to see if the time actually changed after I attempted to write it.

Put Setdate function in loop . SO that it keep remain in same date

So I've figured out the problem.

Turns out it wasn't a programming issue, rather a hardware issue. The ground pin on the header had a bad solder joint, so the arduino ground was not connected to the chip ground. Given that, it's actually surprising that the board worked as well as it did. I reheated the joint and now the board works perfectly (and I can set the clock!)

Thank you to everyone who helped.