Adjusting the date on a DS1307 using external buttons?

Hi all,

Ive undertaken a project to make a clock using the DS1307 RTC chip. I've used these chips before while trying to learn Arduino coding and been generally successful but i'm stumped on part of the code i'm trying to write now. I'd like to use external push buttons to be able to set and adjust the time as a stand alone unit without having to plug into my computer.

I've found some code at this link

http://www.bristolwatch.com/arduino/arduino_ds1307.htm

which is doing pretty much what i want however it only adjusts the hours and minutes. I'd like to be able to adjust the date as well. Ive tried copying the "hours" portion and changing it to month and using a 4th switch (SW03) but although it says that i am adjusting the month in the serial monitor, it doesnt actually change the month on the chip.

I'm also slowly getting my head around binary, dec, bcd and hex etc but cant understand part of the "change time" script at the end. It says

if ((minutes & 0x0f) > 9) minutes = minutes + 6;

Whats happening here?

Here is the code that i have adjusted. Could someone please take a look and tell me why the month isn't changing even though the serial monitor says it is?

#include <Wire.h> // specify use of Wire.h library.

byte blinkPin = 13;
byte SW0 = 4;
byte SW1 = 5;
byte SW2 = 6;
byte SW3 = 7;

void setup()

{
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);
  pinMode(blinkPin, OUTPUT);
  digitalWrite(blinkPin, 0);


  pinMode(SW0, INPUT);  // Set Time (for this use a slide switch)
  pinMode(SW1, INPUT);  // Set Date (for this use a slide switch)
  pinMode(SW2, INPUT);  // N.O. push button switch
  pinMode(SW3, INPUT);  // N.O. push button switch

  digitalWrite(SW0, HIGH); // pull-ups on
  digitalWrite(SW1, HIGH);
  digitalWrite(SW2, HIGH);
  digitalWrite(SW3, HIGH);
}

void loop()
{
  Wire.beginTransmission(0x68);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(0x68, 7);
  byte secs = Wire.receive();
  byte mins = Wire.receive();
  byte hrs = Wire.receive();
  byte day = Wire.receive();
  byte date = Wire.receive();
  byte month = Wire.receive();
  byte year = Wire.receive();

  // hours, minutes, seconds

  Serial.print("The time is "); 
  if (hrs < 10) Serial.print("0");
  Serial.print(hrs,HEX);    
  Serial.print(":");
  if (mins < 10) Serial.print("0");
  Serial.print(mins, HEX);
  Serial.print(":");
  if (secs < 10) Serial.print("0");
  Serial.println(secs, HEX);

  // use MM-DD-YYYY

  Serial.print("The date is "); 
  if (month < 10) Serial.print("0");
  Serial.print(month,HEX);    
  Serial.print("-");
  if (date < 10) Serial.print("0");
  Serial.print(date, HEX);
  Serial.print("-");
  Serial.print("20");
  if (year < 10) Serial.print("0");
  Serial.println(year, HEX);
  Serial.println();


  if (!(digitalRead(SW0))) set_time(); // hold the switch to set time
  delay(1000);    //wait a second before next output
  toggle(blinkPin);
  
  
} 


// toggle the state on a pin
void toggle(int pinNum) 
{  
  int pinState = digitalRead(pinNum);
  pinState = !pinState;
  digitalWrite(pinNum, pinState); 
}




void set_time()   {
  byte minutes = 0;
  byte hours = 0;
  byte month = 0;

  
  {
    while (!digitalRead(SW0))  // set time switch must be released to exit
    {
    while (!digitalRead(SW1)) // set minutes
    { 
      minutes++;          
      if ((minutes & 0x0f) > 9) minutes = minutes + 6;
      if (minutes > 0x59) minutes = 0;
      Serial.print("Minutes = ");
      if (minutes <= 9) Serial.print("0");
      Serial.println(minutes, HEX);

      delay(200);
    }

    while (!digitalRead(SW2)) // set hours
    { 
      hours++;          
      if ((hours & 0x0f) > 9) hours =  hours + 6;
      if (hours > 0x23) hours = 0;
      Serial.print("Hours = ");
      if (hours <= 9) Serial.print("0");
      Serial.println(hours, HEX);
      delay(200);
    }
    
    while (!digitalRead(SW3)) // set date
    { 
      month++;          
      if ((month & 0x0f) > 9) month =  month + 6;
      if (month > 0x12) month = 0;
      Serial.print("month = ");
      if (month <= 9) Serial.print("0");
      Serial.println(month, HEX);
      delay(200);
    }
    }
}

    Wire.beginTransmission(0x68); // activate DS1307
    Wire.send(0); // where to begin
    Wire.send(0x00);          //seconds
    Wire.send(minutes);          //minutes
    Wire.send(0x80 | hours);    //hours (24hr time)
    Wire.send(0x06);  // Day 01-07
    Wire.send(0x01);  // Date 0-31
    Wire.send(0x05);  // month 0-12
    Wire.send(0x09);  // Year 00-99
    Wire.send(0x10); // Control 0x10 produces a 1 HZ square wave on pin 7. 
    Wire.endTransmission();
      
}

Also, why is it that the Wire.send code at the end uses (0x09) for the year ( i believe this is somehow the address but looking at the datasheet, can't figure out how) but (minutes) for the minutes?

Thanks so much everyone. Any help is always appreciated!

edit: changed 31 to 12 in the change month part

Could someone please take a look and tell me why the month isn't changing even though the serial monitor says it is?

Without seeing your serial output? No, not really.

Also, why is it that the Wire.send code at the end uses (0x09) for the year ( i believe this is somehow the address but looking at the datasheet, can't figure out how) but (minutes) for the minutes?

It's your code. You tell us why you do it that way.

P.S. The comments answer your question.

Trying to interpret your code you're trying to get the day of month with the third button but you call it month (months are cycling at 12 and not 31). Additionally you have the code to enter the day of month but you don't transmit it to the 1307. The date transmitted is always 1st May 09. Also with your code you must have a serial connection to your PC to see what value you got. Why don't you use that connection for setting the date directly?

PaulS,

Thanks for your reply. Its not actually my code, i'm just trying to apply it to my project. I'm just having some troubles understanding it in the first place which is why im here asking questions.

Pylon,

Thanks for pointing that out. I had initially set it to 12 months but messed the code up so copied that portion back in from elsewhere. Forgot to change it to 12 before posting :blush:

Also...... THANKYOU! I didn't realise that the wire.send lines at the end were sending the actual figure and not some strange hex address. I thought those bits i.e wire.send(0x09) were sending hex address parts to the ds1307. Ive now changed it to wire.send(month) and it works much gooder!

Lastly, im still not sure what this line in the code is doing???

if ((minutes & 0x0f) > 9) minutes = minutes + 6;

Mainly the 0x0f part. The rest of the code im getting my head around ok.

I'll keep plodding away and be back at my next hurdle!

Thanks team

The chip uses BCD.

So the next number up from 9 is 10 but 10 in hex (ie. go from 0x09 to 0x10). That is a jump of 6 on top of the original add of 1 (ie add 6 to 0x0A to give 0x10).

Mainly the 0x0f part.

That means in this context "the low order digit". So for example if the minutes were 0x29, and we added 1, we get 0x2A. But we need 0x30, so we test the low order 4 bits (0x0A) and see if they exceed 9, which they do, so we add 6, giving 0x30 as the result.

Excellent! Thank you Nick!

That's exactly the kick in the pants I was looking for! Wow, BCD and HEX is easy! Erhum, well maybe not but i certainly see whats happening there now!

Cheers!

Hi,

Did you ever get a finished program where you adjust all parameters with buttons? If so, could I see it.

Thanks,

Sid