Tiny RTC Wrong date and time problem

Hi there!

I have a Tiny RTC (ds1307) module and i wrote a small tool on my computer that will send the date and time in case the battery fails. Now that tool already works, but i have a problem on the arduino side.
It just writes the wrong value to the RTC. What is wrong with my code? Please note the way the data is being transferred is with a 10 millisecond delay and then it expects the new data to arrive.

I hope somebody can help! :slight_smile:

(This code also writes it to a OLED display, but it is not mandatory)

#include <RTClib.h>

#include <Wire.h>
RTC_DS1307 RTC;

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

int RTC_Configured;

int m;
char carray[6];
byte Month = 0;
byte Day = 0;
byte Year = 0;
byte Hour = 0;
byte Minute = 0;
byte Second = 0;
String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete

byte decToBcd(byte val) {
  return ((val/10*16) + (val%10));
}


void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    Wire.begin();
    RTC.begin();

    delay(100);
    Serial.println("RTC DEMO OK"); 
    //Dit wordt gebruikt voor de configurator om er zeker van te zijn dat het de Tiny RTC Demo is
    delay(100);
  if (! RTC.isrunning()) {
    Serial.println("RTC DEMO NOT SET");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC_Configured = 1;
    delay(100);
  }
}

void loop() {
  // put your main code here, to run repeatedly:

  if (stringComplete) {
    if (isDigit(inputString.charAt(0))){
     
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Month = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;

      delay(10);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Day = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;

      delay(10);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Year = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;

      delay(10);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Hour = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;

      delay(10);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Minute = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;

      delay(10);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Second = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;

    RTC.adjust(DateTime(Year, Month, Day, Hour, Minute, Second));

    }

    inputString = "";
    stringComplete = false;
    RTC_Configured = 0;
    }

  if (RTC_Configured != 1) 
  {
    DateTime now = RTC.now(); 
    Serial.print("DATE");
    Serial.print(now.year(), DEC);
    Serial.print('-');
    Serial.print(now.month(), DEC);
    Serial.print('-');
    Serial.print(now.day(), DEC);
    Serial.println();
    
    delay(100);
    
    Serial.print("TIME");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println(); 

    display.clearDisplay();
    display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Tiny RTC Demo");

  display.setCursor(0,8);
  display.print("Date: ");
  display.print(now.year(), DEC);
  display.print("-");
  display.print(now.month(), DEC);
  display.print("-");
  display.println(now.day(), DEC);

  display.print("Time: ");
  display.print(now.hour(), DEC);
  display.print(":");
  display.print(now.minute(), DEC);
  display.print(":");
  display.print(now.second(), DEC);

  display.setCursor(0,56);
  display.print("Gemaakt door: Sander");
  
  display.display(); //Je MOET display.display doen of anders zal hij niks laten zien
    delay(250); //Vaker dan 1 keer bijwerken om er zeker van te zijn dat de tijd op het beeldscherm klopt
  }
  else
  {
    display.clearDisplay();
    display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Use the Tiny RTC Demo");
  display.println("Configurator to set");
  display.println("the clock!");
  display.display();
  }
}

void serialEvent() {
  while (Serial.available()) {
  // get the new byte:
  char inChar = (char)Serial.read(); 
  // add it to the inputString:
  delay(3);
  inputString += inChar;
  stringComplete = true;

  }
}

Do you put a new battery in first after the old battery fails?

no, i have a tiny capacitor inside there as this module also charges it.
So it doesn't run out of power that fast.

But with wrong date and time i mean when my tool writes the date and time to the arduino, the arduino just displays the wrong date and time and saves it in the Tiny RTC module. But i know for a fact that the tool i made works, just the arduino sketch doesn't work

Does somebody else know a solution?
I still haven't been able to fix it and i'm slowly starting to go insane :-/
I'm suspecting that i write a value to the RTC while it actually expects something else, But i don't know for sure.

just the arduino sketch doesn't work

You've provided not a shred of proof. The Arduino code DOES work. It just doesn't do what you expect. So, you need to prove to us what it ACTUALLY does. Then, we can help you understand why your expectations are wrong.

Okay, After editing the sketch i can already see missing data in the variables.
So there might be a problem the variable names or a problem with my tool

I'm gonna continue diagnosing everything!

      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Month = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;

      delay(10);
      inputString.toCharArray(carray, sizeof(carray));

inputString has not changed between these calls, so the same data will be copied into carray in both cases.

Storing the converted value in Month and then Day is wrong.

That was indeed the problem!
I noticed that every value that was send would later return as the month that was entered.
And since the month is the first thing that is transmitted that means it is indeed a variable problem!
But how should i fix this? What is the best way to do it? And where must i add it / replace it?

Thanks for the help so far! :slight_smile:

Does somebody know how i need to change the code?
Since i don't have much RAM Memory available on the UNO and i haven't been able to fix it :frowning:
Can somebody post the code that i need to change?

I have tried clearing the array, but sadly it causes the program to slow down too much and causes the timing to go bad :frowning:
Does somebody know a solution?

Here is the updated code since i have changed a few things since the first time i posted the code

#include <RTClib.h>

#include <Wire.h>
RTC_DS1307 RTC;

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

int RTC_Configured;

int m;
char carray[6];
byte Month = 0;
byte Day = 0;
byte Year = 0;
byte Hour = 0;
byte Minute = 0;
byte Second = 0;
String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
boolean exists = true; // Controlleer of de RTC beschiktbaar is

byte decToBcd(byte val) {
  return ((val/10*16) + (val%10));
}


void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    Wire.begin();
    RTC.begin();

    delay(100);
    Serial.println("RTC DEMO OK"); 
    //Dit wordt gebruikt voor de configurator om er zeker van te zijn dat het de Tiny RTC Demo is
    delay(100);
    
    Wire.beginTransmission(0x68);
  #if ARDUINO >= 100  
    Wire.write((uint8_t)0x00); 
  #else
    Wire.send(0x00);
  #endif  
  if (Wire.endTransmission() != 0) { //Controleer of de RTC module bereikbaar is
    Serial.println("RTC DEMO HARDWARE ERROR"); //De RTC module is niet bereikbaar, meld dit aan de computer
    exists = false;
  } else { 
  if (! RTC.isrunning()) { //Controleer of de RTC module al ingesteld is
    Serial.println("RTC DEMO NOT SET"); //De RTC module is nog niet ingesteld, meld dit aan de computer
    RTC_Configured = 1;
    delay(100);
  }
  }
}

void loop() {
  // put your main code here, to run repeatedly:

  if (exists == false) {
    HardwareError();
  }

  if (stringComplete) {
    if (isDigit(inputString.charAt(0))){

      display.setTextSize(1);
      display.setTextColor(WHITE);
      display.setCursor(30,40);
      display.println("Syncing...");
      display.display();

      memset(carray, 0, sizeof(carray));

      delay(15);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Month = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;
      Serial.println(Month);

      memset(carray, 0, sizeof(carray));

      delay(15);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Day = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;
      Serial.println(Day);

      memset(carray, 0, sizeof(carray));

      delay(15);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Year = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;
      Serial.println(Year);

      memset(carray, 0, sizeof(carray));

      delay(15);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Hour = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;
      Serial.println(Hour);

      memset(carray, 0, sizeof(carray));

      delay(15);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Minute = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;
      Serial.println(Minute);

      memset(carray, 0, sizeof(carray));

      delay(15);
      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Second = m;
      for( int i = 0; i < sizeof(carray);  ++i )
      carray[i] = (char)0;
      Serial.println(Second);

    RTC.adjust(DateTime(Year, Month, Day, Hour, Minute, Second));

    delay(5000);

    }

    inputString = "";
    stringComplete = false;
    RTC_Configured = 0;
    }

  if (RTC_Configured != 1) 
  {
    DateTime now = RTC.now(); 
    Serial.print("DATE");
    Serial.print(now.year(), DEC);
    Serial.print('-');
    Serial.print(now.month(), DEC);
    Serial.print('-');
    Serial.print(now.day(), DEC);
    Serial.println();
    
    delay(100);
    
    Serial.print("TIME");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println(); 

    display.clearDisplay();
    display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Tiny RTC Demo");

  display.setCursor(0,8);
  display.print("Date: ");
  display.print(now.year(), DEC);
  display.print("-");
  display.print(now.month(), DEC);
  display.print("-");
  display.println(now.day(), DEC);

  display.print("Time: ");
  display.print(now.hour(), DEC);
  display.print(":");
  display.print(now.minute(), DEC);
  display.print(":");
  display.print(now.second(), DEC);

  display.setCursor(0,56);
  display.print("Gemaakt door: Sander");
  
  display.display(); //Je MOET display.display doen of anders zal hij niks laten zien
    delay(250); //Vaker dan 1 keer bijwerken om er zeker van te zijn dat de tijd op het beeldscherm klopt
  }
  else //Als de RTC nog niet geconfigueerd is zal de code hier naar toe springen
  {
    display.clearDisplay();
    display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("The RTC is not ready!");
  display.println(""); //Laat een lege regel over
  display.println("Use the Tiny RTC Demo");
  display.println("Configurator to set");
  display.println("the clock!");
  display.display();
  }
}

void HardwareError() { //Als er een hardware error is bij het opstarten zal de code hier naar toe springen
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Hardware error!");
  display.println(""); //Laat een lege regel over
  display.println("Unable to detect the");
  display.println("Tiny RTC Module.");
  display.println("Please check your");
  display.println("connections.");
  display.display();
  delay(100000);
  HardwareError(); //Laat de arduino steeds hier naartoe springen zodat de sketch niet veder wordt geladen. Dit is permanent zolang de sketch draait!
}

void serialEvent() {
  while (Serial.available()) {
  // get the new byte:
  char inChar = (char)Serial.read(); 
  // add it to the inputString:
  delay(3);
  inputString += inChar;
  stringComplete = true;

  }
}

Here is the updated code since i have changed a few things since the first time i posted the code

From which I'm going to snip a few things, like useless delay()s...

  if (stringComplete) {
    if (isDigit(inputString.charAt(0))){

      memset(carray, 0, sizeof(carray));

      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Month = m;

      Serial.println(Month);

      memset(carray, 0, sizeof(carray));

      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Day = m;

      Serial.println(Day);

      memset(carray, 0, sizeof(carray));


      inputString.toCharArray(carray, sizeof(carray));
      m = atoi(carray);
      Year = m;

You have a String, containing some unknown data (at least, I don't know what it contains). You copy the String contents to a char array, and convert the data to an int. You copy the value to a variable called Month.

Then, you take the same String and copy the contents to a char array, and convert the data to an int. You copy the value to a variable called Day.

Then, you take the same String and copy the contents to a char array, and convert the data to an int. You copy the value to a variable called Year.

How can you reasonably expect to get different values in Month, Day, and Year?

Just what IS in inputString?

You have to parse the String. That means that you find the first delimiter - the one that precedes the data of interest. Then, you find the second delimiter - the one that marks the end of the data of interest. Then, you make a substring of the part between the two delimiters. You convert the substring to an int. Then, you make the first delimiter position what was the second position, and find the position of the next delimiter, make a substring, etc.

Suppose that you have "Now: 6/15/17 7:56:23" in inputString. You find the position of the ':' - 3. You find the position of '/' - 6. You make a substring of the data between them, " 6". You convert that to Month. Then, the first delimiter position becomes 6, and you find a '/' relative to position 6, which is in position 9. So, you create a substring, "15", and convert that to Day.

You can see that the next delimiter is not a slash. It is a space, and the substring becomes "17" which becomes Year.

Parsing the time is simply a matter of plodding on.

that does indeed sound a lot easier and more reliable.
I'll check on how to do that and i will post the code when i got it working!
I can also post the configurator program that runs on your computer, but i don't think that that is allowed