DS1307 RTC Clock : Different Date & Time Values

Greetings;

I'm fairly new to C++ and Arduino (comming from C#) and I'm building a LCD (Menu) with DS1307, a Pushbutton and AM2302 (DHT22).

Im having issues with the DS1307; where the Date and Time is not shown correctly, and giving (either correct or incorrect values) every time I upload the Code to arduino.

Notes:

  • Using Arduino Uno.

  • DS1307 does not have a battery. Instead is connected: 3v3 (module) to 3.3v (arduino).
    Therefore I know I should expect it not to store the DateTime whenvere the Power is Cut.
    I wonder this is influencing my issue and if I can use arduino power instead of a CR1220 battery and how to hook it up for project completion.
    [!] Additional information regarding this would be extremely appreciated.

  • Using millis() (delay with 1 second) to be able to recognize and click the Pushbutton.

Issues:

  • Sometimes (rarely) Date is Set Correctly;
  • Day of Week is not show 99% of the times;
  • Time is slightly delayed (when is set "almost" correctly);

Result Example:

// Result with Errors
// |TUE MAI 209|
// | 06:36:59 |

// Result Expected
// |TUE 23 MAR 2019|
// | 06:36:59 |

Required:

  • A way to solve this issue (Everything Works Well Except the RTC Clock).

  • Perhaps a better approach (avoiding extreme hardcoding and in the same class.
    I find it hard to understand how to use separate classes on a project; and the lack of something similar to intellisense everything feels really tricky and time consuming);

  • To know and understand the behaviour of the lines bellow.
    *Do any of these lines set the Clock with PC (or Project) DateTime?
    *Do I need to comment them and re-upload the Project everytime I need to set the Clock?

  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  // rtc.adjust(DateTime(now.unixtime() + 10)); // Set Time

My Actual Code:

#include <DHT.h>;             // DHT22 | AM2302 (Temperature & Humidity)
#include "OneButton.h"        // Push Button
#include <LiquidCrystal.h>    // LCD

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

// Constants
#define DHTPIN 13            // DHT Sensor Pin
#define DHTTYPE DHT22        // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE);    // Initializes DHT Sensor (for Normal 16mhz Arduino)

// RTC
RTC_DS1307 rtc;
DateTime now;

// LCD
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Arduino Uno Pins

// DHT 22 | AM2302
float hum;  // Stores : Humidity Value
float temp; // Stores : Temperature Value

// Push Button
OneButton button(A0, true); // Setup a new OneButton on pin A1.

// Menu
int menuPage = 1;

// Millis
unsigned long currentMillis;        // Used to get Current Millis Value
unsigned long previousMillis = 0;   // Used to Store the Last Time the LED was Updated

// setup code here, to run once:
void setup() 
{
  dht.begin();                        // Initializes DHT22

  InitRTC();                          // Initialize RTC

  lcd.begin(16,2);                    // Initializes LCD
  lcd.clear();                        // Clears LCD
  lcd.setCursor(4, 0);                // Sets LCD Cursor Position
  PrntWelcome();                      // Print Welcome Message

  // Push Button(s)
  button.attachClick(ButtonClick);    // Assigns a Push Button to a Method (Similar as Assigning an Event)
}
  
void loop() 
{
  button.tick();                      // Keeps tracking for Push Button Click on Every Machine Tick
  
  currentMillis = millis();           // Get Current Millis Value
  
  if (millisDelay(1000))
  {
    switch(menuPage)
    {
      case 0: break;
      case 1: PrntRTC();    break;
      case 2: PrntDHT22();  break;
      case 3: lcd.clear(); lcd.setCursor(0,0); lcd.print("Menu 3"); break;
      case 4: lcd.clear(); lcd.setCursor(0,0); lcd.print("Menu 4"); break;
    }
  }
}

  // a) If the Difference between "actual millis().Value" and the "millis().(Value when the last event occurred) is 
  // b) "Equals" or "Superior to" : "Specified Interval Value" (delay time)
  // c) then Do Something.

bool millisDelay(long interval)       // Returns true when Time Marker is Reached
{
  bool isReady = false;
  
  // Check to see if it's time to change LED state
  if ((currentMillis - previousMillis >= interval))
  {
    previousMillis = currentMillis;  // Set previousMillis value to Remember the "last time marker"; so it can make Comparisons
    isReady = true;
  }

  return isReady;
}

void GoMainPage()                     // MENU : Returns and Diplays Main Page
{
    menuPage = 0;
    ButtonClick();
}

void ButtonClick()                    // PUSHBUTTON : Button Click
{
  if (menuPage < 4) { menuPage ++; }
  else { menuPage = 1; }
}

void PrntWelcome()                    // LCD : Print Welcome Message
{
  lcd.clear();
  
  // Row, Line 
  lcd.setCursor(6, 0);
  lcd.print("Hello");
  
  lcd.setCursor(1, 1);
  lcd.print("Ricardo Garcia");

  delay(3000);

  GoMainPage();
}

void PrntDHT22()                      // DHT22 : Print Sensor Readings
{
    lcd.clear();
    
    // Read data and store it to variables hum and temp
    hum  = dht.readHumidity();
    temp = dht.readTemperature();

    if(!isnan(temp) && !isnan(hum))
    {      
      // Print temp and humidity values to LCD
      lcd.setCursor(0, 0);
      lcd.print("Tmp: " + String(temp) + " C");
      
      lcd.setCursor(0, 1);
      lcd.print("Hum: " + String(hum) + " %");
    }

    else
    {
      lcd.setCursor(0, 0);
      lcd.print("Failed Reading");

      lcd.setCursor(0, 1);
      lcd.print("Temperature");
    }
}

void InitRTC()                                                   // RTC : RTC Initialization and DateTime Store Configuration
{    
    Wire.begin();
    rtc.begin();
    
    if (!rtc.isrunning()) 
    {
      lcd.clear();
      lcd.setCursor(6,0);
      lcd.print("RTC");

      lcd.setCursor(0, 1);
      lcd.print("RTC is NOT running!");
      
      // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
       rtc.adjust(DateTime(now.unixtime() + 10)); // Set Time
    }
}

void PrntRTC()                                                   // RTC : Print RTC Date & Time
{
    now = rtc.now();

    // Date
    int _day = now.day();
    String dd;
    if (_day < 10 ) { dd = "0"  + _day; }                        // Assign Day (Add Zero if Necessary)
    else { dd = _day; }
    
    int _month = now.month();
    String MM;
    if (_month < 10) { MM = "0" + String(_month); }              // Assign Month (Add Zero if Necessary)
    else { MM = String(_month); }
  
    int _year = now.year();
    
    // Time
    int _hour = now.hour();                                       // Get the hours right now 
    String hh;
    if (_hour < 10){ hh = "0" + String(_hour); }                  // Assign Hours (Add Zero if Necessary)
    else { hh = String(_hour); }
    
    int _minute = now.minute();  // Get the minutes right now
    String mm;
    if (_minute < 10){ mm = "0" + String(_minute); }              // Assign Minutes (Add Zero if Necessary)
    else { mm = String(_minute); }
    
    int _second = now.second();  // Get the seconds right now
    String ss;
    if (_second < 10){ ss = "0" + String(_second); }              // Assign Seconds (Add Zero if Necessary)
    else { ss = String(_second); }

    // Set Date
    lcd.clear();
    
    lcd.setCursor(0, 0);                                          // Row, Line
    lcd.print(GetDOW());                                          // Print Day of Week
    
    lcd.setCursor(4, 0);                                          // Row, Line
    lcd.print(dd + " " + GetMonthName() + " " + String(_year));   // Print Date

    // Set Time
    lcd.setCursor(4, 1);                                          // Row, Line
    lcd.print(hh + ":" + mm + ":" + ss);                          // Print Time
}

String GetDOW()                       // RTC : Get Date & Time
{
  String _dow;
  
  switch(now.dayOfTheWeek())
  {
     case 1: _dow = "Mon"; break;
     case 2: _dow = "Tue"; break;
     case 3: _dow = "Wed"; break;
     case 4: _dow = "Thu"; break;
     case 5: _dow = "Fri"; break;
     case 6: _dow = "Sat"; break;
     case 0: _dow = "Sun"; break;
   }

   return _dow;
}

String GetMonthName()                 // RTC : Get Month Name
{
  String _month;
  
  switch(now.dayOfTheWeek())
  {
     case 1:  _month = "Jan"; break;
     case 2:  _month = "Feb"; break;
     case 3:  _month = "Mar"; break;
     case 4:  _month = "Abr"; break;
     case 5:  _month = "Mai"; break;
     case 6:  _month = "Jun"; break;
     case 7:  _month = "Jul"; break;
     case 8:  _month = "Aug"; break;
     case 9:  _month = "Sep"; break;
     case 10: _month = "Oct"; break;
     case 11: _month = "Nov"; break;
     case 12: _month = "Dez"; break;
   }
   return _month;
}

It is nearly impossible to set the RTC accurately using a hard coded line of programming. You would have to estimate how Long it will take to load and execute the sketch and preset that line of code accordingly. The other Thing is, you then Change the sketch (commenting out the lines) but when you try to reload you may cause a reset which re-runs the code again and sets the time back to the original code.

To set it accurately, you Need to do something like delay 30 seconds, Output a Serial message like "please provide time in xxx Format", wait for a Response which you manually enter through the Serial Monitor and set the time accordingly.

The lines of code you mention do not communicate with the PC at all and are therefore not getting the PC time.

It is probably not a good idea to power the RTC from the Arduino power unless you are really sure about the Arduino powers availability. I would recommend always using the battery as the RTC module was designed.