ESP Free Memory Heap leak or something

@Dmitriy @vshymanskyy
Dear Sirs,
I have noticed a very big and strange problem to my Blynk project that is running in ESP8266 hardware.
First of all, it is necessary to report that I am running the latest Blynk library ( 0.4.7 ), in Arduino IDE ( 1.6.9 ), Blynk app ( 2.13.4 ) and Arduino ESP core 2.3.0 @ my two Android phones. I use Blynk public server.
The under problem project has not been changed for the last 15 days ( and tested an even older version much more older exposed the same problem ), it seems that the problems has been started for 4-5 days ago, and all the rest of the equipment are exactly as they were…
I did not exchange the hardware yet, I will do it in the forthcoming days.
What I noticed: the ESP free heap constantly reduced by itself as the time goes by and when reaches very low the ESP8266 resets itself…

With the exception of the hardware problem, ( that I did not check it yet, as I said above ), is the something from Blynk public server or Blynk library that can cause this problem? I can ensure you that my project was running unchanged for weeks without the reported problem. Strange ehh?

Please offer me your point of view.

Thanks and Best Regards,
Mike Kranidis

@mikekgr looks like memory leak was spotted earlier today and is now fixed, should be available in 0.24.5 https://github.com/blynkkk/blynk-server/issues/629#event-1090805389

Blynk itself only uses static/stack memory. Not dynamic - so please check your code or report to ESP Core…

This is another one :slight_smile:, on server side, not hardware side.

1 Like

@Costas @vshymanskyy @Dmitriy
First of all I would like to thank you for your replies.
It is very strange that this problem was exposed to my project as the project was running without any software / hardware change… It is so much strange…

I am thinking the hardware side… I will check it by exchange hardware in the next days and of course I will report the findings here.

Best Regards,
Mike Kranidis

@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:

  1. I upload the sketch ( OTA ) and I watch the writings in the terminal widget, that is enough.
  2. 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…
  3. In my case the deductions are 80 byte each time or rare, multiplications of 80 bytes ( e.x. 160, 240 etc ).
  4. 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 ----------*/


Any helping hand here ???

Please try to help me!
Thanks

Well, I for one can’t even determine what your project is supposed to be doing :confused: let alone duplicate it on my Arduinos :wink:

I do think that troubleshooting something like this might be a bit beyond the scope of this forum, but give it time and keep updating whenever/whatever results from your own attempts, just in case it triggers an idea from someone here.

Dear @Gunner
first of all thanks for the support try.

Well the sketch that I gave above is a slimmed down version of my project running at ESP8266 ( and not Arduino ) doing excess usage of Blynk ( Not necessarily the block you see above ). So I think the subject is 100% Blynk related. To go further, what I discovered, when my project ( even the slimmed down version that you can see above ) leaved running for let say 2-3 days then, the hardware is doing self-reset because no Free Heap left… ! gorgeous eh?
I have made lot of code changes, hardware changes and so forth WITHOUT find any solution. For this reason I asked for your help. What I asked: Please upload this sketch in one of your ESP8266 ( never mind the model just update the #define HARDWARE_LED 16 using your pin) and keep running it for 2-3 hours or more ( better ). Then it is important to report back to me IF you suffered for ESP Free Heap auto reduction without an obvious reason. If you have the same problem then we can see what cause the problem etc etc.
In case that you want the full project, there is not problem to give you, but here in this very slimmed down version we are doing bug hunting and for this reason this sketch does not make sense to you tho…

I hope to explain you better now. Appologize for my English, are not as good as it should…

I am at your disposal for anything more you need regarding this case.

Thanks and Best Regards,
Mike Kranidis

@mikekgr post a QR or url and i’ll run it here.

@Costas
thanks a lot Costas. Do you need the clone project QR Am I right?

Then here is: ( sorry the project has many more widgets etc etc please keep only the necessary as you can see from the sketch ).

To start using it:

  1. Download Blynk App: http://j.mp/blynk_Android or http://j.mp/blynk_iOS
  2. Touch the QR icon and point the camera to the code below or open the link below - http://tinyurl.com/y9rktbvx
  3. Enjoy my app!

Please report back to me your findings.
Thanks a lot

@Costas please pay attention for the marked with ===> widgets

Ok it’s running:

13:09:24 F.H  = 30144 M=30144
13:12:54 F.H. = 29976 M=-168

More to follow later.

@mikekgr which ESP are you running the code on?

http://www.electrodragon.com/product/wifi-iot-relay-board-based-esp8266/

F.H. means Free Heap
M means Memory Change from the last value

You don’t say :slight_smile:

ok ok I know that looking at the code that is very obvious… !

How it is going? You started at 30144 F.H. Now?

It was obvious without looking at the code.

Didn’t think it meant Fire Hydrant and Metro :slight_smile:

It would be easier if you sent the details to Serial Monitor but I restarted it at 13:23 just before I popped out.
Data so far is:

13:23 29976 29976
13:52 31576  1600
13:53 29976 -1600
14:30 28376 -1600
14:31 29976  1600
16:01 28376 -1600
16:02 29976  1600
21:23 31576  1600
21:23 29976 -1600

My firmware is a year newer than yours though.

Final edit: after 8 hours still the same free Heap. Switching off now.

What do you mean? You mentioned about ESP8266 Arduino Core?