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

ESP work offline


#41

I just tried your template, work the same as my sketch,

as long as this line execute (Blynk.connectWiFi(ssid, pass):wink: without wifi connection, the code stuck on it.


#42

Blynk.connectWiFi() is another Blynk function, not sure why that’s in the template. This is the exact code I am using, confirm it works for you.

/* NoBlynkBlock.ino by Costas for https://community.blynk.cc/t/blynk-is-blocking-if-internet-is-down/16809
will recover from server or router going down   

*/

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char ssid[]   = "xxx";
char pass[]   = "xxx";
char auth[]   = "xxx";
char server[] = "blynk-cloud.com";

BlynkTimer timer;
unsigned int myServerTimeout  =  3500;  //  3.5s server connection timeout (SCT)
unsigned int myWiFiTimeout    =  3200;  //  3.2s WiFi connection timeout   (WCT)
unsigned int functionInterval =  7500;  //  7.5s function call frequency   (FCF)
unsigned int blynkInterval    = 25000;  // 25.0s check server frequency    (CSF)

void setup()
{
  Serial.begin(115200);
  Serial.println();
  if(WiFi.status() == 6){
    Serial.println("\tWiFi not connected yet.");
  }
  timer.setInterval(functionInterval, myfunction);// run some function at intervals per functionInterval
  timer.setInterval(blynkInterval, checkBlynk);   // check connection to server per blynkInterval
  unsigned long startWiFi = millis();
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    if(millis() > startWiFi + myWiFiTimeout){
      Serial.println("\tCheck the WiFi router. ");
      break;
    }       
  }
  Blynk.config(auth, server);
  checkBlynk();
}

void myfunction(){
  Serial.println("\tLook, no Blynk  block.");
  if(WiFi.status()== 3){
    Serial.println("\tWiFi still  connected.");
  }
  if(Blynk.connected()){
    Blynk.virtualWrite(V11, millis() / 1000);
  }
}

void checkBlynk() {
  if (WiFi.status() == WL_CONNECTED)  
  {
    unsigned long startConnecting = millis();    
    while(!Blynk.connected()){
      Blynk.connect();  
      if(millis() > startConnecting + myServerTimeout){
        Serial.print("Unable to connect to server. ");
        break;
      }
    }
  }
  if (WiFi.status() != 3) {
    Serial.print("\tNo WiFi. ");
  } 
  Serial.printf("\tChecking again in %is.\n", blynkInterval / 1000);
  Serial.println(); 
}

void loop()
{
  if (Blynk.connected()) {Blynk.run();}
  timer.run();
}

Recovering Blynk connection to server
#43

i did delete this function from my sketch and it work good,
everything functioning , the sketch run even when there is no wifi connection,
and automatically reconnect when the wifi back.


#44

but you need the replacement WiFi connection code in your sketch because it’s only reconnecting because it remembers your WiFi credentials. If you use another AP it will never connect without the extra code.


#45

this is organized code that work good as i expect :

#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <OneWire.h>

#define boiler 14
#define OnLed  4   
#define systemLED 5

void buttonLedWidget();
void Temperature();
void LEDtoggle();
void OnTime();
void countTime();

WidgetLED led1(0);
WidgetLED led5(3);
WidgetLED led3(V3);

SimpleTimer timer;

OneWire  ds(2);  // on pin 2 between VCC&DATA (a 4.7K resistor is necessary)

float ESP201ADCVref=1.10;

const int btnPin = 17;

unsigned long mytimeout = 3000; // 3.0s timeout
unsigned long minTime = 0;
unsigned long work2 = 0;
unsigned long nowTime = 0;
unsigned long count = 0;

unsigned int myConnectionTimeout =   5000;  // Connection Timeout (CT)
unsigned int blynkcheckInterval  =  60000;  // Check Server Frequency (CSF)

bool dudon = false;
bool dune = true;
bool manual = false;
bool Connected2Blynk = false;
bool lastbutton = 0;

int minutse = 0;
int work = 0;
int state = LOW;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;

char auth[] = "1e0fc8aa350c47e88bbb078dc1f6302a";
char server[] = "blynk-cloud.com";
char ssid[] = "Nir&Rotem";
char pass[] = "11335577";



void setup()
{
  Serial.begin(115200);
  
  Serial.println("start");
  
  timer.setInterval(30000L, checkBlynk);  // every 5s check if connected to server
  
 // Blynk.connectWiFi(ssid, pass);
  Blynk.config(auth,server); 

  checkBlynk();
  
  pinMode(boiler, OUTPUT);
  pinMode(OnLed, OUTPUT);
  pinMode(systemLED, OUTPUT);
 
  digitalWrite(OnLed,HIGH);
  digitalWrite(systemLED,LOW);
  digitalWrite(boiler,HIGH);

  timer.setInterval(200L, pushButtton);
  timer.setInterval(10000L,Temperature);
  timer.setInterval(10000L,countTime);
  timer.setInterval(10000L,OnTime);
  timer.setInterval(10000L,sendTime);
 // timer.setInterval(60000L, CheckConnection); // check if still connected every 11 seconds
  
  led1.on();
  led5.on();
  Blynk.virtualWrite(V1, "pick", 0);
}


void loop()
{
  if(Blynk.connected())  // only process Blynk commands if connected to server
  {    
     Blynk.run();
  }
  timer.run();
}


BLYNK_WRITE(V1) 
{
  int getTime = 0;
  switch (param.asInt())
  {
    case 1: // Item 1
      Serial.println("off");
      getTime = 0;
      break;
    case 2: // Item 1
      Serial.println("30 minuts");
      getTime = 30;
      break;
    case 3: // Item 2
      Serial.println("45 minuts");
      getTime = 45;
      break;
    case 4: // Item 3
      Serial.println("60 minuts");
      getTime = 60;
      break;
    case 5: // Item 4
      Serial.println("75 minuts");
      getTime = 75;
      break;
    case 6: // Item 5
      Serial.println("90 minuts");
      getTime = 90;
      break;
    case 7: // Item 6
      Serial.println("120 minuts");
      getTime = 120;
      break;
    default:
      Serial.println("off");
      getTime = 0 ;
  }
  work = getTime;
 // OnTime();
}

void pushButtton()
{
  bool button = digitalRead(0);  
  Blynk_Delay(1);
  bool button2 = digitalRead(0);
  button = button && button2;
  
  if(button && !lastbutton)
  {
    Serial.println("pressed"); 
    if (state == HIGH)
    {
      state = LOW;
      work = 130;
    }      
    else
    {
      state = HIGH;
      work = 0;
    }
  } 
  digitalWrite(V3, state);
  lastbutton = button;
}

void Temperature()
{
  Serial.println("Tempfunc");
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  
  if ( !ds.search(addr)) {
    //Serial.println("No more addresses.");
   // Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
 
  Blynk_Delay(1000);
 // delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  for ( i = 0; i < 9; i++)  // we need 9 bytes
  {          
    data[i] = ds.read();
  }
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) 
  {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) 
    {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } 
  else 
  {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  
  celsius = (float)raw / 16.0;
  Serial.print("celsius: ");
  Serial.println(celsius);
  Blynk.virtualWrite(V5,celsius);
}

void OnTime()
{
   unsigned long tout; 
   if((!dudon && dune) || work == 0 || (work == 130 && !dudon) )
   {
     work2 = work;  
     if(count < (work*6))
     {
        BoilerOn();
     }
   }
  if((count >= (work*6)) && dudon)
  { 
      Serial.println("tout");
      BoilerOff();
  }
   Serial.print("work2: ");
   Serial.println(work2);
   if (dudon)
   {
     minTime = work2 - count/6; 
     Serial.print("minTime: ");
     Serial.println((minTime));
     nowTime = (count/6);  
     sendTime();
   }
}

void sendTime()
{
  unsigned long timeLeft = 0;
 
  if(dudon &&((minTime > 0) && (work != 130))) timeLeft = (minTime);
  if(minTime <= 0  )timeLeft = 0;
  if(dudon && (minTime == 130))
  {
    Blynk.virtualWrite(V2,"ON");
    Blynk.virtualWrite(V1, "pick", 0);
  }
  else Blynk.virtualWrite(V2,timeLeft);
  
  if(dudon &&((nowTime > 0))) Blynk.virtualWrite(V4,nowTime);
  else
  {
    nowTime = 0;
    Blynk.virtualWrite(V4,nowTime);
  }
  Serial.print("timeLeft: ");
  Serial.println(timeLeft);
  Serial.print("nowTime: ");
  Serial.println(nowTime);
}

void countTime()
{
 if(dudon)
  {
    count++;
//    Serial.print("countTime:");
//    Serial.println(count);
  }
 else count = 0;
}

void BoilerOn()
{
  digitalWrite(boiler,LOW);
  digitalWrite(OnLed,LOW);
  digitalWrite(systemLED,HIGH);
  dudon = true;
  count = 0;
  Serial.println("dudon");
  Blynk.notify("Boiler ON");
  if(work == 130)Blynk.virtualWrite(V1, "pick", 0);
  state = LOW;
}

void BoilerOff()
{
  digitalWrite(boiler,HIGH);
  digitalWrite(OnLed,HIGH);
  digitalWrite(systemLED,LOW);
  Serial.println("dudoff");
  dudon = false;
  Blynk.virtualWrite(V1, "pick", 0);
  
  
  Blynk.notify("Boiler OFF");
  state = HIGH;
  work = 0;
  work2 = 0;
  minTime = 0;  
}

void Blynk_Delay(int milli)
{
  int end_time = millis() + milli;
  while (millis() < end_time){ }
}


//void CheckConnection() {
//  unsigned long startConnecting = millis();    
//  while(!Blynk.connected()){
//    Blynk.connect();  
//    if(millis() > startConnecting + myConnectionTimeout){
//      Serial.println("\tUnable to connect to server. ");
//      break;
//    }
//  }
//  Serial.print("\tChecking again in ");
//  Serial.print(blynkcheckInterval / 1000.0);
//  Serial.println("s.");
//}


void checkBlynk() 
{ 
  Serial.println("checkBlynk");
  if (WiFi.status() == WL_CONNECTED)  
  {
    unsigned long startConnecting = millis();    
    while(!Blynk.connected()){
      Blynk.connect();  //
      if(millis() > startConnecting + mytimeout){
        Serial.print("Unable to connect to server. ");
        break;
      }
    }
  }
  if (WiFi.status() == 1) {
    Serial.print("No WiFi. ");
  } 
  Serial.println("Checking again in 5s."); 
}

but you need the replacement WiFi connection code in your sketch because it’s only reconnecting because it remembers your WiFi credentials. If you use another AP it will never connect without the extra code.

in order to replace AP to connect ,without extra code, it just if i reprogram the ESP with the new AP
details , right ?
so what’s the different?


#46

Ok, i did use part of your last code:

timer.setInterval(blynkInterval, checkBlynk);   // check connection to server per blynkInterval
  unsigned long startWiFi = millis();
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    if(millis() > startWiFi + myWiFiTimeout){
      Serial.println("\tCheck the WiFi router. ");
      break;
    }       

it seems to work,

Thank you very much for your help and patient.
Nir


#47

of course it works and it’s essential.

If ever you were to change the name or password of your AP if you never call WiFI.begin() it will never connect.
It only works for you at the moment because you have used Blynk.begin() to store the WiFi credentials in your ESP. Now you have dropped Blynk.begin() you need a way to store new WiFi credentials in the ESP.

Just having ssid and pwd variables in the sketch is no good by itself, understand?


#48

Hi Costas,

Yes, you right,
that the reason i use part of your code in the setup() :

timer.setInterval(blynkInterval, checkBlynk); // check connection to server per blynkInterval
unsigned long startWiFi = millis();
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED){
delay(500);
if(millis() > startWiFi + myWiFiTimeout){
Serial.println("\tCheck the WiFi router. ");
break;
}

Now i can change the ssid and the password, and it is connect to different AP.


#49

Hi to all. Sorry for bringing back a year old topic, but I was not able to find a solution for this case.

@Costas, Please kindly help with a suggestion for non blocking code when WiFiManager is used :

WiFiManager wifiManager;
wifiManager.setTimeout(60);
if (!wifiManager.autoConnect(“TEMPERATURE 1 WiFi”, “”)) {
Serial.println(“failed to connect, we should reset as see if it connects”);
delay(3000);
ESP.reset();
delay(5000);
}

instead of

WiFi.begin(ssid, pass);

Best Regards and many thanks in advance for Your kind cooperation,
Hatters


#50

@Costas I’m trying to implement your ESP work offline routine into my project, some details: -

NodeMCU
3 x SoftwareSerial using 2 x serial sensors and 1 x Nextion serial display.
Blynk

As a standalone sketch in the NodeMCU your routine works great, reconnects no problem and the “functionInterval” continues to be live. Fantastic just what I want… :clap:

However, when I insert the same routine into my larger sketch I nearly always get a WDT reset and then it hangs whilst trying to reconnect. It doesn’t like the “while” statement in the checkBlynk function.

I don’t have my sketch with me at the time of writing but I can tell you that I have 7 separate timed functions ranging from 830ms to 60s including checkBlynk. I have spent many hours changing login times, commenting out routines and software serial connections to no avail.

This morning I commented out all the software serial routines and only left 1 timed function implemented, so far it seems to be okay with 1 successful reconnection.

Do you think there maybe a problem using software serial?
Do you think there maybe a problem using more than 1 “functionInterval” routines?

EDIT…

I have just noticed in @ladan.nir code above that he/she says works very well, the timer.setInterval for checkBlynk is placed at the beginning of the void setup() and before and before the other 5 timer.setIntervals. I have placed my checkBlynk timer at the end just like @ladan.nir but he/she has commented it out, maybe because it didn’t work!

Does the order of interval timers matter?

THIS IS NOT MY CODE. IT IS A COPY OF THE ABOVE POST BY @ladan.nir

void setup()
{
  Serial.begin(115200);
  
  Serial.println("start");
  
  timer.setInterval(30000L, checkBlynk);  // every 5s check if connected to server
  
 // Blynk.connectWiFi(ssid, pass);
  Blynk.config(auth,server); 

  checkBlynk();
  
  pinMode(boiler, OUTPUT);
  pinMode(OnLed, OUTPUT);
  pinMode(systemLED, OUTPUT);
 
  digitalWrite(OnLed,HIGH);
  digitalWrite(systemLED,LOW);
  digitalWrite(boiler,HIGH);

  timer.setInterval(200L, pushButtton);
  timer.setInterval(10000L,Temperature);
  timer.setInterval(10000L,countTime);
  timer.setInterval(10000L,OnTime);
  timer.setInterval(10000L,sendTime);
 // timer.setInterval(60000L, CheckConnection); // check if still connected every 11 seconds
  
  led1.on();
  led5.on();
  Blynk.virtualWrite(V1, "pick", 0);
}


void loop()
{
  if(Blynk.connected())  // only process Blynk commands if connected to server
  {    
     Blynk.run();
  }
  timer.run();
}

Richard


#51

The order is not critical, they all start counting down effectively at the same time (within a ms or less)… However the fact that they all try to run their respective functions at the exact same time (within a ms or less) does… bad code, bad :stuck_out_tongue_winking_eye: The timers should be staggered so as to allow time for each function to run before the next one starts.

Read the Staggering Timers: section of this post


#52

@Gunner the code posted above is not mine, it is a copy of the previous post.

After reading many of your (and others) excellent posts on the subject I understand the concept of timers and the 7 timers I’ve set up are staggered and the main program works very well, the only problem I have is if the heartbeat times out and I need to reconnect.

Richard


#53

I knew that… was just answering the question :wink:

Anything like conflicting timers, overtly long blocking routines, while loops, delays, etc. can and will cause WDT issues. Unfortunately troubleshooting such can be tricky unless you really know how your code process runs. Working with someone else’s code just adds to the fun :stuck_out_tongue:

I am unsure of your issue, or what you are trying to accomplish… but based on the title of this OP topic, here is one of my methods of letting any Blynk sketch run when not connected to Blynk.

If this is not quite what you are running into, then perhaps start your own topic with indepth details and code.


#54

@Gunner I tagged on the end of this topic because the routine posted by @Costas works just as I want as a standalone sketch, but for some unknown reason I just cannot successfully implement it into my main project.

I have a topic that I started explaining my connection issues here in China, maybe I should just retire back to good old England where the Internet maybe faster and more stable!

https://community.blynk.cc/t/login-time-out-and-heartbeat/28548/11

I used your code when I started this project, then I was using a Mega2560 because of the available multiple serial ports. Now I’ve moved over to a NodeMCU with software serial, I came across this topic and thought I would give it a try. If I cannot find an answer then I will try your version with the NodeMCU.

Richard


#55

I understood that as well… it is just in this day and age of desiring quick food, facts, solutions, etc… you will get better mileage with the independent topic-per-issue, wherein you take the time/effort to compile all your facts, code, issue descriptions, and show the work/results you have done so far… as it should help draw in others (short) attentions, particularly if they don’t want to read a past year+ of partially related postings and so on.