Skip to content

Instantly share code, notes, and snippets.

@mercdev
Created January 25, 2018 02:52
Show Gist options
  • Save mercdev/f0fea967a82fb87e92a425c5f12580af to your computer and use it in GitHub Desktop.
Save mercdev/f0fea967a82fb87e92a425c5f12580af to your computer and use it in GitHub Desktop.
Using Blynk with WeMos D1 R2 and RTC
#define BLYNK_PRINT Serial
// Blynk app
#include <BlynkSimpleEsp8266.h>
#include <RTClib.h>
#include <WidgetRTC.h>
// Non Blynk specific, local files
#include <WiFiUdp.h>
#include "NTP.h"
// device hardware specific
#include <PCF85063TP.h>
PCD85063TP RTC;
// WiFi settings
char ssid[] = "xxx";
char pass[] = "xxx";
// Blynk Settings
char auth[] = "xxxxxx";
// Blynk Widgets
WidgetTerminal terminalWidget(V8);
WidgetRTC rtcWidget; // requires RTC widget in app
BlynkTimer blynkTimer; // SimpleTimer replacement
// Sketch variables
boolean connectInProgress;
boolean syncBlynkTime = true;
boolean ntpStarted = false;
int blynkTimerId;
int connectTimerId;
//
// This is called for all virtual pins that do not have BLYNK_WRITE handler
//
BLYNK_WRITE_DEFAULT()
{
terminalWidget.print("BLYNK_WRITE for pin V");
terminalWidget.print(request.pin);
terminalWidget.println(" not defined.");
terminalWidget.println("Values: ");
for (auto i = param.begin(); i < param.end(); ++i)
{
terminalWidget.print("* ");
terminalWidget.println(i.asString());
}
terminalWidget.flush();
}
//
// This is called for all virtual pins that do not have BLYNK_READ handler
//
BLYNK_READ_DEFAULT()
{
terminalWidget.print("BLYNK_READ for pin V");
terminalWidget.print(request.pin);
terminalWidget.println(" not defined.");
terminalWidget.flush();
}
//
// This is called when Blynk has successfully connected
//
BLYNK_CONNECTED()
{
syncBlynkTime = true; // (re)set time to synchronize with Blynk by default
rtcWidget.begin(); // sets setSyncProvider internally and immediately call Blynk.sendInternal("rtc", "sync");
setSyncInterval(5*60); // subsequent time sync interval in seconds (5 minutes), once that interval has elapsed, time will set itself to timeNeedsSync
// cancel NTP time synchronization
if (ntpStarted)
{
ntpStop();
ntpStarted = false;
// reset checkBlynkConnection to default/startup interval of 5 minutes
blynkTimer.changeInterval(connectTimerId, 300000L);
blynkTimer.restartTimer(connectTimerId);
}
}
/*
* Blynk feature was postponed until a later release
BLYNK_DISCONNECTED()
{
#ifdef BLYNK_PRINT
Serial.println("[_\\|/_] Blynk Disonnected.");
#endif
}
*/
//
// This is called when Smartphone App is opened
//
BLYNK_APP_CONNECTED()
{
#ifdef BLYNK_PRINT
Serial.println("[_\\|/_] Blynk App Connected.");
#endif
}
//
// This is called when Smartphone App is closed
//
BLYNK_APP_DISCONNECTED()
{
#ifdef BLYNK_PRINT
Serial.println("[_\\|/_] Blynk App Disconnected.");
#endif
}
//
// synchronize the RTC hardware device with our TimeLib provided date/time values
// The time library is synchronized by the Blynk WidgetRTC on connect
// NOTE: most RTC's require a battery in order to oscillate, otherwise time doesn't increment on the hardware
//
void syncRTCHardware()
{
#ifdef BLYNK_PRINT
char currentTime[16];
char currentDate[16];
#endif
if (!Blynk.connected() && syncBlynkTime)
{
#ifdef BLYNK_PRINT
Serial.println("[_\\|/_] Blynk not connected. Changing to NTP Sync");
#endif
syncBlynkTime = false;
ntpStarted = ntpStart(); // starts the udp listener for NTP sync
if (ntpStarted)
{
setSyncProvider(getNtpTime);
setSyncInterval(5*60); // 5 minutes
// change checkBlynkConnection to check every 1 minute
blynkTimer.changeInterval(connectTimerId, 60000L);
blynkTimer.restartTimer(connectTimerId);
}
else
{
#ifdef BLYNK_PRINT
Serial.println("[_\\|/_] NTP start failed.");
#endif
}
}
// get the time library status
// enums: timeNotSet = 0, timeNeedsSync = 1, timeSet = 2
timeStatus_t timestatus = timeStatus();
if (timestatus == 0)
{
#ifdef BLYNK_PRINT
Serial.println("[_\\|/_] TimeLib: not set."); // this is where you get concerned
#endif
// time library has never been set exit the function so we don't overwrite RTC values
return;
}
if (timestatus == 1)
{
// time library needs synchronization, wait for time status to change
// before comparing RTC
#ifdef BLYNK_PRINT
Serial.println("[_\\|/_] TimeLib: needs synchronization.");
#endif
return;
}
if (timestatus == 2)
{
RTC.getTime();
// check RTC values against the synchronized TimeLib value
// TODO: change this to do simple unix epoch comparison, PCF85063TP.h doesn't support this
if ((RTC.year + 2000) != year() || RTC.month != month() || RTC.dayOfMonth != day() || RTC.hour != hour() || RTC.minute != minute() || RTC.second != second())
{
#ifdef BLYNK_PRINT
// display the current values of each
Serial.println("[_\\|/_] TimeLib: RTC not matched. Resynchronizing RTC.");
sprintf(currentDate, "%02d/%02d/%04d", month(), day(), year());
sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
Serial.print("[_\\|/_] TimeLib: ");
Serial.print(currentDate);
Serial.print (" ");
Serial.println(currentTime);
// depending on the RTC library used, the RTC property names could be different
// i.e. RTC.month vs RTC.month()
sprintf(currentDate, "%02d/%02d/%04d", RTC.month, RTC.dayOfMonth, RTC.year);
sprintf(currentTime, "%02d:%02d:%02d", RTC.hour, RTC.minute, RTC.second);
Serial.print("[_\\|/_] RTC Time: ");
Serial.print(currentDate);
Serial.print(" ");
Serial.println(currentTime);
#endif
// set the RTC to TimeLib values here
RTC.stopClock();
RTC.fillByYMD(year(), month(), day());
RTC.fillByHMS(hour(), minute(), second());
RTC.setTime();
RTC.startClock();
return;
}
#ifdef BLYNK_PRINT
Serial.println("[_\\|/_] TimeLib: RTC matches.");
#endif
}
}
//
// checks connection to Blynk server and attempts reconnect if needed
//
void checkBlynkConnection()
{
if (!Blynk.connected() && !connectInProgress)
{
connectInProgress = true;
if(!Blynk.connect())
{
#ifdef BLYNK_PRINT
Serial.println("[_\\|/_] Blynk Connect failed");
#endif
}
else
{
#ifdef BLYNK_PRINT
Serial.println("[_\\|/_] Blynk Connected");
#endif
}
connectInProgress = false; // either it connected or timed out
}
}
int freeRam()
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
void checkMemory()
{
#ifdef BLYNK_PRINT
Serial.print("[_\\|/_] SRAM: ");
Serial.println(freeRam());
#endif
}
//
// all initialization and timer setups go here
//
void setup()
{
Serial.begin(115200);
RTC.begin();
// timer tasks
blynkTimerId = blynkTimer.setInterval(150000L, syncRTCHardware); // synchronize the RTC every 2.5 minutes
connectTimerId = blynkTimer.setInterval(300000L, checkBlynkConnection); // check Blynk connection every 5 minutes
// non-blocking Blynk setup
Blynk.config(auth, BLYNK_DEFAULT_DOMAIN, BLYNK_DEFAULT_PORT);
Blynk.disconnect(); // skip connecting to the Blynk server until checkBlynkConnection timer fires
// this allows setup() to continue/exit and the main loop() to begin without blocking
blynkTimer.setTimeout(2000L, checkBlynkConnection); // in 2 seconds, do initial connection check
blynkTimer.setTimeout(10000L, syncRTCHardware); // in 10 seconds, do initial time check
blynkTimer.setTimeout(3000L, checkMemory);
}
// Main processing loop.
void loop()
{
blynkTimer.run();
// only attempt Blynk-related functions when connected to Blynk
if (Blynk.connected())
{
Blynk.run();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment