Saving WidgetRTC time to TimeLib time for offline usage

Pretty basic question here, I’ve got my Blynk RTC setup and it works great, but as soon as I disconnect I lose all time information. I need to store the time locally using the Time Arduino library, basically storing the most last time before disconnect, and then re-synchronizing when I reconnect. I’m not even really sure where to start with saving the Blynk data locally. I already have a BlynkTimer that requests time information every second, so within the function called by that timer I want to store the time locally within the Time Library so it can be accessed with hourFormat12(), minute(), etc. Once again, as it stands now, as soon as I lose connection I don’t get anything displayed on my LCD. If you cannot help me without seeing code, let me know, but I’m hoping it’s a question that can just be answered as my code is messy and disorganized. Thanks again.

When you say “disconnect” do you mean disconnecting the board from the power supply, or are you meaning when your router drops the connection to the internet?

Exactly which board are you using for this?

Are you saying that you are re-synchronising the time with the Blynk server once every second? (hopefully not!).

Pete.

By disconnect I mean press the stop button in the Blynk App. I’m using an Arduino UNO over Serial/USB to my laptop. I plan on using an ESP8266 later however.

In terms of the Blynk time resync, it runs the command Blynk.sendInternal("rtc", "sync"); every second. I’m happy to extend this time if it would help, I’m not sure if it needs to be fetched this fast so if I could do it every minute that may be better.

The normal process is to allow the Blynk library to synchronise automatically every 10 minutes using the following:

setSyncInterval(10 * 60); // Sync interval in seconds (10 minutes)

It’s difficult to say what’s happening within your sketch without seeing the code.

Pete.

I’ll post more of my code in a few. That’s a good thing to keep in mind. But back to my original question, how would I store that time information locally? Is there a method to check if the time data returned is invalid, or if Blynk is disconnect etc?

The Blynk rtc does not stop working if off line!

I’m not showing full code because it’s unneeded and messy, but here is my function that displays the time to an LCD

void displayTime() {
  //basically just some LCD stuff, moving cursor around and displaying strings on it
  alarmShowing = false;
  lcd.clear();
  lcd.setCursor(3, 0); //Set cursor at block 4
  if (hourFormat12() < 10) {
    lcd.print(" " + String(hourFormat12()));
  } else {
    lcd.print(hourFormat12()); // display 12 hour time
  }
  blinkColon(5); //Blink colon at block 5
  lcd.setCursor(6, 0); //Set cursor at block 7
  lcd.print(digitMinutes(minute())); //display minutes at cursor 6/7
  lcd.setCursor(9, 0);
  lcd.print(aMpM());
}

Basically, this code displays the time found from the TimeLib (I haven’t manually setup anything here, it seems that WidgetRTC automatically transfers it’s time data to TimeLib). I use the hourFormat12() method within TimeLib, as well as a beautified version of the minute() method to get the 12 hour time printed.

The above function runs during this function:

void requestTime() {
  Blynk.sendInternal("rtc", "sync");
  //if alarm is not showing
  if (!alarmShowing) {
    displayTime();
  }
}

Which runs primarly within:

void setup() {
  Serial.begin(9600);
  SwSerial.begin(9600);
  Blynk.begin(Serial, auth);
  setSyncInterval(1L);
  //Starts refreshing time/displaying time every second
  pinMode(A0, INPUT);
  lcd.begin(16, 2); //Sets character size
  lcd.clear();
  synctimer.setInterval(1000L, requestTime);
}

void loop() {
  //Basic testing shows above 900 = flashlight
  //Serial.println(analogRead(A0));
  Blynk.run();
  synctimer.run();
}

Where synctimer is a BlynkTimer. As I mentioned, requestTime() is called in a few other places, usually after another screen is done being shown on the LCD. rtc.begin() and Blynk.syncAll() run on BLYNK_CONNECTED. WidgetRTC rtc is declared in my sketch, more details are in the full spoiler.

So when I have my Blynk app running (I press the start button and the board is connected) it works fine, the time displays accurately and keeps time, all my other code works etc. But when I press the stop button or close the Blynk Serial server on my PC, the screen completely blanks out. I know this may be a easy question but I cannot figure out how to do this. If the code I provided is not enough, here is the entire sketch in a spoiler. I know it’s messy and inefficient, but I am only trying to sort out this one thing for now. Thanks!

#include <ISR_Timer.h>
#include <LiquidCrystal.h>
#include <TimeLib.h>
#include <NTPClient.h>
#include <Blynk.h>
#include <BlynkSimpleStream.h>
//ONLY FOR TESTING
#include <SoftwareSerial.h>
#include <WidgetRTC.h>


//setup software serial on rx tx (ONLY FOR TESTING)
SoftwareSerial SwSerial(10, 11); // RX, TX
char auth[] = xxxxxxxxx //Don't worry it works, just protecting my key for the post.
LiquidCrystal lcd(13, 12, 11, 10, 9, 8); //Create LCD object at set pins.
WidgetRTC rtc;
BlynkTimer synctimer;
unsigned long previousMillis = 0;
const long interval = 800;
const long intervalshow = 1000;
boolean colonShow = false;
boolean alarmRunning = false;
boolean alarmShowing = false;
long localAlarm;

void blinkColon(int cursorpos) {
  //store current time since last reset
  unsigned long currentMillis = millis();
  //check if the time between now and 0 is more than 800
  if (currentMillis - previousMillis >= interval) {
    //set then to now
    previousMillis = currentMillis;
    //if colon is not on screen
    if (colonShow == false) {
      //set colonshow to true & display colon
      colonShow = true;
      lcd.setCursor(cursorpos, 0);
      lcd.print(":");
    } else {
      //set colonshow to false & remove colon
      colonShow = false;
      lcd.setCursor(cursorpos, 0);
      lcd.print(" ");
    }
  }
}

String aMpM() {
  //return string for am or pm
  if (isAM()) {
    return "A.M.";
  } else {
    return "P.M.";
  }

}

boolean alarmReached() {
  //returns whether or not alarm should go off
  //set alarm running true
  alarmRunning = true;
}



String digitMinutes(int input) {
  //create empty string
  String minutes = String(input);
  //check if current minute is less than 10. (0,1,2,3 etc)
  if (input < 10) {
    //add 0 to beginning of the string version of current minute (00, 01, 02, 03 etc)
    minutes = "0" + String(input);
    if (input < 1) {
      return "00";
    } else {
      return minutes;
    }
  } else {
    return minutes;
  }


  return minutes;
}


String alarmFormat(TimeInputParam t) {
  int houroutput = 0;
  String ampm = "";
  if (t.getStartHour() >= 12) {
    if (t.getStartHour() == 12) {
      houroutput = 12;
    } else {
      houroutput = t.getStartHour() - 12;
    }
    ampm = " P.M.";
  } else {
    if (t.getStartHour() == 0) {
      houroutput = 12;
    } else {
      houroutput = t.getStartHour();
    }
    ampm = " A.M.";
  }



  return String(houroutput) + ":" + digitMinutes(t.getStartMinute()) + ampm;
}


void displayTime() {
  //basically just some LCD stuff, moving cursor around and displaying strings on it
  alarmShowing = false;
  lcd.clear();
  lcd.setCursor(3, 0); //Set cursor at block 4
  if (hourFormat12() < 10) {
    lcd.print(" " + String(hourFormat12()));
  } else {
    lcd.print(hourFormat12()); // display 12 hour time
  }
  blinkColon(5); //Blink colon at block 5
  lcd.setCursor(6, 0); //Set cursor at block 7
  lcd.print(digitMinutes(minute())); //display minutes at cursor 6/7
  lcd.setCursor(9, 0);
  lcd.print(aMpM());
}




//THIS CODE STOPS STUFF FROM HAPPENING FAST.
/*void blinkColon(int cursorpos) {
  lcd.setCursor(cursorpos, 0);
  lcd.print(":");
  delay(800);
  lcd.setCursor(cursorpos, 0);
  lcd.print(" ");
  delay(800);
  }
*/

void setupTime() {
  //Use method to get time from NTP service/esp8266

}

void requestTime() {
  Blynk.sendInternal("rtc", "sync");
  //if alarm is not showing
  if (!alarmShowing) {
    displayTime();
  }
}

BLYNK_CONNECTED() {
  rtc.begin();
  Blynk.syncAll();
  requestTime();
}

BLYNK_WRITE(V1) {
  TimeInputParam t(param);
  //if alarm is not being displayed
  if (t.hasStartTime() && !alarmShowing) {
    //save the alarmtime as seconds in localAlarm
    localAlarm = param[0].asLong();
    alarmShowing = true;
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print(alarmFormat(t));
    lcd.setCursor(3, 1);
    lcd.print("Alarm Set.");
    //alarm is being displayed
    //start a timer
    delay(4000);
    alarmShowing = false;
    requestTime();
  }

}



void setup() {
  Serial.begin(9600);
  SwSerial.begin(9600);
  Blynk.begin(Serial, auth);
  setSyncInterval(1L);
  //Starts refreshing time/displaying time every second
  pinMode(A0, INPUT);
  lcd.begin(16, 2); //Sets character size
  lcd.clear();
  synctimer.setInterval(1000L, requestTime);
}

void loop() {
  //Basic testing shows above 900 = flashlight
  //Serial.println(analogRead(A0));
  Blynk.run();
  synctimer.run();


}

Have you considered using one of the RTC sketches in the Sketch Builder as the foundation for your RTC processes, rather than your rather unorthodox process you’re currently using?

Pete.

I can troubleshoot a little with the default example, but I got all the time gathering code I used from the example, so I’m not sure if that would make a huge difference.