DS1307 RTC with buttons, interface with i2C with a 128x23 monochrome OLED

I am trying to create a simple clock using a DS1307 breakout board and I am finding it difficult to use switches with the DS1307. I am using 3 switches and an Arduino Uno
I want one switch to be able to increment a time variable (minutes or hours or date) by holding it down, one to move between these variables and the other switch to confirm.
As of now, I only set one switch to increment the hour, and one switch to increment the minutes because i do not understand how t cycle between the variables.

Using Time and DS1307 libraries

DS1307_withbutton.ino (3.7 KB)

  // *** had to adjust the adjustTime function in the Time library.

Why?

So that when i press the switch, it increments and sets the time

kcoelho:
So that when i press the switch, it increments and sets the time

Does the unmodified library function not alter the time?

void adjustTime(long adjustment) {
  sysTime += adjustment;
}

Yours is:

void adjustTime(long adjustment){
setTime(sysTime + adjustment);
}

setTime is a function in the Time library. It updates the time. it's easier to use I feel. My issue is in using one switch to cycle between the different time variables. Because each one will be a different t_value, I am unsure how to do this

kcoelho:
setTime is a function in the Time library. It updates the time. it’s easier to use I feel. My issue is in using one switch to cycle between the different time variables. Because each one will be a different t_value, I am unsure how to do this

A variable can remember the mode. Switches set the variable. Then you test the variable to see which code blocks to use for the mode in question.

I'll try that out thanks

What exactly do you mean by a variable can remember the mode? using switch? the input to most of the functions have to be t_values

aarg:
A variable can remember the mode. Switches set the variable. Then you test the variable to see which code blocks to use for the mode in question.

The more I try to code, I don't understand what exactly this variable is and should be?

kcoelho:
The more I try to code, I don't understand what exactly this variable is and should be?

I currently use the microchip RTC, but just had a look at the DS1307 RTC library, and the one I looked at has a "setDate(...)" function. If the library you're using has that function and it looks kinda like setDate(hr, min, sec), then here's a slightly different strategy that may work and help you get your head around what to do with the variables as they relate to the buttons.

The variable for the mode could be anything, for example an int called "mode." When the button you use to set the "variable used to move between the variables" is pressed, increment the variable "mode." Then when the "time" button is pressed, set either the sec, min, hr, variable based on what the mode variable is set to.

For example, you have some variables called, "timeSec", "timeMin", "timeHr." Then when the "time" button is used, immediately call rtc.getTime, and set those variables based on the sec, min, etc received - in other words, the current time values. If "mode" variable is 0 for example, then incremeint the "timeSec" variable (leaving the timeMin and timeHr vars unchanged), and call rtc.setTime(timeHr, timeMin, timeSec);. The timeHr, and timeMin, would remain unchanged, but the timeSec would have the new value, and that value would be updated in that call. If "mode" variable is 1 for example, then increment the "timeMin" variable (leaving the timeSec and timeHr vars unchanged), and call rtc.setTime(timeHr, timeMin, timeSec);. The timeHr, and timeSec, would remain unchanged, but the timeMin would have the new value, and that value would be updated in that call.

Obviously, that's "simplified." To prevent a bazillion calls to getTime() and setTime, have a variable such as "timeInc" which you increment based on the pressing of the "time" button, then when done, do the getTime()/setTime() with that "timeInc" value added to the correct variable (timeSec, timeMin, etc.). This could all be put into a switch statement, or you could use an if/elseif type of thing, whichever you're comfortable with.

In addition to what I already wrote, if you get that working and want to "take it to the next level," you could just access a particular register, such as the "seconds" register if you use the adafruit RTC library (not the one I referenced in the previous response which has the set/getDate() funcs) that I just looked at. It has a function defined as "static void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val)"

What that gets you, is a better resolution of setting the time values. For example, between the getting of the time and setting of the time (using the seconds for example) the seconds could have ticked up enough to change the minutes, yet you setting the seconds the other way, would set the minutes to the value retrieved in the prior getTime function. Whereas writing to just the seconds register, it would only update the seconds.

For example to change the seconds, you'd call:
int adr = 0xd0; //0xd0 for write and 0xd1 for read
write_i2c_register(0xD0, mode, timeSec); //mode=0 for seconds

Since the chip uses BCD, it's easier than if it didn't, since for example the 12th hour is actually 0x12 instead of 0xc. :slight_smile:

To take it yet another step, you could eliminate the RTC and write to the chip directly using just the wire library, or even just writing to the port, since both i2c and spi are such simple interfaces to do that with.

But before any of these, I'd recommend doing what I explained in the other response first, and then decide if you want to pursue it in either of these ways.

Do that and post the result, and we'll show you how to improve the mode variable usage with an "enum".

justjohn:
I currently use the microchip RTC, but just had a look at the DS1307 RTC library, and the one I looked at has a "setDate(...)" function. If the library you're using has that function and it looks kinda like setDate(hr, min, sec), then here's a slightly different strategy that may work and help you get your head around what to do with the variables as they relate to the buttons.

The variable for the mode could be anything, for example an int called "mode." When the button you use to set the "variable used to move between the variables" is pressed, increment the variable "mode." Then when the "time" button is pressed, set either the sec, min, hr, variable based on what the mode variable is set to.

For example, you have some variables called, "timeSec", "timeMin", "timeHr." Then when the "time" button is used, immediately call rtc.getTime, and set those variables based on the sec, min, etc received - in other words, the current time values. If "mode" variable is 0 for example, then incremeint the "timeSec" variable (leaving the timeMin and timeHr vars unchanged), and call rtc.setTime(timeHr, timeMin, timeSec);. The timeHr, and timeMin, would remain unchanged, but the timeSec would have the new value, and that value would be updated in that call. If "mode" variable is 1 for example, then increment the "timeMin" variable (leaving the timeSec and timeHr vars unchanged), and call rtc.setTime(timeHr, timeMin, timeSec);. The timeHr, and timeSec, would remain unchanged, but the timeMin would have the new value, and that value would be updated in that call.

Obviously, that's "simplified." To prevent a bazillion calls to getTime() and setTime, have a variable such as "timeInc" which you increment based on the pressing of the "time" button, then when done, do the getTime()/setTime() with that "timeInc" value added to the correct variable (timeSec, timeMin, etc.). This could all be put into a switch statement, or you could use an if/elseif type of thing, whichever you're comfortable with.

Where did you find this library.
I have been using this one:
https://www.pjrc.com/teensy/td_libs_DS1307RTC.html
It is based on the time library

A great "go-to" for a whole lot of stuff - Adafruit.com

Here's the link for the site with the library link

So I implemented that but all the time values keep getting messed up.
I think I’ll stick to the DS1307 library if I plan to switch to an MCP7940 later.

DS1307_withbutton.ino (4.67 KB)

4.67Kb should be short enough to post in code tags.