Help with an RTC time not displaying right

#include <LiquidCrystal.h>
#define DS1307_I2C_ADDRESS 0x68   
#include "Wire.h"
 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int menuState = 0;
int lastState = -1;
int state;
int b_light_value = 0;
int w_light_value = 0;
const int w_pin = 11;
const int b_pin = 3;
int b_output = 0;
int w_output = 0;

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}

void showMenus() {

  switch (menuState){     //Blues Select
    case 0:
      lcd.clear();
      
      lcd.setCursor(0,1);
      lcd.print("Blues");
      break;
    case 1:
      lcd.clear();
        //White Select
      lcd.setCursor(0,1);
      lcd.print("Whites");
      break;
    case 2:
      lcd.clear();
          //Time Set Menu
      lcd.setCursor(0,1);
      lcd.print("Time Set");
      break;
    case 3:
      lcd.clear();
            //Ramp-up/down Timer
      lcd.setCursor(0,1);
      lcd.print("Sunrise/Set");
      break;      
    case 7:
           //Set Blues
      lcd.setCursor(0,1);
      lcd.print("Blues     ");
      lcd.print(b_light_value);
      break;  
    case 8:
         //Set Whites
      lcd.setCursor(0,1);
      lcd.print("Whites     ");
      lcd.print(w_light_value);
      break;  
  }
}  

void processButtons(){
  int state = 0;
  int x = analogRead(0);

 //Check analog values from LCD Keypad Shield
  if (x < 50) {
    state = 5;
    //Right
  } else if (x < 200) {
   //Up
    state = 1;
  } else if (x < 400){
   //Down
    state = 2;
  } else if (x < 600){
    state = 6;
    //Left
  } else if (x < 800){
    //Select
    state = 4;
  }

 delay(250);      //delay button read
 
 switch (menuState){
    case 0:             //Blues
      switch (state){
        case 1:
        menuState = 3;
        showMenus();
        break;
        case 2:
        menuState = 1;
        showMenus();
        break;
        case 4: //Enter
        menuState = 7;
        showMenus();
        }
        break;
     case 1:          //Whites
       switch (state){
         case 1:
         menuState = 0;
         showMenus();
         break;
         case 2:
         menuState = 2;
         showMenus();
         break;
         case 4:
         menuState = 8;
         showMenus();
         break;
         }
         break;
      case 2:         //Time Set
        switch (state){
          case 1:
          menuState = 1;
          showMenus();
          break;
          case 2:
          menuState = 3;
          showMenus();
          break;  
          case 4:
          menuState = 2;
          showMenus();
          break;
          }
          break;
       case 3:        //Ramp-up/down set
        switch (state){
          case 1:
          menuState = 2;
          showMenus();
          break;
          case 2:
          menuState = 0;
          showMenus();
          break;  
          case 4:
          menuState = 3;
          showMenus();
          break;  
          }
          break;
        case 7:   //Adjust Blues
          switch (state){
            case 5: //If Right
            b_light_value = b_light_value + 5;
            b_output =  b_output + 12.75;
            if (b_light_value > 100){
              b_light_value = 0;
            }
            if (b_output > 255){
              b_output = 0;
            }
            analogWrite(b_pin, b_output);
            showMenus();
            break;
            case 6: //If Left
            b_light_value = b_light_value - 5;
            b_output =  b_output - 12.75;
            if (b_light_value < 0){
              b_light_value = 0;
            }
            if (b_output < 0){
              b_output = 0;
            }
            analogWrite(b_pin, b_output);
            showMenus();  
            break;
            case 4: //If Select
            menuState = 0;
            showMenus();
            break;
            }
            break;
         case 8:  //Adjust Whites
          switch (state){
            case 5: //If Right
            w_light_value = w_light_value + 5;
            w_output =  w_output + 12.75;
            if (w_light_value > 100){
              w_light_value = 0;
            }
            if (w_output > 255){
              w_output = 0;
            }
            analogWrite(w_pin, w_output);
            showMenus();
            break;
            case 6: //If Left
            w_light_value = w_light_value - 5;
            w_output =  w_output - 12.75;
            if (w_light_value < 0){
              w_light_value = 0;
            }
            if (w_output < 0){
              w_output = 0;
            }
            analogWrite(w_pin, w_output);
            showMenus();  
            break;
            case 4: //If Select
            menuState = 1;
            showMenus();
            break;
            }   
            break;
  }     
}

void loop(){
  
  processButtons();
  showMenus();
  DisplayTime();
  delay(1000);
  
}  

void setup(){
  setDS1307time(30,42,21,3,8,4,17);
  lcd.begin(16,2);
 
}

void DisplayTime() {

  lcd.setCursor(4,0);
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS1307
  readDS1307time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  &year);

  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute<10)
  {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10)
  {
    Serial.print("0");
  }
  Serial.print(second, DEC);
  lcd.setCursor(4,0);
  lcd.print(hour, DEC);
  lcd.print(":");
  lcd.print(minute, DEC);
  lcd.print(":");
  lcd.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");
  switch(dayOfWeek){
  case 1:
    Serial.println("Sunday");
    break;
  case 2:
    Serial.println("Monday");
    break;
  case 3:
    Serial.println("Tuesday");
    break;
  case 4:
    Serial.println("Wednesday");
    break;
  case 5:
    Serial.println("Thursday");
    break;
  case 6:
    Serial.println("Friday");
    break;
  case 7:
    Serial.println("Saturday");
    break;
  }
}

void setDS1307time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS1307
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}

void readDS1307time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 3);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

Here’s what I have going on. The RTC stuff is basically copy and pasted from another program I made that displays correctly. When I run this, it displays the time as 45:165:85. I’m sure it has somethign to with the way the menu system works but I cant figure out what.

Have you confirmed that in your new setup you can see the RTC on the i2c bus and can read the time with a basic ds1307 library example?

// I2C Scanner
// Written by Nick Gammon
// Date: 20th April 2011

#include <Wire.h>

void setup() {
  Serial.begin (115200);

  // Leonardo: wait for serial port to connect
  while (!Serial) 
    {
    }

  Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;
  
  Wire.begin();
  for (byte i = 8; i < 120; i++)
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
      {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);  // maybe unneeded?
      } // end of good response
  } // end of for loop
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
}  // end of setup

void loop() {}

liquidis54: I cant figure out what.

Those 165 and 85 values might be caused by "reading from a non working I2C bus".

Which RTC module are you using, actually?

Hopefully there is no "Tiny RTC" label printed on the module.

I don't know why they print "Tiny RTC" and not "Fully Crap" on those modules. But that's what they are. Use any other RTC module (foraccurate timing, DS3231), but NOT Tiny RTC.

And: Include two lines of code in the setup() function to check whether the I2C bus on your RTC module is working!

Crap! Yeah, it says tiny rtc :/ I'll give that a shot and see what happens.

45:165:85 is nothing to do with the menu system. It is a sure/certain sign that the RTC is not connected properly. The library is reading the RTC and getting 0xff from each register. For example, this is why it shows 165 for the minutes. When it reads the minutes register it assumes that it is reading a correct value (which is stored in BCD) so it multiplies the top BCD digit by 10 and then adds the bottom BCD digit. But both digits are 0xF = 15. So the result is 15*10+15 = 165.

Pete

If I add in that code it displays a time and updates, in the serial monitor it says it found the address and prints time and date, but, the time and date aren't what I set in settime. Also, if I remove the code, it stops working. I'm not exactly sure what that code does or why it works.

Add Wire.begin() to setup.

Ha, wow, ok that worked. Im still kind of a noob to this obviously. Thanks for the help. Now the only issue is that the time seems to skip a second every so often. Im assuming this has to do with buying a crappy RTC?

Now the only issue is that the time seems to skip a second every so often. Im assuming this has to do with buying a crappy RTC?

void loop(){ 
  processButtons();
  showMenus();
  DisplayTime();
  delay(1000);  
}

No, it's more to do with your code and your expectations. Loop() take some time to execute, the delay may also be longer than one second because the UNO oscillator is not very accurate. With these factors, it can be very easy to miss out a second.

Ah, ok. Is there a way to fix/compensate for that?

you have a realTime clock!!!

void loop(void)
{
  static byte lastSecond = 60;
  byte nowSecond = second();
  if(nowSecond != lastSecond)
  {
    updateDisplay();
    lastSecond = nowSecond;
  }
}

liquidis54: Ha, wow, ok that worked. Im still kind of a noob to this obviously. Thanks for the help. Now the only issue is that the time seems to skip a second every so often. Im assuming this has to do with buying a crappy RTC?

Not really, skipping a second every two or three minutes is caused by the inarrurate 16 MHz clocking of most Arduino boards.

Modern boards ("R3" design) like UNO R3, create their 16 MHz clocking NOT from a fairly accurate crystal oscillator, but by a fairly inaccurate ceramic resonator.

A 16 MHz ceramic resonator might be off by 0.8% from 16 MHz,actually and this is also the inaccuracy of internal timing, created by the board.

So delay(1000) might be something in the range 992 ... 1008 milliseconds.

Even the crappiest RTC will be MUCH MORE ACCURATE than 0,8%. But ceramic resonators might be inaccurate by 0.8%, which is 0.8 seconds in 100 seconds, or let's say: One second in two minutes, worst case.

Skipping seconds is caused by the discrepancy of "internal" 16 MHz timing (inaccurate up to 0.8%) and real time RTC timing (accurate). Time drift may be up to one whole second in two minutes. And don't forget: Execution time of your code. This is NOT counted in the RTC module. RTC module counts "real time" only.

See a problem with these lines?:

  Wire.requestFrom(DS1307_I2C_ADDRESS, 3);
  // request seven bytes of data from DS3231 starting from register 00h