How to make ESP8266 Shield work full automatically without any effect by router's interruptions

At first i want to thanks the God because he is inspired me to fix this very difficult issue i was facing with my project, and i want to thanks Gunner because he is encouraged me to keep going and fix this issue.

Let’s start:
We know there are my projects facing problems with router interruptions specially when they use ESP8266 as Shield on Arduino. Now i want you to knew there are three interruptions we will counter and all these interruptions will stop your project completely and it was there is no way to get your project reconnect with your router, but a week ago i was able to fix and remove all these interruptions and make your project keep reset by himself until it get connect with your router when your router be ready to connect. Let’s talk about these interruptions and who we will solve them, also all this interruptions will happen at same time:

1 - This one we will face it when your project already connected with your router also with your blynk App, at this time if any interruption will happen with your router that will lead your project to stop completely and no way to reconnect again, so now to fix this problem we need to add this library on your sketch #include <avr/wdt.h> with timer to check if your project still connecting with your blynk, that will be timer.setInterval(6000L, checkBlynk); inside viod setup and you will need conditional statement code to check:

void checkBlynk(){  
 if(!Blynk.connected()){
    Serial.println("Not connected to Blynk server"); 
    wdt_enable(WDTO_1S);
  }
} 

2 - After first interruption we will face the second one, that will happen because when the first reset happened your monitor screen will stop with “Failed to connect WiFi” because your router at this time will not be ready to let any device connect with it, and it need time and that time different from router to router, so was my idea to keep the ESP8266 resetting until my router be ready then it will reconnect automatically. my solution is by update the BlynkSimpleShieldEsp8266.h library through add #include <avr/wdt.h> library inside the BlynkSimpleShieldEsp8266.h library. and add wdt_enable(WDTO_1S); to these lines as shown:

bool connectWiFi(const char* ssid, const char* pass)
    {
        ::delay(500);
        BLYNK_LOG2(BLYNK_F("Connecting to "), ssid);
        /*if (!wifi->restart()) {
            BLYNK_LOG1(BLYNK_F("Failed to restart"));
            return false;
        }*/
        if (!wifi->kick()) {
             BLYNK_LOG1(BLYNK_F("ESP is not responding"));
			 wdt_enable(WDTO_1S);
             //TODO: BLYNK_LOG_TROUBLE(BLYNK_F("esp8266-not-responding"));
             return false;
        }
        if (!wifi->setEcho(0)) {
            BLYNK_LOG1(BLYNK_F("Failed to disable Echo"));
            return false;
        }
        String ver = wifi->ESP8266::getVersion();
        BLYNK_LOG1(ver);
        if (!wifi->enableMUX()) {
            BLYNK_LOG1(BLYNK_F("Failed to enable MUX"));
        }
        if (!wifi->setOprToStation()) {
            BLYNK_LOG1(BLYNK_F("Failed to set STA mode"));
            return false;
        }
        if (wifi->joinAP(ssid, pass)) {
            String my_ip = wifi->getLocalIP();
            BLYNK_LOG1(my_ip);
        } else {
            BLYNK_LOG1(BLYNK_F("Failed to connect WiFi"));
			wdt_enable(WDTO_1S);
            return false;

3 - sometime you will get this message “ESP is not responding” and this will stop your device from reconnecting or reset himself, so I add wdt_enable(WDTO_1S); to this line inside the BlynkSimpleShieldEsp8266.h

 if (!wifi->kick()) {
             BLYNK_LOG1(BLYNK_F("ESP is not responding"));
			 wdt_enable(WDTO_1S);  

Finally i want to ask the blynk manager or coder to do permanently update for his BlynkSimpleShieldEsp8266.h library with last two point to make these issues fix forever for any user and they will not need to go again with these issues.

3 Likes

I’m using an UNO. Should work too I guess. Your solution looks very good. The first step goes fine: so the watchdog in the Arduino sketch works. I’ve tried to follow steps 2 and 3 but it seems like I have not implemented the wdt.h correctly in the Simpleshield.h… Can you please post your modified simpleshield library so I know what goes wrong?

Quick question, will this method work on D1 mini (esp8266) ?

I believe that particular WDT is an Arduino only command. It is placed in the ESP shield library since on a shield configuration all the code still runs on the actual Arduino.

I don’t know if there is an ESP equivalent of a Watch Dog Timer Reset, but you can Google that :wink:

I have tried couple methods but no luck so far maybe because lack of knowledge. I tried this one [Tutorial] Blynk Non Blocking Connect Call

1 Like

Hi Marten,
this is all code for BlynkSimpleShieldEsp8266.h library

/**
 * @file       BlynkSimpleShieldEsp8266.h
 * @author     Volodymyr Shymanskyy
 * @license    This project is released under the MIT License (MIT)
 * @copyright  Copyright (c) 2015 Volodymyr Shymanskyy
 * @date       Jun 2015
 * @brief
 *
 */

#ifndef BlynkSimpleShieldEsp8266_h
#define BlynkSimpleShieldEsp8266_h

#ifdef ESP8266
#error This code is not intended to run on the ESP8266 platform! Please check your Tools->Board setting.
#endif

#ifndef BLYNK_INFO_CONNECTION
#define BLYNK_INFO_CONNECTION  "ESP8266"
#endif

#ifndef BLYNK_ESP8266_MUX
#define BLYNK_ESP8266_MUX  1
#endif

#define BLYNK_SEND_ATOMIC
#define BLYNK_SEND_CHUNK 40

#include <BlynkApiArduino.h>
#include <Blynk/BlynkProtocol.h>
#include <utility/BlynkFifo.h>
#include <ESP8266_Lib.h>
#include <avr/wdt.h>
class BlynkTransportShieldEsp8266
{
    static void onData(uint8_t mux_id, uint32_t len, void* ptr) {
        ((BlynkTransportShieldEsp8266*)ptr)->onData(mux_id, len);
    }

    void onData(uint8_t mux_id, uint32_t len) {
        if (mux_id != BLYNK_ESP8266_MUX) {
            return;
        }
        //BLYNK_LOG2("Got ", len);
        while (len) {
            if (client->getUart()->available()) {
                uint8_t b = client->getUart()->read();
                if(!buffer.push(b)) {
                    BLYNK_LOG1(BLYNK_F("Buffer overflow"));
                }
                len--;
            }
        }
    }

public:
    BlynkTransportShieldEsp8266()
        : client(NULL)
        , status(false)
        , domain(NULL)
        , port(0)
    {}

    void setEsp8266(ESP8266* esp8266) {
        client = esp8266;
        client->setOnData(onData, this);
    }

    void begin(const char* d,  uint16_t p) {
        domain = d;
        port = p;
    }

    bool connect() {
        if (!domain || !port)
            return false;
        status = client->createTCP(BLYNK_ESP8266_MUX, domain, port);
        return status;
    }

    void disconnect() {
        status = false;
        buffer.clear();
        client->releaseTCP(BLYNK_ESP8266_MUX);
    }

    size_t read(void* buf, size_t len) {
        uint32_t start = millis();
        //BLYNK_LOG4("Waiting: ", len, " Occuied: ", buffer.getOccupied());
        while ((buffer.getOccupied() < len) && (millis() - start < 1500)) {
            client->run();
        }
        return buffer.read((uint8_t*)buf, len);
    }
    size_t write(const void* buf, size_t len) {
        if (client->send(BLYNK_ESP8266_MUX, (const uint8_t*)buf, len)) {
            return len;
        }
        return 0;
    }

    bool connected() { return status; }

    int available() {
        client->run();
        //BLYNK_LOG2("Still: ", buffer.getOccupied());
        return buffer.getOccupied();
    }

private:
    ESP8266* client;
    bool status;
    BlynkFifo<uint8_t,256> buffer;
    const char* domain;
    uint16_t    port;
};

class BlynkWifi
    : public BlynkProtocol<BlynkTransportShieldEsp8266>
{
    typedef BlynkProtocol<BlynkTransportShieldEsp8266> Base;
public:
    BlynkWifi(BlynkTransportShieldEsp8266& transp)
        : Base(transp)
        , wifi(NULL)
    {}

    bool connectWiFi(const char* ssid, const char* pass)
    {
        ::delay(500);
        BLYNK_LOG2(BLYNK_F("Connecting to "), ssid);
        /*if (!wifi->restart()) {
            BLYNK_LOG1(BLYNK_F("Failed to restart"));
            return false;
        }*/
        if (!wifi->kick()) {
             BLYNK_LOG1(BLYNK_F("ESP is not responding"));
			 wdt_enable(WDTO_1S);
             //TODO: BLYNK_LOG_TROUBLE(BLYNK_F("esp8266-not-responding"));
             return false;
        }
        if (!wifi->setEcho(0)) {
            BLYNK_LOG1(BLYNK_F("Failed to disable Echo"));
            return false;
        }
        String ver = wifi->ESP8266::getVersion();
        BLYNK_LOG1(ver);
        if (!wifi->enableMUX()) {
            BLYNK_LOG1(BLYNK_F("Failed to enable MUX"));
        }
        if (!wifi->setOprToStation()) {
            BLYNK_LOG1(BLYNK_F("Failed to set STA mode"));
            return false;
        }
        if (wifi->joinAP(ssid, pass)) {
            String my_ip = wifi->getLocalIP();
            BLYNK_LOG1(my_ip);
        } else {
            BLYNK_LOG1(BLYNK_F("Failed to connect WiFi"));
			wdt_enable(WDTO_1S);
            return false;
        }
        BLYNK_LOG1(BLYNK_F("Connected to WiFi"));
        return true;
    }

    void config(ESP8266&    esp8266,
                const char* auth,
                const char* domain = BLYNK_DEFAULT_DOMAIN,
                uint16_t    port   = BLYNK_DEFAULT_PORT)
    {
        Base::begin(auth);
        wifi = &esp8266;
        this->conn.setEsp8266(wifi);
        this->conn.begin(domain, port);
    }

    void begin(const char* auth,
               ESP8266&    esp8266,
               const char* ssid,
               const char* pass,
               const char* domain = BLYNK_DEFAULT_DOMAIN,
               uint16_t    port   = BLYNK_DEFAULT_PORT)
    {
        config(esp8266, auth, domain, port);
        connectWiFi(ssid, pass);
        while(this->connect() != true) {}
    }

private:
    ESP8266* wifi;
};

static BlynkTransportShieldEsp8266 _blynkTransport;
BlynkWifi Blynk(_blynkTransport);

#include <BlynkWidgets.h>

#endif

***** and delete BlynkSimpleShieldEsp8266.cpp library for arduino libraries.

2 Likes

Sorry speed57, I didn’t use D1 mini, so i don’t know right now.

@speed57 yes the ESP has 2 WDT’s, a software and hardware version. Nobody really seems to quite now the difference between the two.

The core version 2.3.0 had bugs relating to working with the WDT so you need to ensure you are on 2.4.0-rc2.

Espressif have the built in WDT’s so you shouldn’t need to do much with it but I guess Atmel have the same for their Arduino chips. WDT for ESP’s normally involves disabling the features as the inbuilt WDT’s (2 off) are from about 2 to 6 seconds and some routines might take longer than this to run.

2 to 6s is a very long time and can normally be countered by including delay(1) / yield() and Blynk.run() within your functions.

Can we try to keep this “project” related to the shield system as Blynk already have a working system for ESP’s.

speed57,
check this link: https://techtutorialsx.com/2017/01/21/esp8266-watchdog-functions/

2 Likes

Thankyou, the code is exactly the same as mine. I can’t find the BlynkSimpleShieldEsp8266.cpp file. These are te libraries included in the Arduino Sketch:

#define BLYNK_PRINT Serial
#include <BlynkSimpleShieldEsp8266.h>
#include <ESP8266_Lib.h>
#include <avr/wdt.h>
#include <SimpleTimer.h>

Is this correct? Where can I find the BlynkSimpleShieldEsp8266.cpp file?

You meant the *.h file… In your Blynk Libraries folder for Arduino… mine is located here

Yes I know, what I meant is this:

If I delete the included BlynkSimpleShieldEsp8266.h in my Arduino sketch, it won’t compile.

Ahh… well, I don’t know what he is referring to in that statement?? Might even be a typo as I can’t even find that file with a .cpp extension on my PC.

But it is not in reference to removing the *.h library in the sketch… that much I know :slight_smile:

Can you give some example code for point 1? :grin::grin:

Thank you…

What is wrong with the example code already provided for point 1?

Aah nothing wrong, i just not really understand where to locate that code in my sketch, but now maybe l’m understand.

Update: I already follow this tutorial. If i get “Not connected to Blynk server”, then automatically reconnecting. But why if i get “[13778] Failed to connect WiFi”, then stop reconnecting?

Now step 2 and 3 work too. I needed to place the wdt_reset(); in the BlynkSimpleShield8266.h and in the setup of my Arduino Sketch.