Heartbeat timeout Problem every Day around the same time

Hi Community,

I hope you can help me with my problem. I have created a project and actually all the functions work as I expect. However, I have a problem every morning. Always at about 7am (+/- 30 min) I have a Heartbeat timeout (see DEBUG log). After that I try to restart via WDT but then Blynk can’t sync anything anymore … in this case only a hard-reset helps to bring it back to work.

Since everything runs stable during the day I assume that I have a bug in my code that triggers the timeout. Does anyone have a tip what I should change or where i do the error?

My timer input is set to 10.00- 13.30 on all days in the correct timezone.

Thank you in advance for your help.

My Hardware Setup:
Arduino Mega + ESP8266 (NodeMUC 1.3 (AT Firmeware))
Blynk Local Server 0.41.14 (Java 8 on Raspi) // before i used the could with same result
Blynk Libary: v0.6.1
iOS App: 2.26.5
NodeMCU:
AT version:1.3.0.0(Jul 14 2016 18:54:01)
SDK version:2.0.0(656edbf)

#define BLYNK_DEBUG
#define BLYNK_PRINT Serial
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <Blynk.h>
#include <DHT.h>
#include <Wire.h>
#include "cactus_io_BME280_I2C.h"
#include <Adafruit_CCS811.h>
#include <WidgetRTC.h>
#include <TimeLib.h>
#include <avr/wdt.h>


Adafruit_CCS811 ccs;
BME280_I2C bme; // I2C using address 0x76

BlynkTimer timer;
WidgetRTC rtc;
WidgetTerminal terminal(V1);

char auth[] = "xxxxxxxxxx";
char ssid[] = "xxxxxxxxxx";
char pass[] = "xxxxxxxxxx";

WidgetLED ledLicht(V46);
WidgetLED ledVentilator(V47);
WidgetLED ledLuefter(V48);
WidgetLED ledTest(V2);


bool ledStatus = false;
#define BLYNK_GREEN     "#23C48E"
#define BLYNK_BLUE      "#04C0F8"
#define BLYNK_YELLOW    "#ED9D00"
#define BLYNK_RED       "#D3435C"
#define BLYNK_DARK_BLUE "#5F7CD8"

#define EspSerial Serial3
#define led 32
#define onboardLed 13
#define ventilator 35
#define luefterLow 33
#define luefterHigh 34
#define DHTPIN A11
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

#define ESP8266_BAUD 9600
ESP8266 wifi(&EspSerial);

char Date[16];
char Time[16];
int t;
int h;
int t_a;
int h_a;
int t_i;
int h_i;
int maxTemp = 30;
int maxH = 65;

char currentTime[9];
bool clockSync = false;

bool notifiedT     = false;
bool notifiedH     = false;

int alldays ;
int manual = 0;
long startsecondswd;            // weekday start time in seconds
long stopsecondswd;             // weekday stop  time in seconds
long nowseconds;                // time now in seconds
bool isFirstConnect = true;


// Calibration for Soil Sensors
const int AirValue1 = 595;   
const int WaterValue1 = 300;  

const int AirValue2 = 580;   
const int WaterValue2 = 293;  

const int AirValue3 = 586;   
const int WaterValue3 = 290; 

const int AirValue4 = 590;   
const int WaterValue4 = 290;  

int soil_sensor1 = A1;
int output_value1 ;
int moisturelevel1;

int soil_sensor2 = A2;
int output_value2 ;
int moisturelevel2 ;

int soil_sensor3 = A3;
int output_value3 ;
int moisturelevel3 ;

int soil_sensor4 = A7;
int output_value4 ;
int moisturelevel4 ;

int co2_ppm ;
int TVOC; 

int ledPin = 32;
int ventilatorPin = 35;
int luefterLowPin = 33;
int luefterHighPin = 34;

void setup()
{

  dht.begin();
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
  pinMode(onboardLed, OUTPUT);
  digitalWrite(onboardLed, LOW);
  pinMode(ventilatorPin, OUTPUT);
  digitalWrite(ventilatorPin, HIGH);
  pinMode(luefterLowPin, OUTPUT);
  digitalWrite(luefterLowPin, HIGH);
  pinMode(luefterHighPin, OUTPUT);
  digitalWrite(luefterHigh, HIGH);

  Serial.begin(9600);
  EspSerial.begin(ESP8266_BAUD);
  Blynk.begin(auth, wifi, ssid, pass, "x.x.x.x", 8080);
  setSyncInterval(10 * 60); // RTC Sync interval in seconds (10 minutes)


  // Clear the terminal content
  terminal.clear();


  Blynk.virtualWrite(V1,"Blynk v ", BLYNK_VERSION, ": Sync gestartet\n");
  Blynk.virtualWrite(V1,"-------------\n");
  Blynk.syncVirtual(V33, V35, V36);
  delay(20);
  Blynk.syncVirtual(V15, V16);
  terminal.flush();

  if (!ccs.begin()) {
    Serial.println("Start des co2-Sensors fehlgeschlagen! Bitte ueberpruefen Sie Ihre Verdrahtung.");
    terminal.println("Start des co2-Sensors fehlgeschlagen! Bitte ueberpruefen Sie Ihre Verdrahtung.");
    terminal.flush();
  }

  if (!bme.begin()) {
  Serial.println("Es konnte kein BME280 Sensor gefunden werden!");
  Serial.println("Bitte überprüfen Sie die Verkabelung!");
  // while (1);
  }
  bme.setTempCal(-1);

  // Setup a function to be called every second
  timer.setInterval(100000L, checkBlynk);
  timer.setInterval(14000L, clockDisplay);
  timer.setInterval(31000L, sendSensor);
  timer.setInterval(60000L, activetoday);
  // timer.setInterval(3000L, lcd_data);
 

  ledLicht.on();
  ledLicht.setColor(BLYNK_RED);

  ledVentilator.on();
  ledVentilator.setColor(BLYNK_RED);

  ledLuefter.on();
  ledLuefter.setColor(BLYNK_RED);

  ledTest.on();
  ledTest.setColor(BLYNK_RED);


}


void resetNotifiedT() 
{
  notifiedT = 0;
}

void resetNotifiedH() 
{
  notifiedH = 0;
}


void checkBlynk() {
  if (!Blynk.connected()) {
    Serial.println();
    Serial.println("*********** Verbindungs Fehler ************");
    Serial.println("Nicht mit dem Blynk-Server verbunden");
    Serial.println("*********** Automatischer Neustart ************");
    Serial.println();
    wdt_enable(WDTO_1S);
  }
}



BLYNK_CONNECTED() {
  rtc.begin();
}




void activetoday() {        
  if (alldays == 1) {
    Blynk.syncVirtual(V34); 

  }
}

void clockDisplay() { // only needs to be done once after time sync
  if ((year() != 1970) && (clockSync == false)) {
    sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
    Serial.println(currentTime);
    // terminal.println(currentTime);
    clockSync = true;
  }
  int gmthour = hour();
  if (gmthour == 24) {
    gmthour = 0;
  }
  String displayhour =   String(gmthour, DEC);
  int hourdigits = displayhour.length();
  if (hourdigits == 1) {
    displayhour = "0" + displayhour;
  }
  String displayminute = String(minute(), DEC);
  int minutedigits = displayminute.length();
  if (minutedigits == 1) {
    displayminute = "0" + displayminute;
  }

}

BLYNK_WRITE(V15)
{
maxTemp = param.asInt(); 
}

BLYNK_WRITE(V16)
{
maxH = param.asInt(); 
}


BLYNK_WRITE(V33) {
  switch (param.asInt())
  {
    case 1: // Item 1
      alldays = 1;
      terminal.println("Automatik Beleuchtung: Auto");
      break;
    case 2: // Item 2
      alldays = 0;
      digitalWrite(ledPin, HIGH);
      ledLicht.setColor(BLYNK_RED);
      terminal.println("Automatik Beleuchtung: Manuell Aus");
      break;
    case 3:
      alldays = 0;
      digitalWrite(ledPin, LOW); // set LED OFF
      ledLicht.setColor(BLYNK_GREEN);
      terminal.println("Automatik Beleuchtung: Manuell An");
      break;
    default:
      terminal.println("Automatik Beleuchtung: Auto");
      alldays = 1;
  }
  // Serial.println("DEBUG: V33 OK");
  terminal.flush();
}


BLYNK_WRITE(V34)//All days
{
  if (alldays == 1) {
    sprintf(Date, "%02d/%02d/%04d",  day(), month(), year());
    sprintf(Time, "%02d:%02d:%02d", hour(), minute(), second());

    TimeInputParam t(param);

    terminal.print("Check Automatik Beleuchtung gestartet: ");
    terminal.println(Time);
    terminal.flush();
    int dayadjustment = -1;
    if (weekday() == 1) {
      dayadjustment =  6; // needed for Sunday, Time library is day 1 and Blynk is day 7
    }
    if (t.isWeekdaySelected(weekday() + dayadjustment)) { //Time library starts week on Sunday, Blynk on Monday
      terminal.println("Automatik aktiv heute");
      terminal.flush();
      if (t.hasStartTime()) // Process start time
      {
        terminal.println(String("Starte Nachtphase: ") + t.getStartHour() + ":" + t.getStartMinute());
        terminal.flush();
      }
      if (t.hasStopTime()) // Process stop time
      {
        terminal.println(String("Stop Nachtphase : ") + t.getStopHour() + ":" + t.getStopMinute());
        terminal.flush();
      }
      // Display timezone details, for information purposes only
      terminal.println(String("Zeitzone: ") + t.getTZ()); // Timezone is already added to start/stop time
      //  terminal.println(String("Time zone offset: ") + t.getTZ_Offset()); // Get timezone offset (in seconds)
      terminal.flush();

      for (int i = 1; i <= 7; i++) {  // Process weekdays (1. Mon, 2. Tue, 3. Wed, ...)
        if (t.isWeekdaySelected(i)) {
          // terminal.println(String("Tag ") + i + " ist ausgewaehlt");
          // terminal.flush();
        }
      }
      nowseconds = ((hour() * 3600L) + (minute() * 60L) + second());
      // terminal.println(String("hour : ") + (hour() * 3600L) );
      // terminal.println(String("minute : ") + (minute() * 60L));
      // terminal.println(String("second : ") + second());
      // terminal.println((hour() * 3600L) + (minute() * 60) + second());
      startsecondswd = (t.getStartHour() * 3600L) + (t.getStartMinute() * 60L);
      // terminal.println(String("DEBUG : nowseconds : ") + nowseconds);
      // terminal.println(String("DEBUG : Startpsecondswd : ") + startsecondswd); // used for debugging
      terminal.flush();
      if (nowseconds >= startsecondswd) {
        terminal.print("LED aus ab");
        terminal.println(String(" ") + t.getStartHour() + ":" + t.getStartMinute());
        terminal.flush();
        if (nowseconds <= startsecondswd + 90) {  // 90s on 60s timer ensures 1 trigger command is sent

          digitalWrite(ledPin, HIGH);
          ledLicht.setColor(BLYNK_RED);
          terminal.print("LED Bechleuchtung ist ausgeschalten. Es ist Nacht !");
          // set LED ON
          // Blynk.virtualWrite(V2, 1);
          // code here to switch the relay ON
        }
      }
      else {
        digitalWrite(ledPin, LOW); // set LED OFF
        ledLicht.setColor(BLYNK_GREEN);
        terminal.println("LED Bechleutung eingeschalten. Es ist Tag.");
        terminal.flush();

      }
      stopsecondswd = (t.getStopHour() * 3600L) + (t.getStopMinute() * 60L);
      // terminal.println(String("DEBUG : nowseconds : ") + nowseconds);
      // terminal.println(String("DEBUG : Stopsecondswd : ") + stopsecondswd);  // used for debugging
      // terminal.flush();
      if (nowseconds >= stopsecondswd) {
        digitalWrite(ledPin, LOW); // set LED OFF
        ledLicht.setColor(BLYNK_GREEN);
        terminal.print("LED an ab");
        terminal.println(String(" ") + t.getStopHour() + ":" + t.getStopMinute());
        terminal.println("LED Bechleutung eingeschalten. Es ist Tag.");
        terminal.flush();
        if (nowseconds <= stopsecondswd + 90) { // 90s on 60s timer ensures 1 trigger command is sent
          digitalWrite(ledPin, LOW); // set LED OFF
          ledLicht.setColor(BLYNK_GREEN);
          terminal.println("LED Bechleutung eingeschalten. Es ist Tag.");
          // code here to switch the relay OFF
        }
      }
      else {
        if (nowseconds >= startsecondswd) {
          digitalWrite(ledPin, HIGH);
          ledLicht.setColor(BLYNK_RED);
          terminal.print("LED Bechleuchtung ist ausgeschaltet. Es ist Nacht !");
          terminal.flush();

        }
      }
    }
    else {
      terminal.println("Automatik heute nicht aktiv.");
      terminal.flush();
          }
    terminal.println();
    
  }
}





BLYNK_WRITE(V35) {
  switch (param.asInt())
  {
    case 1: 
      terminal.println("Umluftventilator Aus");
      digitalWrite(ventilatorPin, HIGH);
      ledVentilator.setColor(BLYNK_RED);
      break;
    case 2: 
      terminal.println("Umluftventilator An");
      digitalWrite(ventilatorPin, LOW);
      ledVentilator.setColor(BLYNK_GREEN);
      break;
    default:
      digitalWrite(ventilatorPin, HIGH);
      ledVentilator.setColor(BLYNK_RED);
  }
  terminal.flush();
}





BLYNK_WRITE(V36) {
  switch (param.asInt())
  {
    case 1:       
      terminal.println("Abluftventilator Aus");
      digitalWrite(luefterHighPin, HIGH);
      digitalWrite(luefterLowPin, HIGH);
      ledLuefter.setColor(BLYNK_RED);
      break;
    case 2:      
      terminal.println("Abluftventilator 100%");
      digitalWrite(luefterHighPin, HIGH);
      digitalWrite(luefterLowPin, LOW);
      ledLuefter.setColor(BLYNK_BLUE);
      break;
    case 3:  
      terminal.println("Abluftventilator 80%");
      digitalWrite(luefterHighPin, LOW);
      digitalWrite(luefterLowPin, HIGH);
      ledLuefter.setColor(BLYNK_DARK_BLUE);
      break;
    default:    
      digitalWrite(luefterHighPin, HIGH);
      digitalWrite(luefterLowPin, HIGH);
      ledLuefter.setColor(BLYNK_RED);
  }
  terminal.flush();
}




BLYNK_WRITE(V1)
{

  
  if (String("Marco") == param.asStr()) {
    terminal.println("You said: 'Marco'") ;
    terminal.println("I said: 'Polo'") ;
  } else {

    // Send it back
    terminal.print("You said:");
    terminal.write(param.getBuffer(), param.getLength());
    terminal.println();
  }
  
  terminal.flush();
}





void sendSensor()
{
  
  String notifyStringT;
  String notifyStringH;
  bme.readSensor();
  h_a = dht.readHumidity();
  t_a = dht.readTemperature(); // or dht.readTemperature(true) for Fahrenheit
  h_i = bme.getHumidity();
  t_i = bme.getTemperature_C(); // or dht.readTemperature(true) for Fahrenheit


  output_value1 = analogRead(soil_sensor1);
  moisturelevel1 = constrain ( map(output_value1, AirValue1, WaterValue1, 0, 100), 0, 100);

  output_value2 = analogRead(soil_sensor2);
  moisturelevel2 = constrain ( map(output_value2, AirValue2, WaterValue2, 0, 100), 0, 100);

  output_value3 = analogRead(soil_sensor3);
  moisturelevel3 = constrain ( map(output_value3, AirValue3, WaterValue3, 0, 100), 0, 100);

  output_value4 = analogRead(soil_sensor4);
  moisturelevel4 = constrain (map(output_value4, AirValue4, WaterValue4, 0, 100), 0, 100);


  if (ccs.available()) {
    if (!ccs.readData()) {
      ccs.setDriveMode(4);
      ccs.readData();
      co2_ppm = (ccs.geteCO2());
      TVOC = (ccs.getTVOC());
    }
    else {
      terminal.println("CO2-Sensor - FEHLER!");
      ccs.readData();
    }
  }

 if (t_i >= maxTemp && !notifiedT) 
    {
      notifiedT = true;
      
      notifyStringT = "Alarm - Temperatur IST:" + String(t_i) + " SOLL MAX:" + String(maxTemp);
      Serial.println(notifyStringT);
      terminal.println(notifyStringT);
      Blynk.notify(notifyStringT);
      timer.setTimeout(600000L, resetNotifiedT); 
    }
    
  if (h_i >= maxH && !notifiedH) 
    {
      notifiedH = true;
      
      notifyStringH = "Alarm - Luftfeuchtigkeit IST:" + String(h_i) + " SOLL MAX:" + String(maxH);
      Serial.println(notifyStringH);
      terminal.println(notifyStringH);
      Blynk.notify(notifyStringH);
      timer.setTimeout(600000L, resetNotifiedH); 
    }




  Blynk.virtualWrite(V5, h_i);
  Blynk.virtualWrite(V6, t_i);
  Blynk.virtualWrite(V13, h_a);
  Blynk.virtualWrite(V14, t_a);

  Blynk.virtualWrite(V7, moisturelevel1 );
  Blynk.virtualWrite(V8, moisturelevel2 );
  Blynk.virtualWrite(V9, moisturelevel3 );
  Blynk.virtualWrite(V10, moisturelevel4 );

  Blynk.virtualWrite(V21, output_value1 );
  Blynk.virtualWrite(V22, output_value2 );
  Blynk.virtualWrite(V23, output_value3 );
  Blynk.virtualWrite(V24, output_value4 );
  
  // 400ppm - 8192ppm
  Blynk.virtualWrite(V11, co2_ppm);
  // 0ppb- 1187ppb
  Blynk.virtualWrite(V12, TVOC);
  terminal.flush();
}





void loop()
{
  Blynk.run();
  timer.run(); // Initiates BlynkTimer
}

Debug Log:

07:25:21.929 -> [144256271] <[14].[EE|00|09]vw[00]11[00]417
07:25:21.929 -> [144256434] <[14].[EF|00|07]vw[00]12[00]2
07:25:21.929 -> [144256685] <[06].[F0|00|00]
07:25:21.929 -> [144256791] >[00].[F0|00|C8]
07:25:41.960 -> [144266770] <[06].[F1|00|00]
07:25:41.960 -> [144266878] >[00].[F1|00|C8]
07:25:41.960 -> [144276856] <[06].[F2|00|00]
07:25:41.960 -> [144276963] >[00].[F2|00|C8]
07:27:11.957 -> [144363900] Heartbeat timeout: 144363900, 144276963, 144276856
07:27:11.957 -> [144368911] <[14].[F3|00|07]vw[00]5[00]44
07:27:11.957 -> [144373922] Cmd error
07:27:40.176 -> [144384021] <[1D|00|01|00] xxxxxxxxx AUTH CODE xxxxxxxxx
07:27:40.176 -> 
07:27:40.176 -> *********** Verbindungs Fehler ************
07:27:40.176 -> Nicht mit dem Blynk-Server verbunden
07:27:40.176 -> *********** Automatischer Neustart ************
07:27:40.176 -> 
07:27:40.176 -> [0] 
FREEEEEEZZZZZZZ -> no more reaction until hard-reset

I’m not sure that…

Is the correct way to achieve that.

I’d guess that the cause of the issue is your ISP re-assigning IP addresses, but you’d need to monitor your external IP to confirm that.

I think the first step is to see if it’s the ESP8266 which stops responding and requires resetting, or the Arduino.

Pete.

Hi Pete,

I had the ip change in mind too but i change to local server to avoid this. Problem still the same.

The ESP console show that it get a last command corresponding to the last i see in debug log. But than it seams that my mega don’t response / answer. So i think the Arduino needs the reset. How can i test this ? Resetting the esp when the fail is happen boot up the esp again ( got ip etc.) but nothing happens in the Mega console.

I can try to remove the wdt … but it only takes effect after the connection is gone.

Best ,

Patrick

Maybe it’s when your DHCP leases expire then?

What do you mean by ESP console?

Pete.

So for now i removed “wdt” for debugging better.

My DHCP leases are vaild for 10 days … i checked in my DHCP server. As well the ESP has everytime the same adress.

I connect a Serial Console to the ESP as well to see whats happing on the ESP in case of the failture.

I’m not sure that’s a good idea!

Pete.

I have only tried this to get a better picture of the error. The error was and is present even without monitoring the serial interface of the ESP.

07:25:41.960 -> [144276856] <[06].[F2|00|00]
07:25:41.960 -> [144276963] >[00].[F2|00|C8]
07:27:11.957 -> [144363900] Heartbeat timeout: 144363900, 144276963, 144276856

What are the Actions behind this DEBUG Lines … where the Timeout is happening ? I cant find a documentation about it. And whats comes next if such a Timeout happend normaly ?

Pete.

hi pete,

just to let you know … i think it was a HW problem with my Mega Board (China). After i can not find any problem i decide to port everything to a ESP32 where everything works fine an stable from the beginning.

If I had done this weeks ago, it would have saved me many hours of debugging.

But anyway thank for your help.

1 Like