BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

Heartbeat timeout continuously

I am facing issue of Heartbeat timeout. I have reconnection code which is running via SimpleTimer but it never connects back. Really not sure what is going wrong. Sometimes, it works by entirely restarting ESP8266.

Logs says like this

[1198811] Heartbeat timeout: 1198811, 1179810, 1198169
[1203170] Connecting to blynk-cloud.com:80

Reconnection code:

void setupTimers() {
  simpleTimer.setInterval(60000L, checkBlynkConnection);
}

void blynkConnect() {
  for (int x = 0; x < 10; x++) {
    bool result = Blynk.connect();
    if (result) {
      break;
    } else {
      if (x == 9) {
        Serial.println("Blynk not connected - resetting");
        restartESP();
        delay(500);
      }
    }
    delay(3000);
  }
}

void checkBlynkConnection() {
  for (int x = 0; x < 10; x++) {
    bool result = Blynk.connected();
    if (result) {
      break;
    } else {
      if (x ==9) {
        blynkConnect();
        delay(500);
      }
    }
    delay(3000);
  }
}

I’d suggest that you post your full code.

Pete.

1 Like

Full code

#define BLYNK_PRINT Serial // Defines the object that is used for printing
#define BLYNK_DEBUG        // Optional, this enables more detailed prints
#include <SimpleTimer.h>
#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <ESP8266Ping.h>
#include <ESP8266mDNS.h>
#include <WiFiManager.h>
#include <BlynkSimpleEsp8266.h>
#define DEBUG

//////////////////////////////////////////////////////////--Init--////////////////////////////////////////////////////

SimpleTimer simpleTimer;
int tokenSize = 33;
char blynk_token[] = "11111111111111111111111111111111";
const int no_of_times_blynk_check = 10;
const int blynk_check_delay = 3000; //3 seconds change for blynk check
const long blynk_timer_check = 600000L; //Check every 600 seconds (10 mins)

/////////////////////////////////////////////////////////////--Vars--////////////////////////////////////////////////////

String Rx_string;
bool isFirstTime = true;
bool shouldSaveConfig = false;

//callback notifying us of the need to save config
void saveConfigCallback () {
#ifdef DEBUG
  Serial.println("Should save config");
#endif
  shouldSaveConfig = true;
}

void UART_receive()
{
  //Do some stuff here..
}

void PhysicalButton()
{
  //Do some stuff here..
}


BLYNK_WRITE(V1)
{
 //TBD
}

BLYNK_WRITE(V2)
{
 //TBD
}

BLYNK_WRITE(V3)
{
  //TBD
}

BLYNK_WRITE(V4)
{
 //TBD
}

BLYNK_WRITE(V5)
{
 //TBD
}

BLYNK_WRITE(V6)
{
  //TBD
}


BLYNK_CONNECTED()
{
 //TBD
}


void restartESP() {
  Blynk.disconnect();
  delay(3000);
  ESP.restart(); //ESP.restart() tells the SDK to reboot, so its a more clean reboot.
  delay(5000);
}

void saveValuesToEEPROM(const char* token) {
#ifdef DEBUG
  Serial.println("Saving values to EEPROM...");
#endif
  strcpy(blynk_token, token);

  if (shouldSaveConfig) {
#ifdef DEBUG
    Serial.println("shouldSaveConfig - Saving values to EEPROM...");
#endif
    //Lets clear EEPROM first
    for (int i = 0; i < 512; i++) {
      EEPROM.write(i, 0);
    }

    //Write to EEPROM
    String strBlynkToken = blynk_token;
    for (int i = 0; i < strBlynkToken.length() + 1; i++)
    {
      EEPROM.write(i, strBlynkToken[i]);
    }
    EEPROM.commit();
  }
#ifdef DEBUG
  Serial.println("Saved values to EEPROM...");
#endif
}

void readFromEEPROM() {
  //Read from EEPROM
  String authToken;
  for (int i = 0; i < tokenSize; i++)
  {
    if (EEPROM.read(i) == 255) {
      authToken = authToken + char(0);
    }
    else {
      authToken = authToken + char(EEPROM.read(i)); //Read one by one with starting address of 0
    }
  }

  strcpy(blynk_token, authToken.c_str());
#ifdef DEBUG
  Serial.println("blynk_token");
  Serial.println(String(blynk_token));
  Serial.println(String(blynk_token).length());
#endif
}

void setupWifiManager() {
  readFromEEPROM();

  WiFiManagerParameter custom_blynk_token("Blynk", "token", blynk_token, 35);
  // WiFiManager
  // Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;
#ifdef DEBUG
  wifiManager.setDebugOutput(true);
#else
  wifiManager.setDebugOutput(false);
#endif
  wifiManager.setBreakAfterConfig(true);
  wifiManager.setSaveConfigCallback(saveConfigCallback);
  wifiManager.setConfigPortalTimeout(180);
  wifiManager.addParameter(&custom_blynk_token);
  wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,97), IPAddress(10,0,1,1), IPAddress(255,255,255,0));

  if (!wifiManager.autoConnect("AutoConnectAP97", "password")) {
    saveValuesToEEPROM(custom_blynk_token.getValue());
    restartESP();
  } else {
    #ifdef DEBUG
        Serial.println("AutoConnectAP Connected...");
    #endif
  }

  // if you get here you have connected to the WiFi
  #ifdef DEBUG
    Serial.println("Connected to WIFI....");
  #endif
  saveValuesToEEPROM(custom_blynk_token.getValue());
  #ifdef DEBUG
    Serial.println("local ip");
    Serial.println(WiFi.localIP());
    Serial.println(String(blynk_token));
    Serial.println(WiFi.SSID().c_str());
    Serial.println(WiFi.psk().c_str());
  #endif
  delay(500);
}


void blynkConnect() {
  //First disconnect completely entire hardware
  Blynk.disconnect();
  delay(1000);
  //Now establish proper connection
  Blynk.config(blynk_token);
  Blynk.connectWiFi(WiFi.SSID().c_str(), WiFi.psk().c_str());
  for (int x = 0; x < no_of_times_blynk_check; x++) {
    bool result = Blynk.connect();
    if (result) {
    #ifdef DEBUG
          Serial.println("Blynk connected...");
    #endif
      break;
    } else {
      #ifdef DEBUG
            Serial.println("Blynk not connected. Must be invalid token...");
      #endif
      if (x == (no_of_times_blynk_check - 1)) {
        #ifdef DEBUG
                Serial.println("I am frustrated now and resetting myself now...");
        #endif
        restartESP();
        delay(500);
      }
    }
    delay(blynk_check_delay);
  }
    #ifdef DEBUG
      Serial.println("Exiting blynkConnect. Connection to blynk done...");
    #endif
}

void checkBlynkConnection() {
  if (WiFi.status() == WL_CONNECTED) {
      for (int x = 0; x < no_of_times_blynk_check; x++) {
        bool result = Blynk.connected();
        if (result) {
    #ifdef DEBUG
          Serial.println("Blynk connected. Do nothing...");
    #endif
          break;
        } else {
    #ifdef DEBUG
          Serial.println("Blynk not connected. Must be internet gone...");
    #endif
          if (x == (no_of_times_blynk_check - 1)) {
    #ifdef DEBUG
            Serial.println("I am frustrated now and trying to re-establish connection now...");
    #endif
            blynkConnect();
            delay(500);
          }
        }
        delay(blynk_check_delay);
      }
    #ifdef DEBUG
      Serial.println("Exiting checkBlynkConnection function...");
    #endif
  }else{
    #ifdef DEBUG
      Serial.println("WIFI not available! Issue with WIFI");
    #endif
    restartESP();
  }
}

void checkWifiConnection() {
  if (WiFi.status() != WL_CONNECTED) {
  #ifdef DEBUG
      Serial.println("Internet Gone. Restarting ESP now..!!");
  #endif
    restartESP();
  }
}


void setupBlynk() {
  #ifdef DEBUG
    Serial.println("Connecting to blynk now...");
    Serial.println("blynk_token");
    Serial.println(String(blynk_token));
    Serial.println(String(blynk_token).length());
    Serial.println("Connecting to WIFI...");
  #endif
  blynkConnect();
}

void setupTimers() {
  simpleTimer.setInterval(blynk_timer_check, checkBlynkConnection);
}

void setup()
{
  ESP.wdtDisable();
  ESP.wdtEnable(WDTO_8S);
  EEPROM.begin(512);
  Serial.begin(38400);
  Serial.println();
  WiFi.setSleepMode(WIFI_NONE_SLEEP);
  WiFi.setAutoReconnect(true);
  setupWifiManager();
  setupBlynk();
  setupTimers();
}


void loop()
{
  ESP.wdtFeed();
  MDNS.update();
  Blynk.run();
  simpleTimer.run();
  if (Serial.available() > 0)
  {
    Rx_string = Serial.readStringUntil('\n');
  }
  UART_receive();
  PhysicalButton();
  yield();
}
1 Like

I’d focus on fixing the source of your problem…

Pete.

Agree on what Pete says. The only way to get this stable is either fix that or get an ESP32 which features two cores that you can use. One for Blynk and one for your other stuff.

But maybe there is another question which needs answering first, why would you want to handle connection management yourself? Why not have Blynk fix that for you? Is there any particular reason you want to reset after ten tries? Just being curious a bit too :slight_smile:

thanks for all the help!

To answer your question - if the device goes offline(meaning connection lost from Blynk or sloppy internet), it never connects back. Hence, It tries to connect back to blynk and tries for 10 times. How can connection be restored once lost without writing additional timer code? Just curious to know.

Thanks for all the help as always! Documentation was very helpful.
One query - does blynk automatically connect back if the connection is lost for some reason - may be lost internet, blynk restart etc.?

Secondly, I will minimize the calls in the loop and test further.

void loop()
{
  ESP.wdtFeed();
  MDNS.update();
  Blynk.run();
  simpleTimer.run();
  if (Serial.available() > 0)
  {
    Rx_string = Serial.readStringUntil('\n');
  }
  UART_receive();
  PhysicalButton();
  yield();
}

Blynk will handle it and with a clean loop() it will be much more stable. Reading the serial port can already wreak havoc on things, let alone if you insert conditional statements :slight_smile:

ok thanks! I will try to optimize loop(). thanks!

Np, please let us know if you need help cleaning up stuff :wink:

That would be really great help! I was just thinking what to remove or refactor as I am using everything in loop().

I did small refactoring as shown below - not sure what more can be done here…:

void loop()
{
  ESP.wdtFeed();
  MDNS.update();
  Blynk.run();
  simpleTimer.run();
  if (Serial.available() > 0)
  {
    tempString = Serial.readStringUntil('\n');
    if(tempString != ""){
      Rx_string = tempString;
      UART_receive();
    }
  }
  UART_receive();
  //PhysicalButton(); //removed as not needed
  yield();
}

@vishalavalani, you mentioned in another topic that you’re thinking of using Node-Red.
If go down that route then you don’t need to run any Blynk code on your devices at all. My standard setup is to run Wi-Fi and MQTT code on my devices. The devices talk to my Node-Red server using MQTT and Node-Red talks to Blynk.

One advantage of this is that MQTT connection to Node-Red is much more accommodating in terms of cluttered void loops. Obviously you shouldn’t use this as a way of getting around bad programming, but there are some things, like waiting for data over a serial interface that are very difficult to do in the Blynk environment (unless you use @Lichtsignaal’s suggestion of utilising multiple cores within the ESP32.

If you’ve not already come across it, then you might find this topic useful…

Pete.

Have you tried to just add Blynk.run and simpletimer? It may be prudent to build it from there and see where things get sticky.

@Lichtsignaal will try this out.

@PeteKnight thanks for detailed information. it is very useful. I have also purchased another router and testing on it. So far things are better and may be router was the culprit which is very unfortunate. :frowning:

1 Like

Wifi can be a pain in the butt and there are so many factors which will contribute to bad signal (I know, I manage 1600+ accesspoints on a daily basis …). The router could be an issue, but it’s usually a series of things combined which will turn things over for the worst or better.

I still would advice to refactor the loop() as to reach the highest possible degree of robustness.