DS3234 Clock Project (Help w/ Buttons)

Makers,

As a retirement gift I’m trying to re-purpose a piece of old electronics equipment that said retiree used to work on. I want it to display the time where it used to display DC Amps and everything has been going well up to adding button(s) to it. I only want to add it for DST purposes. Once I gift this, it won’t be much good without the ability to adjust the clock.

I’m using the DS3234 RTC and am having a heck of a time coding for external button functionality to change the time. I’m starting small with one button to increment the minutes, later I’ll add one for the hours if I can successfully do the former.

The bulk of the code comes from the DS3234_RTC_Demo, and Serial 7-Segment Display examples. As far as button example code, I’ve found more info on the DS1307 RTC which uses different libraries and I’m running out of sources or things to try. My coding skill is Rookie.

#include <SPI.h>
#include <SparkFunDS3234RTC.h>
#include <SoftwareSerial.h>

#define DS13074_CS_PIN 10 // DeadOn RTC Chip-select pin

const int softwareTx = 8;
const int softwareRx = 7;
const int minButton = 9;     // pushbutton for incrementing minutes

int minPlus = 0;  //sets switches value to off as default

int varMin = 0; //temporary variables for time changing

SoftwareSerial s7s(softwareRx, softwareTx);

char tempString[10];  // Will be used with sprintf to create strings

void setup() 
{
  // Use the serial monitor to view time/date output
  Serial.begin(9600);
  s7s.begin(9600);
    // Clear the display before jumping into loop
  clearDisplay(); 

  rtc.begin(DS13074_CS_PIN);

  rtc.autoTime();

  pinMode(9, INPUT);
}
void loop() 
{
  static int8_t lastSecond = -1;
  
  // Call rtc.update() to update all rtc.seconds(), rtc.minutes(),
  // etc. return functions.
  rtc.update();

  if (rtc.second() != lastSecond) // If the second has changed
  {
    printTime(); // Print the new time

    lastSecond = rtc.second(); // Update lastSecond value  
  }
      setTimeManually();
}
void printTime()
{
  if (rtc.hour() < 10)
    s7s.print('0'); // Print leading '0' for hour
  s7s.print(String(rtc.hour())); // Print hour
  if (rtc.minute() < 10)
    s7s.print('0'); // Print leading '0' for minute
  s7s.print(String(rtc.minute())); // Print minute
    s7s.print(tempString);
  setDecimals(0b00010000);  // Sets colon on
  delay(1000);
   s7s.print(tempString);
  setDecimals(0b00000000);  // Sets colon off
  delay(1000);
}
void clearDisplay()
{
  s7s.write(0x76);  // Clear display command
}

void setDecimals(byte decimals)
{
  s7s.write(0x77);
  s7s.write(decimals);
}
void setTimeManually()
{
minPlus = digitalRead(minButton);
while(minPlus == HIGH)
{
  varMin = rtc.minute();
  varMin++;   //add 1 minute from the current time
      
  s7s.print(tempString);   //Flash colon quickly while incrementing minutes
  setDecimals(0b00010000);  // Sets colon on
  delay(250);
  s7s.print(tempString);
  setDecimals(0b00000000);  // Sets colon off
  delay(250);
}
}

The function “void setTimeManually()” which is at the bottom is where I’m struggling. It doesn’t increment the minutes. I do have code to flash the clock colon faster so I can tell when the button is pressed, but it is stuck in this function and will not come out even when I stop pressing the button.

Any help would be greatly appreciated!

minPlus = digitalRead(minButton);

while(minPlus == HIGH) { . . . }

If you don't update 'minPlus' within the 'while' loop you will stay there until you retire + some.

I don't know, it should break the while loop once the condition changes I thought. Eventually I got it return to the main loop with a subtle change from this...

void setTimeManually()
{
minPlus = digitalRead(minButton);
while(minPlus == HIGH)
{
.
.
}

to this...

void setTimeManually()
{
while (digitalRead(minButton) == HIGH) 
 {
.
.
}

and it breaks the loop now, but still feeling very far away to incrementing the minutes. I'm starting to think I might have better luck with the DS1307 RTC and it's libraries... :sob:

varMin = rtc.minute();
  varMin++;   //add 1 minute from the current time

This code is reading a value from the RTC, and incrementing it by one, but you never write the increased value back into the RTC.

From a quick look at the linked SparkFun library I think the command will be

rtc.setMinute(varMin);

That was exactly it! I'm one step closer. You are my hero cattledog. I guess you found that in the .cpp file? It increments ok now, I just need to come up with a way to continuously increment the longer you hold the button. I also have to take out the colon flashing. I had it flashing on and off for one second but it's a delay in the main program I have to wait for.

Any ideas how to do two things at once? Flash something while running a time program?

I guess you found that in the .cpp file?

Yes. Looking at the library source code is a good habit to learn. Library example programs rarely demonstrate all the functions.

I just need to slingshot the minutes so it continuously increments and updates the display with each increment. I also have to take out the colon flashing. I have it flashing on and off for one second each but it's a delay in the main program that I have to wait for.

Please post your current code, and explain in detail what it is doing that you don't want it to do, and what it is not doing that you want it to do.

Any ideas how to do two things at once? Flash something while running a time program?

Most likely you will be using a millis() timer and the "Blink without Delay" approach. Take a look at the "Blink without delay" example in the IDE, and also Robin2's example program "Demonstration code for several things at the same time" which is the first sticky post in the Project guidance section of the forum,

Awesome! Thanks again cattledog. I will just focus on incrementing time continuously from this point forward. This is the function where it should be but I have not come up with any theories yet. So as it stands, all this does is increment the minute one time while the button is HIGH. When the button is LOW then returned HIGH, it will increment the minute by one again... I would like it to increment continuously while the button is HIGH.

void setTimeManually()
{
while (digitalRead(minButton) == HIGH) 
  {
  static int8_t lastMinute = -1;

  addMinute = rtc.minute(); //assign variable
  addMinute++;              //increment it
  rtc.setMinute(addMinute); //write to RTC

    if (rtc.minute() != lastMinute) // If the minute has changed
    {
    printTime(); // Print the new time

    lastMinute = rtc.minute(); // Update lastMinute value     
    }
  }
}

"I would like it to increment continuously while the button is HIGH."

Write the code so the longer you hold the button, the faster it increments. When you get near the value you want, let go of the button for a short time then press it again. This will once again increment at the slower rate again allowing you more control as you approach the time needed.

.

The way I understand this library to work is that the values like rtc.minute() are filled when the rtc is actually read, and they will hold the values of the last time the device was read. The do not update without a read.

In the library .h it notes

// To read a single value at a time, use the get___ functions:
 uint8_t getSecond(void);
 uint8_t getMinute(void);
 uint8_t getHour(void);
 uint8_t getDay(void);
 uint8_t getDate(void);
 uint8_t getMonth(void);
 uint8_t getYear(void);

I think your function needs to look like this.

void setTimeManually()
{
while (digitalRead(minButton) == HIGH) 
  {
  static int8_t lastMinute = -1;

  addMinute = rtc.getMinute(); //assign variable
  addMinute++;              //increment it
  rtc.setMinute(addMinute); //write to RTC

    if (rtc.minute() != lastMinute) // If the minute has changed
    {
    printTime(); // Print the new time

    lastMinute = rtc.minute(); // Update lastMinute value     
    }
  }
}

Makers,

Just wanted to pass along my completed simple clock using the SparkFun DeadOn RTC Breakout - DS3234 and Serial 7-Segment Display. The program displays time in 24 hours (or 12 hour) to the S7SD. There are hour up/down, minutes up/down, and a display test button. Time adjust buttons only increment once per press. Any minute adjust will reset the seconds. The colon blinks every second without delay. Big thanks to cattledog and the rest of the forum. The below image is a prototype before I install it in its intended enclosure.

/* This is a simple clock using the SparkFun DeadOn RTC Breakout - DS3234 
 * and Serial 7-Segment Display. The program displays time in 24 hours to 
 * the S7SD. There are hour up/down, minutes up/down, and display test 
 * buttons. Time adjust buttons only increment once per press. Any minute 
 * adjust will reset the seconds.*/
 
#include <SparkFunDS3234RTC.h>
#include <SoftwareSerial.h>

#define DS13074_CS_PIN 10 // DeadOn RTC Chip-select pin

const int softwareTx = 8; //serial pin assignment for 7SD
const int softwareRx = 7;
const int hourUpButton = A0; //push button assignments
const int hourDownButton = A1;
const int minUpButton = A2;
const int minDownButton = A3;
const int testButton = A4;

int addHour = 0; //temporary variables for time changing
int subtractHour = 0;
int addMinute = 0;
int subtractMinute = 0;
int zeroSecond = 0;
int test = 0;

unsigned long previousTime = 0; 
const long interval = 1000;
boolean colon = false;

SoftwareSerial s7s(softwareRx, softwareTx);

void setup() 
{ 
  Serial.begin(9600); // Baud for serial monitor communication
  s7s.begin(9600); // Baud for 7 segment communication
  
  //rtc.set12Hour(); 
  /* Use rtc.set12Hour to set to 12-hour mode.You will need to 
   * adjust setTimeManually() function so hour adjustments reset 
   * for a 12 hour clock vs 24.*/
    
  clearDisplay(); // Clear the display before jumping into loop

  setBrightness(255); // max brightness

  rtc.begin(DS13074_CS_PIN);

  //rtc.autoTime(); // Pulls an initial time from IDE's time, comment out once time is set
}
void loop() {
  static int8_t lastSecond = -1;
  static int8_t lastMinute = -1;
  static int8_t lastHour = -1;
  
  // Call rtc.update() to update all rtc.seconds(), rtc.minutes(),
  // etc. return functions.
  rtc.update();

  if (rtc.second() != lastSecond) // If the second has changed
  {
    printTime(); // Print the new time

    lastSecond = rtc.second(); // Update lastSecond value
  }
  if (rtc.minute() != lastMinute) // If the minute has changed
  {
    printTime(); // Print the new time

    lastMinute = rtc.minute(); // Update lastMinute value
  }
  if (rtc.hour() != lastHour) // If the hour has changed
  {
    printTime(); // Print the new time

    lastHour = rtc.hour(); // Update lastHour value
  }
  
   colonBlink();
   setTimeManually();
   testDisplay();
}  // end loop

//////////FUNCTIONS///////////

void printTime()
{
  if (rtc.hour() < 10)
    s7s.print('0'); // Print leading '0' for hour
  s7s.print(String(rtc.hour())); // Print hour
  if (rtc.minute() < 10)
    s7s.print('0'); // Print leading '0' for minute
  s7s.print(String(rtc.minute())); // Print minute
        
/*Uncomment to see time on serial monitor
    Serial.print(String(rtc.hour()) + ":"); // Print hour
  if (rtc.minute() < 10)
    Serial.print('0'); // Print leading '0' for minute
  Serial.print(String(rtc.minute()) + ":"); // Print minute
  if (rtc.second() < 10)
    Serial.print('0'); // Print leading '0' for second
  Serial.print(String(rtc.second())); // Print second
  Serial.println();*/
}
void clearDisplay()
{
  s7s.write(0x76);  // Clear display command
}
void setDecimals(byte decimals)
{
  s7s.write(0x77);
  s7s.write(decimals);
}
void setTimeManually()
{
while (digitalRead(hourUpButton) == HIGH)
  {
  addHour = rtc.hour(); //assign local variable
  addHour++;            //increment it
  if(addHour > 23)      //if greater than 23 hours
      {
        addHour -= 24; //Reset hours to 00               
      }
  rtc.setHour(addHour); //write to RTC 
  }
while (digitalRead(hourDownButton) == HIGH)
  { 
  subtractHour = rtc.hour(); //assign local variable
  subtractHour--;           //decrement it
  if(subtractHour < 0)      //if less than 00 hours
      {
        subtractHour += 24; //Reset hours to 23              
      }               
  rtc.setHour(subtractHour); //write to RTC
  }  
while (digitalRead(minUpButton) == HIGH)
  {   
  addMinute = rtc.minute();     //assign local variable
  zeroSecond = rtc.getSecond(); //when rtc.getSecond is used it increments/decrements continuosly,
                                //don't know why but I use it to my advantage to zero the seconds with minute changes
  addMinute++;                  //increment it
  zeroSecond--;                 //zero the seconds out
  if(addMinute > 59)            //if minutes are greater than 59
      {
        addMinute -= 60;        //Reset minutes to 00              
      }   
  rtc.setMinute(addMinute);     //write to RTC
  rtc.setSecond(zeroSecond);    //write to RTC (for purposes of seeing on the serial monitor)
  }
while (digitalRead(minDownButton) == HIGH)
  {
  subtractMinute = rtc.minute();  //assign local variable
  zeroSecond = rtc.getSecond();   //when rtc.getSecond is used it increments/decrements continuosly,
                                  //don't know why but I use it to my advantage to zero the seconds with minute changes
  subtractMinute--;               //decrement it
  zeroSecond--;                   //zero the seconds out
  if(subtractMinute < 0)          //if minutes are less than 00
      {
        subtractMinute += 60;    //Reset minutes and increment hours               
      }                
  rtc.setMinute(subtractMinute); //write to RTC
  rtc.setSecond(zeroSecond);    //write to RTC (for purposes of seeing on the serial monitor) 
  }
}
void testDisplay()              //Test button to light all segments, colon, apostrophe's
{
while (digitalRead(testButton) == HIGH)
  {
s7s.print("8888");
setDecimals(0b111111);
  }
}
void setBrightness(byte value)  //Brightness of S7D
{
  s7s.write(0x7A);  // Set brightness command byte
  s7s.write(value);  // brightness data byte
} 
void colonBlink()
{
  unsigned long currentTime = millis();
  if( currentTime - previousTime >= interval)
  {
    previousTime = currentTime;

    if(colon == false)
    {
      colon = true;
      setDecimals(0b00010000);
    }
    else
    {
      colon = false; 
      setDecimals(0b00000000);
    }
   }
}