@Costas @Gunner @Dmitriy
Dear friends,
I am in a difficult situation and I don’t know what else to check. I have tried different hardware, AUTH code and much more without good result. I have slimmed down my projects sketch, in order to eliminate the dependencies etc to minimum. Still the problem appeared in the quoted sketch bellow. Just a few notes:
- I upload the sketch ( OTA ) and I watch the writings in the terminal widget, that is enough.
- You need to observe these writings ( to the terminal widget ) for an hour to get a good conclusion, most of the time the first 15 minutes after booting the hardware are without ESP free heap loose but you will see after…
- In my case the deductions are 80 byte each time or rare, multiplications of 80 bytes ( e.x. 160, 240 etc ).
- Please see my screen shot
Please share your findings with me !.
Thanks and Best Regards,
Mike Kranidis
#define Project " ESP8266 Free Heap Leakage "
#define WellcomeLine2 "Ver. d2.1"
#define ChangedDate " / 05/06/17"
#define Author "Mike Kranidis"
/// Blynk related setup ///
/// Blynk color definition
/// http://www.rapidtables.com/web/color/RGB_Color.htm ///
#define GREEN "#23C48E"
#define BLUE "#04C0F8"
#define YELLOW "#ED9D00"
#define RED "#D3435C"
#define DARK_BLUE "#5F7CD8"
#define BLACK "#000000"
#define WHITE "#FFFFFF"
/// V1 RUN? LED widget flashing once per second to give the running impression on V1 ///
/// V4 Function button running diagnostics on V14 V4 ///
/// V7 virtual LCD widget, (switch to ADVANCED mode) V7 ///
/// 16 SW1-LED1 (of Board) switch on 16 ///
/// V12 Value Display widget on V12 currentTime V12 ///
/// V13 Value Display widget on V13 currentDate V13 ///
/// V14 WidgetTerminal terminal V14 ///
/// Relay 1: gp12 <--> virtual switch V16, Relay 2: gp13 <--> virtual switch V17 ///
/// HARDWARE_LED gp 16
#define HARDWARE_LED 16
/// RL1: gp12, RL2: gp13 ///
#define RL1 12
#define RL2 13
#include <ESP8266WiFi.h>
/// OTA dependencies ///
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
/// for WEB based file OTA update we need the following ///
#include <ESP8266WebServer.h> //Local WebServer used to serve the configuration portal
#include <ESP8266HTTPUpdateServer.h>
const char* host = "ELIAS2"; // will be "ELIAS2.local/update" in web browser
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
/// WiFiManager dependencies ///
#include <DNSServer.h> //Local DNS Server used for redirecting all requests to the configuration portal
/// it is used above /// #include <ESP8266WebServer.h> //Local WebServer used to serve the configuration portal
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager WiFi Configuration Magic
/// blynk dependencies ///
/// #define BLYNK_PRINT Serial // Comment this out to disable prints and save space
/// it is used above /// #include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
/// NTP dependencies and declarations///
#include <TimeLib.h>
/// it is used above /// #include <ESP8266WiFi.h>
/// it is used above /// #include <WiFiUdp.h>
// NTP Servers:
static const char ntpServerName[] = "gr.pool.ntp.org";
const int timeZone = 3; /// Greek European Time but need to take into consideration the two changes in a year...
WiFiUDP Udp;
unsigned int localPort = 8888; // local port to listen for UDP packets
///time_t getNtpTime();
// Use Virtual pin 5 for uptime display
#define PIN_UPTIME V5
/// global vartiable for looping counting ///
int loopCount = 0; /// print after some interation this message Type ? or help to get help...
int loopCount1 = 0; /// Send date to the App after 10 times of time ///
char auth[] = " AUTH CODE HERE "; /// PLEASE USE BLYNK PUBLIC SERVER FOR TESTING...
/// due to WiFiManager framework the bellow credentials are not needed anymore but still can be used... ///
const char* ssid = "WIFI SSID";
const char* password = "PASSWORD";
boolean ledBlink = true;
/// switch value to control if the terminal printing will be on or not if false ///
boolean termPrint = false;
String relaySelection; /// String used in manual relay activation in the form onrl1,30 or onrl2,33 it keeps onrl1 or onrl2
int duration; /// see above it keeps ex. 30 or 33 etc
unsigned long manualEndTime; /// this actually is keeping the RLn-OFF time in full unix time (i.e. manualEndTime = now()+duration);
unsigned long integer2time = 0;
int manualActiveRLTimer, blinkLedWidgetTimer, sendTemperatureHumidityTimer, clockDisplayTimer, timeCheckerTimer, reconnectBlynkTimer;
char* WeekDays[8]={"Not", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; /// TimeLib format 1 = Sun, 2 = Mon ... ///
/// for WEB based file OTA update ///
boolean WEB_OTA = false;
/// Blynk Diconnection Counter ///
unsigned short int BDC = 0;
/// string that holds the system uptime in the format of DD hh:mm:ss
char Stringuptime[25];
/// boolean that controls via true / false the Blynk.syncAll() execution -- to be done only at the fists / start time ///
boolean isFirstConnect = true;
/// character arrays that keep formated current Date and Time ///
char currentDateTime[24];
/// ESP Free Heap global variables ///
int keepESPgetFreeHeapOld=0, keepESPgetFreeHeap=0;
WidgetLED led1(V1);
WidgetLCD lcd(V7);
/// SimpleTimer timer;
BlynkTimer timer;
/// start of WiFiManager Global Start here... ////
WiFiManager wifiManager;
// Attach virtual serial terminal to Virtual Pin V14
WidgetTerminal terminal(V14);
/// START of temp./humd. report function be called every 30 seconds. Here also Adj the timeZone calling the timeZoneAdj() ///
/// also has the "printing wifi signal strength and Date Time to Terminal Widget laber ///
void sendTemperatureHumidity()
{
sprintf(currentDateTime, "%02d/%02d %02d:%02d:%02d",day(), month(), hour(), minute(), second());
keepESPgetFreeHeap = ESP.getFreeHeap();
if(keepESPgetFreeHeapOld != keepESPgetFreeHeap) {
terminal.printf("\n%s F.H.=%d M=%d",currentDateTime, keepESPgetFreeHeap, (keepESPgetFreeHeap - keepESPgetFreeHeapOld));
keepESPgetFreeHeapOld = keepESPgetFreeHeap;
terminal.flush();
}
if(loopCount <= 10){
loopCount++;
} else {
loopCount = 0;
if(termPrint) {
terminal.println("\nType ? or help, to get help hints...\n");
///terminal.println();
terminal.flush();
}
}
}
/// END of temp./humd. report function be called every 30 seconds. Here also Adj the timeZone calling the timeZoneAdj() ///
/// START of blink LED function be called every second by SimpleTimer ///
/// This blink LED function be called every second also check for BDC counter. If BDC >= 550 then do restart ///
void blinkLedWidget()
{
if (led1.getValue()) {
led1.off();
///BLYNK_LOG("LED1: off");
} else {
if(WiFi.RSSI() < -83){
Blynk.setProperty(V1, "color", RED);
}
else if(WiFi.RSSI() > -57){
Blynk.setProperty(V1, "color", GREEN);
}
else{
Blynk.setProperty(V1, "color", YELLOW);
}
led1.on();
///BLYNK_LOG("LED1: on");
}
if (BDC >= 250) { /// do esp restart
BDC = 0;
Blynk.virtualWrite(V25, BDC);
yield(); yield(); delay(500);
ESP.restart();
}
/// put the routine here to blink HARDWARE LED gp 16 each second ///
if (ledBlink) {
digitalWrite(HARDWARE_LED, !(digitalRead(HARDWARE_LED)));
}
}
/// END of blink LED function be called every second by SimpleTimer ///
/// simpletimer function, check every 60 seconds the blynk connection and if necessary do connect ///
void reconnectBlynk() {
if (!Blynk.connected()) {
BDC++;
if(Blynk.connect()) {
BLYNK_LOG("Reconnected");
Blynk.run();
} else {
BLYNK_LOG("Not reconnected");
}
}
}
/// START of Digital clock display SimpleTimer timer function of the time updating every 2 seconds ///
void clockDisplay() /// new improved version using sprintf the old exist in V2.0
{
// You can call hour(), minute(), ... at any time
// Please see Time library examples for details
char currentTime[10], currentDate[12];
sprintf(currentTime, "%02d:%02d:%02d",hour(), minute(), second());
/// String currentDate = String(d) + "/" + M + "/" + year();
sprintf(currentDate, "%02d/%02d/%d",day(), month(), year());
// Send time to the App
Blynk.virtualWrite(V12, currentTime);
// Send date to the App after 10 times of time
if(loopCount1 <= 10) {
loopCount1++;
} else {
loopCount1=0;
Blynk.virtualWrite(V13, currentDate);
}
}
/// END of Digital clock display SimpleTimer timer function of the time updating every 2 seconds ///
/// START of manualActiveRL function executed each 2 seconds ///
void manualActiveRL()
{
/// terminal.printf("\ndbg manualActiveRL enter routine\n"); terminal.flush();
if(now() > manualEndTime) { /// it is the time to switch off RL1 or RL2 properly and then disable the manualActiveRLTimer ///
if(relaySelection == "onrl1") { /// RL1 de-activation ///
/// terminal.print("\ndbg manualActiveRL for: "); terminal.println(relaySelection); terminal.flush();
digitalWrite(RL1,LOW); /// RL1 de-activation ///
Blynk.virtualWrite(V16, LOW);
Blynk.setProperty(V16, "color", GREEN);
} else if(relaySelection == "onrl2") { /// RL2 de-activation ///
/// terminal.print("\ndbg manualActiveRL for: "); terminal.println(relaySelection); terminal.flush();
digitalWrite(RL2,LOW); /// RL2 de-activation ///
Blynk.virtualWrite(V17, LOW);
Blynk.setProperty(V17, "color", GREEN);
}
/// terminal.printf("\ndbg manualActiveRL timer dis. now\n"); terminal.flush();
timer.disable(manualActiveRLTimer); /// if time manualEndTime has expired close the timer as: timer.disable(manualActiveRLTimer);
}
}
/// END of manualActiveRL function executed each 2 seconds ///
/// START of int2Time convert integer to time format ///
void int2Time(time_t duration)
{
if(duration >= 86400){ /// 86400
terminal.printf("%dD:", (duration / 86400)); /// how many days ? ///
duration = duration % 86400;
}
if(duration >= 3600){ /// 3600
terminal.printf("%02dH:",(duration / 3600)); /// how many hours ? ///
duration = duration % 3600;
}
if(duration >= 60){ /// 60
terminal.printf("%02dM:",(duration / 60)); /// how many minutes ? ///
duration = duration % 60;
}
terminal.printf("%02dS",(duration)); /// how many seconds ? ///
terminal.flush();
}
/// END of int2Time convert integer to time format ///
/// START of int2uptime convert integer to string for system uptime format dd hh:mm:ss ///
void int2uptime (time_t uptimeduration)
{
unsigned int days, hours, minutes, seconds;
if(uptimeduration >= 86400){
days = uptimeduration / 86400;
uptimeduration = uptimeduration % 86400;
} else days=0;
if(uptimeduration >= 3600){
hours = uptimeduration / 3600;
uptimeduration = uptimeduration % 3600;
} else hours=0;
if(uptimeduration >= 60){
minutes = uptimeduration / 60;
uptimeduration = uptimeduration % 60;
} else minutes =0;
seconds = uptimeduration;
sprintf(Stringuptime, "%02dD %02d:%02d:%02d",days,hours,minutes,seconds);
}
/// END of int2uptime convert integer to string for system uptime format dd hh:mm:ss ///
/// START of V14 terminal processing function ///
// You can send commands from Terminal to your hardware. Just use
// the same Virtual Pin as your Terminal Widget
BLYNK_WRITE(V14)
{
/// take "commands" from the terminal and acting accordingly ///
/// https://www.arduino.cc/en/Tutorial/StringSubstring ///
/// (stringOne.equalsIgnoreCase(stringTwo)) ///
/// stringOne.trim(); ///
/// int strgLenght = param.getLength(); /// get the string lenght ///
String getString = param.asStr(); /// get the string ///
getString.trim(); /// cut off the blank spece(s) at the end of the string ///
if (getString.equalsIgnoreCase("timer1")) {
///timer1PrintOut();
return;
} else if (getString.equalsIgnoreCase("timer2")) {
///timer2PrintOut();
return;
} else if (getString.equalsIgnoreCase("timer3")) {
///timer3PrintOut();
return;
} else if (getString.equalsIgnoreCase("timer4")) {
///timer4PrintOut();
return;
} else if (getString.startsWith("cnv")) {
integer2time = (getString.substring(3)).toInt();
int2Time(integer2time);
return;
} else if ( getString.startsWith("onrl1") || getString.startsWith("onrl2") ) { /// format onrl1,30 or onrl2,34 ...
int firstCommaIndex = getString.indexOf(',');
relaySelection = getString.substring(0, firstCommaIndex);
String durationToOn = getString.substring(firstCommaIndex+1);
duration = durationToOn.toInt();
///terminal.printf("duration(in seconds)=%d\n", duration);
///terminal.flush();
/// make a now() start with now()+duration stop at Timer1 if RL1 or Timer2 if RL2 ... ///
manualEndTime = now()+ (duration - 1); /// this is the manualEndTime that manualActiveRLTimer will check each 2 seconds for RLn-OFF
/// this need other commant from time library ... /// int2Time(manualEndTime);
/// activate rl1 or rl2 and then call manualActiveRLTimer to take care the RL-OFF state
///terminal.printf("The Relay:%s, Will be ON for %s seconds\n",relaySelection, durationToOn);
terminal.println(); terminal.print(relaySelection+" Duration=");
int2Time(duration);
terminal.printf(" end @ %02d:%02d:%02d \n",hour(manualEndTime), minute(manualEndTime), second(manualEndTime));
terminal.flush();
if(relaySelection == "onrl1") { /// RL1 activation ///
digitalWrite(RL1,HIGH);
Blynk.virtualWrite(V16, HIGH);
Blynk.setProperty(V16, "color", RED);
} else if(relaySelection == "onrl2") { /// RL2 activation ///
digitalWrite(RL2,HIGH);
Blynk.virtualWrite(V17, HIGH);
Blynk.setProperty(V17, "color", RED);
}
timer.enable(manualActiveRLTimer);
return;
} else if (getString.equalsIgnoreCase("BDC")) {
Blynk.virtualWrite(V25, BDC);
terminal.printf("\ntime:%02d:%02d:%02d / Disconnections=%03d\n", hour(), minute(), second(), BDC ); terminal.flush();
return;
} else if (getString.equalsIgnoreCase("BDC0")) {
BDC=0;
Blynk.virtualWrite(V25, BDC);
terminal.printf("\ntime:%02d:%02d:%02d / Disconnections=%03d\n", hour(), minute(), second(), BDC ); terminal.flush();
return;
} else if (getString.equalsIgnoreCase("Clear") || getString.equalsIgnoreCase("Cls")) {
clearScreen();
return;
} else if (getString.equalsIgnoreCase("Startled")) {
terminal.println("You said: startled , OK!");
ledBlink = true;
terminal.flush();
return;
} else if (getString.equalsIgnoreCase("Stopled")) {
terminal.println("You said: stopled , OK!");
ledBlink = false;
terminal.flush();
digitalWrite(HARDWARE_LED, 0); /// switch off the internal led /// turn off the LED. It is the default state... ///
return;
} else if (getString.equalsIgnoreCase("Diags")) {
///terminal.println("You said: Diags , OK!");
diagnostics();
return;
} else if (getString.equalsIgnoreCase("restart")) {
terminal.println("OK I do restart !");
terminal.flush();
yield(); yield(); delay(500);
ESP.restart();
} else if (getString.equalsIgnoreCase("?") || getString.equalsIgnoreCase("help")) {
terminal.println("The regognised commands are: ");
terminal.println("onrl1,nn, onrl2,nn, timer1(-4), BDC, clear/cls, startled, stopled, diags, restart, cnv nnnn");
terminal.flush();
return;
} else {
// Send it back
terminal.print("You said:");
terminal.write(param.getBuffer(), param.getLength());
terminal.println();
terminal.println("Type ? or help to get help...");
terminal.println();
}
// Ensure everything is sent
terminal.flush();
}
/// END of V14 terminal processing function ///
/// START of clearScreen function ///
void clearScreen() /// LCD & terinal clear ///
{
lcd.clear();
for(int i=1; i<8; i++) {
terminal.println();
}
terminal.flush();
}
/// END of crearScreen function ///
/// START of diagnostics function ///
void diagnostics()
{
/// diagnostics print here ///
/// termPrint=false; /// shall I implement in this sketch ???
///terminal.printf("\nBlynk %s / %s / %s\n%s\n", BLYNK_VERSION, Author, WellcomeLine2, Project);
terminal.printf("\nBlynk %s / %s / %s\n%s%s\n", BLYNK_VERSION, Author, WellcomeLine2, Project, ChangedDate);
/// terminal.println(WellcomeLine2);
// terminal.println(Version);
/// terminal.println(Project);
terminal.print("Last RST?: ");
terminal.println (ESP.getResetReason());
/// not working /// terminal.printf("Last RST?: %s \n", ESP.getResetReason());
String chipID = String(ESP.getChipId(), HEX);
char charChipID[10];
chipID.toCharArray(charChipID, sizeof(charChipID));
terminal.printf("ESP ID: %d / in HEX: %s\n", ESP.getChipId(),charChipID);
terminal.printf("ESP free heap=%d, time:%02d:%02d:%02d\n", ESP.getFreeHeap(), hour(), minute(), second() );
terminal.printf("WiFi Signal:%ddBm / IP:", WiFi.RSSI());
terminal.println(WiFi.localIP());
///terminal.print("ESP flash chip frequency? : ");
///terminal.println(ESP.getFlashChipSpeed()); /// returns the flash chip frequency, in Hz.
// Ensure everything is sent
terminal.flush();
}
/// END of diagnostics function ///
/// START of press V4 function button running diagnostics @ V14 ///
BLYNK_WRITE(V4)
{
if (param.asInt()) {
diagnostics();
}
}
/// END of press V4 function button running diagnostics @ V14 ///
/// ===> START OF SETUP <=== ///
void setup() {
Serial.begin(115200);
Serial.println("Booting...");
/// on board LED ///
pinMode(HARDWARE_LED, OUTPUT);
digitalWrite(HARDWARE_LED, HIGH); /// initializing internal WeMos led to off (HIGH => OFF) ///
/// Relay 1 @ pin 12 ///
pinMode(RL1, OUTPUT);
/// Relay 2 @ pin 13 ///
pinMode(RL2, OUTPUT);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
//WiFiManager
wifiManager.autoConnect("ELIAS2-AP", "2104934954");
wifiManager.setConfigPortalTimeout(360); /// Configuration Portal Timeout
Serial.println("connected...yesss! :)");
ArduinoOTA.onStart([]() {
Serial.println("Start OTA");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd OTA");
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready OTA");
Serial.print("IP address OTA: ");
Serial.println(WiFi.localIP());
/// for WEB based file OTA update we need the following ///
MDNS.begin(host);
httpUpdater.setup(&httpServer);
httpServer.begin();
MDNS.addService("http", "tcp", 80);
String ipaddress = WiFi.localIP().toString();
String chipID = String(ESP.getChipId(), HEX);
char charChipID[10];
chipID.toCharArray(charChipID, sizeof(charChipID));
char charipaddress[16];
ipaddress.toCharArray(charipaddress, sizeof(charipaddress));
Serial.printf("Now open http://%s.local/update in your browser or \n", host);
Serial.printf("http://%s/update or http://%s.lan/update if you prefer.\n", charipaddress, charChipID);
/// NTP related ///
Serial.println("Starting UDP");
Udp.begin(localPort);
Serial.print("Local port: ");
Serial.println(Udp.localPort());
Serial.println("waiting for sync");
setSyncProvider(getNtpTime); /// call NTP sync now, here !!! ///
unsigned long maxMillis=millis() + 10000;
while ((timeStatus() == timeNotSet) && ( millis() <= maxMillis)) {
yield();
delay(100);
}
setSyncProvider(getNtpTime); /// this acting as "NTP syncNow" !
yield();
delay(200);
yield();
setSyncInterval(1800); /// set sync timer at 1800 seconds = 30 minutes
Blynk.config(auth);
while ((Blynk.connect() == false) && ( millis() <= maxMillis)) {
// Wait until connected or 10 seconds passed without connection ( maxMillis )
yield();
delay(200);
}
/// START of SimpleTimer timer Functions ///
/// This blink LED function be called every second also check for BDC counter. If BDC == 550
/// think about this... blinkLedWidgetTimer = timer.setInterval(1000L, blinkLedWidget);
timer.setInterval(1000L, blinkLedWidget);
/// This temp./humd. report function be called every 30 seconds
/// think about this...
sendTemperatureHumidityTimer = timer.setInterval(30000L, sendTemperatureHumidity);
/// timer.setInterval(30000L, sendTemperatureHumidity);
/// Check each 2 seconds manualActiveRL function for RLn-OFF ///
manualActiveRLTimer = timer.setInterval(2000L, manualActiveRL);
timer.disable(manualActiveRLTimer);
/// Display digital clock every 2 seconds
/// think about this...
clockDisplayTimer = timer.setInterval(2000L, clockDisplay);
/// This timer check each 60 seconds if Blynk is connected and if it is not try to get connected ///
/// think about this...
reconnectBlynkTimer = timer.setInterval(60000L, reconnectBlynk);
/// timer.setInterval(60000L, reconnectBlynk);
/// END of SimpleTimer timer Functions
lcd.clear(); //Use it to clear the LCD Widget
lcd.print(0, 0, Author);
lcd.print(0, 1, WellcomeLine2);
/// lcd.print(13, 1, Version); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
}
/// ===> END OF SETUP <=== ///
/// START routine for reading V16 (Relay 1 Virtual Button) and drive / change gp 12 accordingly ///
BLYNK_WRITE(V16)
{
if (param.asInt()) {
digitalWrite(RL1,HIGH);
Blynk.setProperty(V16, "color", RED);
}
else {
digitalWrite(RL1,LOW);
Blynk.setProperty(V16, "color", GREEN);
}
}
/// END routine for reading V16 (Relay 1 Virtual Button) and drive / change gp 12 accordingly ///
/// START routine for reading V17 (Relay 2 Virtual Button) and drive / change gp 13 accordingly ///
BLYNK_WRITE(V17)
{
if (param.asInt()) {
digitalWrite(RL2,HIGH);
Blynk.setProperty(V17, "color", RED);
}
else {
digitalWrite(RL2,LOW);
Blynk.setProperty(V17, "color", GREEN);
}
}
/// END routine for reading V17 (Relay 2 Virtual Button) and drive / change gp13 accordingly ///
// Every time we connect to the cloud synchronize some of the values from Widgets...
// This function will run every time Blynk connection is established
BLYNK_CONNECTED() {
/// PUT HERE THE LOGIC OF CALENDAR NOTE ///
/// moved from here to more appropriate possition Blynk.connected() ///
BDC++;
Blynk.virtualWrite(V25, BDC);
if(isFirstConnect) {
Blynk.syncAll();
isFirstConnect = false;
}
}
/// ===> START OF LOOP <=== ///
void loop() {
/// to take care dismissed the WDT reset... ///
/// see if this is a fault... /// ESP.wdtFeed();
ArduinoOTA.handle();
if(WEB_OTA) {
/// shall I stop timers and Blynk related in order to ensure succesful WEB OTA ??? ///
httpServer.handleClient();
} /// We need this in order to do WEB file OTA update ///
/// trick to check if connected first (instead of just Blynk.run();) from Costas ///
///if (Blynk.connected()) { // to ensure that Blynk.run() function is only called if we are still connected to the server
///Blynk.run();
///}
Blynk.run();
timer.run();
}
/// ===> END OF LOOP <=== ///
/*-------- START of NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
time_t getNtpTime()
{
IPAddress ntpServerIP; // NTP server's ip address
while (Udp.parsePacket() > 0) ; // discard any previously received packets
Serial.println("Transmit NTP Request");
// get a random server from the pool
WiFi.hostByName(ntpServerName, ntpServerIP);
Serial.print("ntp Server Name: ");
Serial.print(ntpServerName);
Serial.print(" IP: ");
Serial.println(ntpServerIP);
sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Serial.println("Receive NTP Response");
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serial.println("No NTP Response :-(");
return 0; // return 0 if unable to get the time
}
// send an NTP request to the time server at the given address
/// void sendNTPpacket(IPAddress &address)
void sendNTPpacket(IPAddress &address)
{
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
/*-------- END of NTP code ----------*/