Manual set time, 12 hour, Buttons, Storage Space

Hi, Ive been trying to make this clock for a few weeks now and rather than creating a new topic at every road block I've been able to get it pretty close to how I want it by purely banging my head into my computer. However, at this point some problems are arriving.

Im using a DS3231
Arduino Uno
Cheap 128x64 .96" oled
It's my first project.

I apologize if there are too many questions for a single post and I'm happy do delete if I'm breaking any rules. In the off chance this post is acceptable here are my questions.

First, I thought I had it printing in a 12 hour format until midnight last night it displayed 0:00. Based on what I've provided is anyone able to help me correct this? I'm okay at copy/paste but the simplest explanations will take me some time to soak up.

Second, it will go into the dashboard of my car so I realized I will need buttons to set it so I don't have to remove my dashboard every day light savings or if the rechargeable LIR2032 ever dies (will it die?). My question is, is it possible to add buttons to this existing code or do I need to rewrite the whole thing? When I tried some people's codes for adding buttons they never included rtc.now or now.hour (which I think gets the time automatically from my computer?). Also, I've deleted the year because I don't typically need to see that but will the clock need it to keep track of itself when I'm setting it?

Third, this beautiful additional adafruit_GFX font is nearly perfect aesthetically but quite a memory hog bringing me up to 83% of program storage space. Will adding buttons push it over the limit?

Please let me know if I should delete the post and go back to banging my head. And thanks either way, if not for being able to assist me, then for existing, this forum has already been such great help!


#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.h"
#include <DS3231.h>
#include <Fonts/FreeMonoBold24pt7b.h>


RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Lord's Day", "Mondizzle", "Tuesdizzle", "Winesday", "NewFriday", "Fridizzle", "Caturday"};
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3c
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


void setup() {

  display.setRotation(1);
  Serial.begin(9600);
  delay(3000); // wait for console opening
  display.setFont();
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)// Check your I2C address and enter it here, in Our case address is 0x3C
  display.clearDisplay();
  display.display(); // this command will display all the data which is in buffer
  display.setTextColor(WHITE, BLACK);


}
void loop() {


  DateTime now = rtc.now();
  /*============Display Date=================*/
  display.setFont();
  display.setTextSize(1);
  display.setCursor(4, 5);
  display.print(daysOfTheWeek[now.dayOfTheWeek()]);
  char currentDate [16];
  uint8_t thisDay, thisMonth ;
  thisDay = now.day();
  thisMonth = now.month();
  sprintf (currentDate, "%02d.%02d", thisMonth, thisDay); //add leading zeros to the day and month
  display.setTextSize(2);
  display.setCursor(3, 103);
  display.print(currentDate);
  display.setTextSize(2);
  display.setCursor(0, 85);

  /*================Display Time================*/

  char buffer [16];
  uint8_t thisSec, thisMin, thisHour;
  thisSec = now.second();
  thisMin = now.minute();
  thisHour = now.hour();
  if (thisHour > 12) thisHour = thisHour - 12;
  if (thisHour == 0) thisHour == 12; {
  }
  if (now.hour() >= 18)  {
    display.dim(true);
  }
  else if (now.hour() <= 5) {
    display.dim(true);
  }
  else {
    display.dim(false);
  }


  sprintf (buffer, "%2d%02d", thisHour, thisMin);
  display.setFont (&FreeMonoBold24pt7b);
  display.setTextSize(1);
  display.setCursor(2, 47);
  display.print(buffer);

  int16_t  x1, y1;
  uint16_t w, h;

  display.getTextBounds(buffer, 2, 47, &x1, &y1, &w, &h);


  display.fillRect(x1, y1, w + 2, h + 2, BLACK);

  sprintf (buffer, "%2d%02d", thisHour, thisMin);
  display.setFont (&FreeMonoBold24pt7b);
  display.setTextSize(1);
  display.setCursor(2, 47);
  display.print(buffer);








  display.display();
}
void draw_text(byte x_pos, byte y_pos, char *text, byte text_size) {
  display.setCursor(x_pos, y_pos);
  display.setTextSize(text_size);
  display.print(text);
  display.display();
}

That is why you are not getting correct 12-hour format at midnight. That needs to be changed slightly. It needs to be:
if (thisHour == 0) thisHour = 12;

The reason is this:

  • thisHour == 12 means "check to see whether or not thisHour is equal to 12" -- it does not change anything.
  • thisHour = 12 means "change thisHour to be equal to 12`

So, you want to check to see whether thisHour is 0, and if it is, then change it to be equal to 12.
Remember:

  • == means check
  • = means change

Does this help you to understand what's going on?

As for setting the year: yes, you will need to set the year. The reason for that is that you care about the month and day of the month (I see you are displaying them), and what happens at the end of February? After Feb. 28, should your clock go to Feb. 29, or March 1? For that you need the year.

It is possible to make your clock adjust itself automatically for Daylight Saving Time, but it might not make sense to, because the laws regarding Daylight Saving TIme might change soon.

Yes, you can (in theory) add buttons to set the time, but I don't know if that will use up more memory than you have. You will have to try it and find out.

I'm pretty sure that the RTClib that you are using allows you to set the date and time. However, I'm not quite sure exactly how to use it to set the date and time, never having done it myself. (I've made Arduino clocks, but never with RTClib.) I suggest you do some research and read more about this RTClib, and see if you can find examples of it being used to set the time.

1 Like

First:
the line:

 if (thisHour == 0) thisHour == 12; {

It's wrong, I should put:

 if (thisHour == 0) thisHour = 12; {

Second:
The DS3231 is very stable, in almost a year and a half that I have it running , neither has the battery run out, ( which someday will run out), nor have I had to set it on time, except in the summer-winter time changes.
I have opted to have the usb connector on the accecible panel of the one and connect it to the laptop to set the time 2 times a year instead of placing and programming some cumbersome buttons.
I use a simple program to set the time:

#include <Wire.h>
#include "RTClib.h"

RTC_DS3231 rtc;

void setup() {
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (rtc.lostPower()) {
    Serial.println("RTC lost power, check the battery ");
    while (1);
  }
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

void loop() {
  Serial.println("RTC set on time");
  delay (1000);
}

Third:
If you use my solution you will not occupy more memory.

Greetings

Or, you could program it to set itself automatically twice a year, and only connect to the laptop in the event that the Daylight Saving Time rules change. Depending on where you live, and what the DST rules there are, this might or might not be worth the bother.

By the way, your sketch sets the date and time to when it was compiled, rather than to when it was uploaded or run.

Simpler solution than buttons. Use an Analog connected to a potentiometer and a select button. You can scale the 0-1023 into whatever 1-12, 00-59, etc and when it's dialed right just press the one button.

You can get away with two buttons if you do some fancy footwork with the display to prompt the operator by blinking digits in different formats.

You can buy a $15 module that keeps battery backup time and date, shows in/out temp and supply voltage. It has a green LED display and just two buttons. Only two wire hook up and snap in mounting in about a 2x3/4x1 package. Just saying. Link HERE

Thank you for the explanation, that does make sense to me!

Since I will likely skip the buttons for now so I can get this thing in my car, is it possible to set the year but not print it on the screen? As it is now, it will create problems for feb/march right? Please don't feel obligated to respond to dumb questions (but I am curious if it's okay).

You're right about the time changes, i bet we only have one more :smiley:

Thank you also for the comment about the RTClib. Not understanding my own sketch clearly I didn't even know where to start googling about it.

This is really great, I feel like I am moving forward again!

Yes.
On giving your code another look, I noticed this comment in it:

    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

So, I think there's your answer.

Perfect! Thank you for putting your owl eyes on my sketch! That fixed my 12 hour format.

That's good to hear you're still keeping accurate time a year and a half later, that makes me feel better about installing it. Are you using the rechargeable battery also? It seems like you're supposed to but it also seems like people are using the CR2032 with success.

Thank you for the code too. I added

  Serial.println("RTC set on time");
  delay (1000);

to my void loop() and it's got the right time again.

Thank you, I could tell that was a valuable line but no matter what I put in there nothing changes on the screen. I read a couple weeks ago to uncomment and comment it before uploading but I can't remember which of them to comment or in what order to do these steps. Or even where I read that. Sorry, I'm sure you never meant for such a back and forth.

My code establishes the date and time that the laptop contains at that moment, I suppose that when it is connected to the network via wifi... etc. , is the correct one.
Obviously it only updates the time in the RTC, losing the rest of the code.
Once this first compilation is done, it is obvious to do a second compilation with the original post #1 code, but commenting out the line:

 rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

I'm sorry I didn't explain more extensively earlier.
Greetings.

This

rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

is what you would use to adjust the time. Of course, you would have to change it to something more like

rtc.adjust(DateTime(2022, 4, 4, 1, 37, 0));

or whatever the actual date and time is. Of course, it will only work when uncommented!
If you comment it out, like this

// rtc.adjust(DateTime(2022, 4, 4, 1, 37, 0));

then it will do absolutely nothing.

The computer treats commented-out code as though it doesn't exist. This is well worth remembering.

Ha! Thanks again! Seriously, I can take dense to levels previously unheard of. Thank you for your patience.

Another thing to notice is where the line of code is.

Let's say you have this in your sketch:

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    rtc.adjust(DateTime(2022, 4, 4, 2, 22, 0));
  }

Notice that this line

rtc.adjust(DateTime(2022, 4, 4, 2, 22, 0));

is inside of this:

  if (rtc.lostPower()) {

  }

And, because it is inside of that, the time will only be reset if the RTC has lost power.
So, if you are going to reset the time this way, you might want to remove the battery, and any other power source, from the RTC, and then re-insert the battery, before trying to reset the time this way. The purpose of this is to make sure that the RTC has lost power, so that the check for power loss ends up "true".

Boom. This was it. I kept commenting and uncommenting with no result until I unplugged it (I haven't put the battery in yet).

I have a C++ book in the mail that I'm hoping will help me with these kinds of things.

Everything you need is here: GitHub - Michael-Brodsky/PG: Rapid application development tools for avr/samd/megaavr architectures (Arduino, STMicro, Teensy).

Thank you for the suggestion! I would love a solution simpler than buttons but to fit in an empty button slot in my dashboard I need the screen size of this .96" oled

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.