RTC inconfident in time and date

Hello,

I am using a RTC (the DS1307) and an Arduino nano ESP32. The problem is that the RTC isn't confident in date and time. Or in my program, it gives the error message 1R6 on the OLED display all the time.

I don't have a battery, it is powered by a power supply, and that works. Because if I use the standard program from the RTC library by Makuna, it works fine. I have basically copied and pasted the whole example to fit in my program.

This is my program:

  /* 
  * CONNECTIONS:
  *  - DS1337:
  *    - SDA (D2)
  *    - SCL (D5)
  *    - +3V (+ BATTERY)
  *    - GND (- BATTERY) 
  *    - X1  (CRYSTAL)
  *    - X2  (CRYSTAL)
  *
  *  - OT811:
  *    - SDA (A4)
  *    - SCK (A5)
  *    - Vcc (+3.3V)
  *    - GND (GND)
  * 
  * 
  * ERRORS:
  *  - ERROR 1Dx
  *    - ERROR 1D1
  *      - The internal voltage of the OLED-display is not +3.3V. The arduino will continue looping. Try (dis)connection the power or replace the OLED-display.
  *
  *  - ERROR 1Rx
  *    - ERROR 1R1
  *      - The battery of the RTC is low or missing. Or the RTC wasn't running yet. Restart the program, else, replace the battery.
  *    - ERROR 1R2
  *      - The RTC wasn't running, please reset the arduino.
  *    - ERROR 1R3
  *      - The RTC time is older than the real time. Nothing has to be done, the arduino will set it right.
  *    - ERROR 1R4
  *      - There is an error message but no error, please reset the arduino.
  *    - ERROR 1R5
  *      - There are too much messages waiting on the RTC, please reset the arduino.
  *    - ERROR 1R6
  *      - There is no device responding to the arduino, please check the RTC battery and the RTC itself.
  *    - ERROR 1R7
  *      - The RTC has a wrong chip, place replace the RTC with a DS1337.
  *    - ERROR 1R8
  *      - The communication with the RTC takes to long, please check the battery of the RTC, the RTC itself and if the RTC is connected with the arduino.
  *    - ERROR 1R9
  *      - There is an error message but it isn't further specified.
  * 
  * 
  * 
  * 
  */



  #include <Wire.h>                                                                         //library to establish I²C connection        
  #include <Adafruit_GFX.h>                                                                 //library to print and draw on the OLED-display
  #include <Adafruit_SSD1306.h>                                                             //library to establish connection with the OLED-display
  #include <RtcDS1307.h>                                                                    //library to convert incoming data from the RTC
  #include <ThreeWire.h>

  #define RTC_SDA 2                                                                         //define the SDA port of the RTC
  #define RTC_SCL 5                                                                         //define the SCL port of the RTC
  #define ALL_SDA 4                                                                         //define the SDA port of the ATtiny85's and the OLED-display
  #define ALL_SCL 5                                                                         //define the SCL port of the ATtiny85's and the OLED-display
  #define SCREEN_WIDTH 128                                                                  //OLED display width, in pixels
  #define SCREEN_HEIGHT 32                                                                  //OLED display height, in pixels
  #define OLED_RESET     -1                                                                 //variable to connect the screen with the reset of the arduino (needs to be -1 to share the reset)
  #define SCREEN_ADDRESS 0x3C                                                               //adress of the OLED-display
  #define error_time 5000                                                                   //the time an error will be displayed

  RtcDS1307<TwoWire> Rtc(Wire);                                                             //configure the RTC
  Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);                 //configure the OLED-display

  bool true_error = false;                                                                  //this boolean will be set true if there is an error



  void print_error(String error_code){                                                      //void to display an error

    if(error_code == "START-UP"){

      display.clearDisplay();                                                               //clear the display
      display.setTextSize(2);                                                               //set the text size to 2
      display.setCursor(2, 2);                                                              //set the cursor on the display on pixel 2, 2
      display.print("START-UP");                                                            //write the error
      display.display();                                                                    //display the error

      true_error = false;                                                                   //set the error boolean false

      delay(1500);                                                                          //wait some time before the main program will start
      
    }
    else{

      display.clearDisplay();                                                               //clear the display
      display.setTextSize(2);                                                               //set the text size to 2
      display.setCursor(2, 2);                                                              //set the cursor on the display on pixel 2, 2
      display.print("ERROR: ");                                                             //write "ERROR: "
      display.setCursor(70, 2);                                                             //set the cursor on the display on pixel 32, 2
      display.print(error_code);                                                            //write the error code
      display.display();                                                                    //display the error

      true_error = true;                                                                    //set the error boolean true

    }
  }

  bool wasError(const char* errorTopic = ""){                                               //function to determine the right error
      
    uint8_t error = Rtc.LastError();                                                        //set the variable "error" to the last error that isn't processed

    if (error != 0){                                                                        //if the error variable isn't empty, so there is an error

      switch (error){                                                                       //compare the error to different kinds of errors to determine the right error message
          
        case Rtc_Wire_Error_None:                                                           //if the error message is nothing
          print_error("1R4");                                                               //start the void print_error with the error message 1R4
          break;                                                                            //exit the switch case
          
        case Rtc_Wire_Error_TxBufferOverflow:                                               //if there are too much messages waiting for the RTC
          print_error("1R5");                                                               //start the void print_error with the error message 1R5
          break;                                                                            //exit the switch case
          
        case Rtc_Wire_Error_NoAddressableDevice:                                            //if there isn't a device responding to the messages of the arduino
          print_error("1R6");                                                               //start the void print_error with the error message 1R6
          break;                                                                            //exit the switch case
          
        case Rtc_Wire_Error_UnsupportedRequest:                                             //if there is a wrong RTC connected 
          print_error("1R7");                                                               //start the void print_error with the error message 1R7
          break;                                                                            //exit the switch case
        
        case Rtc_Wire_Error_CommunicationTimeout:                                           //if the communication takes to long
          print_error("1R8");                                                               //start the void print_error with the error message 1R8
          break;                                                                            //exit the switch case

        case Rtc_Wire_Error_Unspecific:                                                     //if there is an error but it isn't further specified
          if(!true_error){                                                                  //only if there is no other error message, this one can be displayed
            print_error("1R9");                                                             //start the void print_error with the error message 1R9
          }
          break;                                                                            //exit the switch case
        
      }
      
      return true;                                                                          //return the value true
    
    }
    
    return false;                                                                           //return the value false

  }



  void setup() {

    Wire.begin();                                                                           //start the I²C communication
    Serial.begin(115200);                                                                   //start the serial communication  
    Rtc.Begin(2, 5);                                                                        //set the RTC to the dedicated pins.

    Serial.print("compiled: ");
    Serial.print(__DATE__);
    Serial.println(__TIME__);

    Rtc.Begin();                                                                            //start the RTC
    #if defined(WIRE_HAS_TIMEOUT)                                                           //if the I²C communication has a time-out
      Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);                      //reset on time-out
    #endif                                                                                  //close the if statement

    RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);                                 //set the RTC time to the real time

    if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)){                               //if the internal OLED display voltage isn't 3.3V, don't stop the loop protect the OLED display

      Serial.println(F("ERROR: 1D1"));                                                      //print the error on the serial monitor
      true_error = true;                                                                    //set the error bool true
      for(;;);                                                                              //go in an infinite loop

    }

    display.setTextSize(1);                                                                 //set the standard text size to 1
    display.setTextColor(WHITE);                                                            //set the standard text color to white
    display.clearDisplay();                                                                 //clear the display

    if (!Rtc.IsDateTimeValid()){                                                            //if there is an error in the communication with the RTC
      if (!wasError("setup IsDateTimeValid")){                                              //if the time obtained from the RTC isn't valid

        print_error("1R1");                                                                 //start the void print_error with the error message 1R1
        Rtc.SetDateTime(compiled);                                                          //set the RTC time as an atempt to regain the right connection and communication

      }
    }

    if (!Rtc.GetIsRunning()){                                                               //if the RTC isn't running
      if (!wasError("setup GetIsRunning")){                                                 //if the message "setup GetIsRunning" hasn't appeared internally

        print_error("1R2");                                                                 //start the void print_error with the error message 1R2
        Rtc.SetIsRunning(true);                                                             //start the RTC

      }
    }

    RtcDateTime now = Rtc.GetDateTime();                                                    //get the RTC time to compare with the real time

    if (!wasError("setup GetDateTime")){                                                    //there wasn't an error where the RTC wasn't running
      if (now < compiled){                                                                  //if the RTC time is older than the real time

        print_error("1R3");                                                                 //start the void print_error with the error message 1R3
        Rtc.SetDateTime(compiled);                                                          //set the RTC time to the time the program was compiled

      }
      else if (now > compiled){                                                             //if the RTC time is newer than the real time

        print_error("START-UP");                                                            //start the void print_error with the start message START-UP

      }
      else if (now == compiled){                                                            //if the RTC time is the same as the real time

        print_error("START-UP");                                                            //start the void print_error with the start message START-UP
      
      }
    }

      Rtc.SetSquareWavePin(DS1307SquareWaveOut_Low);                                        //clear the RTC to the needed state
      wasError("setup SetSquareWavePin");                                                   //set RTC message to "setup SetSquareWavePin"

  }

  

  void loop() {

    if (!Rtc.IsDateTimeValid()) 
    {
        if (!wasError("loop IsDateTimeValid"))
        {
            // Common Causes:
            //    1) the battery on the device is low or even missing and the power line was disconnected
            Serial.println("RTC lost confidence in the DateTime!");
        }
    }

    RtcDateTime now = Rtc.GetDateTime();
    if (!wasError("loop GetDateTime"))
    {
        printDateTime(now);
        Serial.println();
    }

    delay(1000); // ten seconds

  }

  #define countof(a) (sizeof(a) / sizeof(a[0]))

  void printDateTime(const RtcDateTime& dt){                                                //void to print the time on the OLED-display
  
    display.setTextSize(1);                                                                 //set the text size to 1
    display.clearDisplay();                                                                 //clear the display

    if(dt.Day() >= 10){                                                                     //if the day is a duble digit number

      display.setCursor(3,2);                                                               //set the cursor to position 3, 2
      display.print(dt.Day());                                                              //print the day

    }
    else{

      display.setCursor(3, 2);                                                              //set the cursor to position 3, 2
      display.print("0");                                                                   //print 0

      display.setCursor(15,2);                                                              //set the cursor to position 11, 2
      display.print(dt.Day());                                                              //print the day

    }

    display.setCursor(17, 2);                                                               //set the cursor to position 17, 2
    display.print("/");                                                                     //print /

    if(dt.Month() >= 10){

      display.setCursor(24, 2);                                                             //set the cursor to position 24, 2
      display.print(dt.Month());                                                            //print the month

    }
    else{

      display.setCursor(24, 2);                                                             //set the cursor to position 24, 2
      display.print("0");                                                                   //print 0

      display.setCursor(36, 2);                                                             //set the cursor to position 32, 2
      display.print(dt.Month());                                                            //print the month

    }

    display.setCursor(38, 2);                                                               //set the cursor to position 37, 2
    display.print("/");                                                                     //print /

    display.setCursor(44, 2);                                                               //set the cursor to position 45, 2
    display.print(dt.Year());                                                               //print the year

    display.setTextSize(2);                                                                 //set the text size to 2

    if(dt.Hour() >= 10){                                                                    //if the hour has 2 digits

      display.setCursor(3, 15);                                                             //set the cursor to position 3, 15
      display.print(dt.Hour());                                                             //print the hour

    }
    else{

      display.setCursor(3, 15);                                                             //set the cursor to position 3, 15
      display.print("0");                                                                   //print 0

      display.setCursor(15, 15);                                                            //set the cursor to position 11, 15
      display.print(dt.Hour());                                                             //print the hour

    }

    display.setCursor(25, 15);                                                              //set the cursor to position 25, 15
    display.print(":");                                                                     //print :

    if(dt.Minute() >= 10){

      display.setCursor(35, 15);                                                            //set the cursor to position 37, 15
      display.print(dt.Minute());                                                           //print the minute

    }
    else{

      display.setCursor(35, 15);                                                            //set the cursor to position 3, 15
      display.print("0");                                                                   //print 0

      display.setCursor(49, 15);                                                            //set the cursor to position 11, 15
      display.print(dt.Minute());                                                           //print the hour

    }

    display.display();                                                                      //display the prepared text

    delay(10);                                                                              //wait 10 milliseconds to cool the processor off

  }


So does anybody know what the solution is for this problem?

Thank you.

1 Like

You might want to see what advances have been made in the RTC world since the DS1307 which is extremely old. Check the Chronodot V3 as an example
https://docs.macetech.com/doku.php/chronodot_v3.0

Are you using the DS1337 or DS1307? The DS1307 has a maximum I2C clock speed of 100KHz, the 400KHz I2C used by the Adafruit_SSD1306 library can cause problems.

I actually use the DS1337, but the library is the 1307. This works fine in the examples, but the moment I even think about changing something, things go wrong.

And it isn't a board, but a raw chip and a crystal.

Is that a problem? And if it is, can I do something about it?

It would seem not:

Can we assume "something" means the code, you are not changing the circuit in any way?

If so, go back to the examples, test again, and then begin making small changes to move towards your code. Test after each change. This should reveal what the problem was as soon as it stops working.

1 Like

no just the code

1 Like

Is there some specific reason you are using an RTC without battery backup on an ESP32?

Just to test, I have a battery holder, but the pins are too big for my breadboard. In my PCB will be a battery.

Another important question would be why you are using a RTC at all. If your ESP will always have access to the internet through WiFi, you do not need an RTC at all.

2 Likes

I have to, because my teacher thinks it is important to use a computer gadget when there is no wifi.

I am making a macro pad, but also for the moments there isn't any Wi-Fi.

1 Like

Sorry, I don't do homework.

No problem, the ESP can keep time well enough for moments with no WiFi, so long as it has power. Obviously, it's timekeeping will drift further away from the correct time the longer the time without WiFi, but I guess that will be a few seconds, maybe a couple of minutes, per day.

2 Likes

Thank you really hard. I am looking for a solution for like 3 days. Now i just have to figure out how that works. But I'll figure it out.

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