[SOLVED] When does RTC Widget sync with sketch? How to force it?

I’m using RTC widget to get real time so that the messages that the sketch sends to the terminal widget are time stamped.

Everything works fine when I send messages from a time-triggered function in the sketch.

But it seems that in the setup function the time is not yet synced and it is the default 01/01/1970.
This happens even if I introduce a
Blynk.run();
timer.run();
in the setup()

Is there a way to force the RTC sync so that I can also send time stamped messages from the Setup function?

Can you show entire code ?

Right after rtc.begin(); you can use setSyncInterval(60); in seconds… in this example it syncs every minute.

But RTC might take a few seconds to start (with accurate time), so generally it is not working until the sketch starts looping.

Thanks @Gunner

Is there a way to check if the RTC has started in order to wait until it has?
I’m not so sure that it is a question of time because I have done a test in the Setup doing a loop to wait for minutes and printing the date and it has not synchronized
But it does perfectly when it is out of Setup and into the Loop.
I tried checking the RTC status but in the Setup it seems never to get into sync.

If year != 1970 the RTC has started.

Yes @Costas I did try that one :wink:
but the year doesn’t change if I check it in the setup.
So it seems that the RTC does not start in the setup and it is not a matter of time…

What I get is:
01/01/1970 00h00:05 WeMos1 SetUp. Terminal in V1 IP192.168.1.131 void setup():L122 BlynkDHT22OTA.ino
01/01/1970 00h00:06 WeMos1 Blynk v0.4.7: Device started void setup():L123 BlynkDHT22OTA.ino
01/01/1970 00h00:06 WeMos1 Time Status=0 year==1970 void setup():L126 BlynkDHT22OTA.ino
01/01/1970 00h00:07 WeMos1 Time Status=0 year==1970 void setup():L126 BlynkDHT22OTA.ino
01/01/1970 00h00:07 WeMos1 Time Status=0 year==1970 void setup():L126 BlynkDHT22OTA.ino

and 10 minutes later…

01/01/1970 00h10:03 WeMos1 Time Status=0 year==1970 void setup():L126 BlynkDHT22OTA.ino
01/01/1970 00h10:03 WeMos1 Time Status=0 year==1970 void setup():L126 BlynkDHT22OTA.ino
01/01/1970 00h10:04 WeMos1 Time Status=0 year==1970 void setup():L126 BlynkDHT22OTA.ino

With this setup code:

void setup()
{
  
  Serial.begin(9600);             // Debug console
  Blynk.begin(AUTH, ssid, pass);  // Connect with Blynk server
  rtc.begin();                    // Begin synchronizing time

  timer.setInterval(1*20*1000L, sendSensor);     // Setup a function to be called every xx millisecond 

  Blynk.run();                    // Try to initialize RTC
  timer.run();                    // Try to initialize RTC

  DEBUG_PRINTJBB("SetUp. Terminal in V"+String(TERMINALPIN)+" IP"+WiFi.localIP().toString());    
  DEBUG_PRINTJBB("Blynk v" BLYNK_VERSION ": Device started");  					// This will print Blynk Software version connected to Blynk Server

  while(year()==1970){  
    DEBUG_PRINTJBB("Time Status="+String(timeStatus())+ " year=="+String(year()));     // Has the RTC started?
  }
  
  dht.begin();      // Begin reading temperature & humidity

  ArduinoOTA.setPassword((const char *)""); //Clave para la conexión OTA
  ArduinoOTA.begin(); //Arranca OTA (Over the Air) update is the process of loading the firmware to ESP module using Wi-Fi connection 

  //wdt_enable(WDTO_8S); //Watchdog Timer 8 segundos // options: WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S
  DEBUG_PRINTJBB("Start Loop");
 }

Whereas if I take the while(year()==1970) out of the setup code the RTC starts in the very first call to the sendsensor function, in only 20 seconds:
01/01/1970 00h00:05 WeMos1 SetUp. Terminal in V1 IP192.168.1.131 void setup():L122 BlynkDHT22OTA.ino
01/01/1970 00h00:05 WeMos1 Blynk v0.4.7: Device started void setup():L123 BlynkDHT22OTA.ino
01/01/1970 00h00:06 WeMos1 Start Loop void setup():L135 BlynkDHT22OTA.ino
24/04/2017 22h21:29 WeMos1 Time Status3=2 void sendSensor():L166 BlynkDHT22OTA.ino

Any ideas to force the RTC start in the setup so that the debug messages sent from setup function are correctly time-stamped?

@Jbb

'1. Knock up a new project with just the RTC widget sketch and you should find for most systems the time will update immediately. In the old days you had to use setInterval and other tweaks but these days that is almost redundant.

'2. From what you learnt in 1. ensure you put everything in the same sequence in your real project. Declarations and setup() positions the same. Most projects should get the time immediately if you follow the same sequence.

'3. Reasons time doesn’t update immediately are because you haven’t followed the right sequence or you have clogged up setup() with syncAll, too many sequential virtualWrite() or syncVirtual() calls etc.

'4. When Blynkers add the RTC widget it’s normally because they want to do something at timed intervals. One thing you should do is call the 1970 check at say 10 or 20s intervals BUT NOT with a while loop. Use Blynk’s SimpleTimer as while statements should generally be avoided.

OK, RTC does sync in the Setup really fast just by calling Blynk.run(); 2 times with a simple code as:

#include <BlynkSimpleEsp8266.h>   // Para conectar con la App Blynk
#include <TimeLib.h>              // Funciones para formatear fechas y horas
#include <WidgetRTC.h>            // Leer el tiempo de Internet en Blynk

char ssid[] = "xxxxxxxxx";        // Your WiFi credentials. 
char pass[] = "xxxxxxxxx";       // Set password to "" for open networks.
char auth[] = "9f87d6987xxxxxxxx4c868a6387a3";

BlynkTimer timer;               // Para lanzar periodicamente las funciones del Blynk
WidgetRTC rtc;                  // Para leer el reloj de tiempo real

void setup() {
  Serial.begin(9600);             // Debug console
  Blynk.begin(auth, ssid, pass);  // Connect with Blynk server
  rtc.begin();                    // Begin synchronizing time
  
  Serial.println(dateString()+" "+timeString()+" in setup 0. RTC not started");
  
  timer.setInterval(1*1000L, debug);     // Setup a function to be called every xx millisecond 

  Blynk.run();
  Serial.println(dateString()+" "+timeString()+" in setup 1. RTC not started");
  Blynk.run();
  Serial.println(dateString()+" "+timeString()+" in setup 2. RTC already started");
  Blynk.run();
  Serial.println(dateString()+" "+timeString()+" in setup 3");
}

void loop() {
  Serial.println(dateString()+" "+timeString()+" in loop begin");
  Blynk.run();
  timer.run();
  Serial.println(dateString()+" "+timeString()+" in loop end");
}

void debug()
{
  Serial.println(dateString()+" "+timeString());
}

String timeString()
{
  char c[20];        // long enough to hold complete string
  sprintf(c, "%02dh%02d:%02d",hour(),minute(),second()); 
  String currentTime= String(c); 
  return currentTime;
}

String dateString()
{
  char c[20];        // long enough to hold complete string
  sprintf(c, "%02d/%02d/%4d",day(),month(),year()); 
  String currentDate= String(c); 
  return currentDate;
}

I get:
¤ÀNX¸þ,MHŒ0¤xVý01/01/1970 00h00:05 in setup 0. RTC not started
01/01/1970 00h00:05 in setup 1. RTC not started
25/04/2017 22h47:53 in setup 2. RTC already started
25/04/2017 22h47:53 in setup 3
25/04/2017 22h47:53 in loop begin
25/04/2017 22h47:53 in loop end

I will now try to go step by step to see why this does not happen in my complete code. Thanks.

@Jbb if you change setup() and loop() as indicated below how long does it take for debug() to give the correct time?

void setup() {
  Serial.begin(9600);             // Debug console
  Blynk.begin(auth, ssid, pass);  // Connect with Blynk server
  rtc.begin();                    // Begin synchronizing time
  
  //Serial.println(dateString()+" "+timeString()+" in setup 0. RTC not started");
  
  timer.setInterval(1*1000L, debug);     // Setup a function to be called every xx millisecond 

  //Blynk.run();
  //Serial.println(dateString()+" "+timeString()+" in setup 1. RTC not started");
  //Blynk.run();
  //Serial.println(dateString()+" "+timeString()+" in setup 2. RTC already started");
  //Blynk.run();
  //Serial.println(dateString()+" "+timeString()+" in setup 3");
}

void loop() {
  //Serial.println(dateString()+" "+timeString()+" in loop begin");
  Blynk.run();
  timer.run();
  //Serial.println(dateString()+" "+timeString()+" in loop end");
} 

@Costas Less than 1 second. In the first call it is already started. It is consistent, I have repeated it 3 times:

¶HA=FäBäMÐXÐþÿ25/04/2017 23h24:49
25/04/2017 23h24:50
25/04/2017 23h24:51

And surprisingly, even if I set the timer to 1 milisecond, the RTC seems to start from the first call:

  timer.setInterval(1L, debug);     // Setup a function to be called every xx millisecond 

I don’t understand then why in my complete code it does not start…

As I thought, immediate without any tweaking.

I believe Blynk’s version of SimpleTimer is specified for > 10ms so I wouldn’t go down to 1ms.

There’s no reason you can’t call dht.begin before the Blynk connection. In fact I would always call it first.
Never seen Blynk.run() and timer.run() in setup(), remove them. As stated previously remove the while(year() == 1970) call.

Then just comment out other items of setup() until you find what is stopping the RTC sync.

I have been following this topic, but honestly and still unsure of why you are even having an issue in the first place.

In every sketch I have made, all I really needed in the setup was

Blynk.begin(auth, etc);
rtc.begin();  // immediately following Blynk.Begin()

And it just works… if you are having issue where your code seems to run quicker than the RTC syncs, why not just simply delay for a short moment in the setup before continuing on? (NOTE, since this delay is right after Blynk.begin() it could cause connection issues, but if it is only called once and is no more than 1 second, it should be OK)

Blynk.begin(auth, etc);
rtc.begin();
delay(1000);  // give RTC a second to sync up

With my complete code I still need some tweaking.
As recommended by @Costas I have moved dht.begin before Blynk connection, of course removed the while loop and… I don’t get the RTC started in the setup if I don’t call Blynk.run() at least 4 times.
The RTC is started after some loops if I don’t call Blynk.run() any time in the setup.

@Gunner Even though the 4 Blynk.run() calls take less than 2 millis in being executed, substituting them by a delay(1000) or even a delay(5000) does not help in getting the RTC started… and the clear recommendation is not to use delay with Blynk.

It seems to me that it is not a matter of time or delays, but a matter of calling Blynk.run() some times.

So I get the intended result of having the RTC started in the setup in order to be able to time-stamp messages sent from the setup by calling Blynk.run in the setup several times… but I don’t understand the rationale behind it.

My code:

void setup()
{ 
  Serial.begin(9600);             // Debug console
  dht.begin();                    // Begin reading temperature & humidity
  Blynk.begin(AUTH, ssid, pass);  // Connect with Blynk server
  rtc.begin();                    // Begin synchronizing time
  ArduinoOTA.setPassword((const char *)""); //Clave para la conexión OTA
  ArduinoOTA.begin(); //Arranca OTA (Over the Air) update is the process of loading the firmware to ESP module using Wi-Fi connection 

//  timer.setInterval(1000L, debug);     // Setup a function to be called every xx millisecond 
  timer.setInterval(1*10*1000L, sendSensor);     // Setup a function to be called every xx millisecond 

  Serial.println();
  Serial.println(millis());
  Blynk.run();                    // Try to initialize RTC
  Blynk.run();                    // Try to initialize RTC
  Blynk.run();                    // Try to initialize RTC
  Blynk.run();                    // Try to initialize RTC
  Serial.println(millis());
//  delay(1000);
  Serial.println(dateString()+" "+timeString()+" in setup 1. ");

  //wdt_enable(WDTO_8S); //Watchdog Timer 8 segundos // options: WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S
  DEBUG_PRINTJBB("SetUp. Terminal in V"+String(TERMINALPIN)+" IP"+WiFi.localIP().toString());    
  DEBUG_PRINTJBB("Blynk v" BLYNK_VERSION ": Device started");                                 // This will print Blynk Software version connected to Blynk Server
  DEBUG_PRINTJBB("Start Loop");
 }

Looks like you are correct :+1:

Without specifying a different time source rtc.begin() will get its time sync via the Blynk Server, so that is why it needs to happen during a Blynk.run() cycle.

Since not too many people seem to want the time during the setup phase, I guess it hasn’t been an issue before :wink:

So unless you want to use a different time source, via setSyncProvider(provider); // set the external time provider, your workaround works, so I guess we will call this solved.

Yes, thanks @Gunner, finally I have changed to setSyncProvider(getNtpTime); as I get more consistent results in the setup that with the RTC Widget.

I read lots of messages about how to synchronize RTC.
I tried to add: setSyncProvider (provider); but ‘provider’ was not declared in this scope

I think you would be better starting your own thread and post your code.

Did you declare ‘provider’ in your code?