I have a Pro subscription, and using an Adafruit HUZZAH32 Feather card. I’m also using Visual Code, PlatformIO with the Arduino framework.
I have converted two major projects from Blynk Legacy to Blynk IoT and have learned a lot. This two Blynk platforms are very different yet got much in common regarding the coding. I have spent hour after hours to make my code stable and bug-free, but I have discovered some things on my way. One of the most critical experience is that one can not trust Blynk.connected()! I have added some of my code in this message, and have done a lots of tests to confirm this issue. I’m using FreeRTOS quite extensively a have a own task just to handle Blynk.run(). The problem is that Blynk.connected() returns true but there is no WiFi. The reason I can claim this is because WiFi.RSSI() returns 0. My device is also running a small web-server which is unavailable when the WiFi fails. Even my WiFi-router is not abel to detect the device as online. But Blynk.connected() keep returning true. I’m also using ElegantOTA (I know that Blynk got an OTA, but haven’t tested it yet) and WebSerial. Could this cause the problem?
Nevertheless, the solution for me has been to run a ping() (ESP32Ping) check every minute to the local gateway (very often 192.168.10.1), and to call ESP.restart() if the ping fails.
I have to admit that Blynk.connected() do not fail very often, but it does! In my tests it has been around once every 3 days. I have now performed an installation at a factory plant in northern Norway to monitor a process on a machine. It is 500 km away from my office, and is therefore very hard to reach. I had to rest assure that the device was always online and that Blynk is connected before I did the installation. If this conditions fails, the device should perform an reboot and hopefully regain a stable state. In my tests before implementing at the factory, I luckily discovered this Blynk.connected() issue, and implemented a workaround utilizing ping.
Here are some pieces of code regarding my BlynkRun() implementation. The priority of the BlynkRun task is always the highest among the normal tasks, only a special watchdog task (not shown here) got a higher priority. In my test I print out the BlynkRunCtr, BlynkRunTaskCtr, Blynk.connected(), BlynkReconnectAttempts and WiFi.RSSI() every second just to check the status of the Blynk connection.
/*
platformio.ini:
;-------------------
[env:MyBlynkConnectedTest]
platform = espressif32
board = featheresp32
framework = arduino
upload_speed = 512000
monitor_speed = 115200
lib_deps =
ayushsharma82/WebSerial@^1.3.0
ottowinter/ESPAsyncWebServer-esphome@^3.0.0
ayushsharma82/AsyncElegantOTA@^2.2.7
blynkkk/Blynk@^1.1.0
marian-craciunescu/ESP32Ping@^1.7
;-------------------
*/
#include <Arduino.h>
#define BLYNK_TEMPLATE_ID "xxxxxxxxxxxx"
#define BLYNK_AUTH_TOKEN "yyyyyyyyyyyyyyyyyyyyyyyyy"
#include <BlynkSimpleEsp32.h>
const char *auth = BLYNK_AUTH_TOKEN;
const char *ssid = "YourNetworkName";
const char *pass = "YourPassword";
#define BLYNK_CONNECT_TIMEOUT 10000 // 10 seconds
#define MAX_BLYNK_RETRIES 3
#define _TMPSTRING_SIZE 128
int BlynkReconnectAttempts=0;
long BlynkRunCtr=0L;
long BlynkRunTaskCtr;
long BlynkRun_Task_overruns_ctr=0L;
/**** Piece of my test code ****/
void X_CreateBlynkRunTask(void);
void PartsOfMyInitCode(void)
{ // This is code typically placed in setup()
Serial.begin(115200);
// xStartWatchdog(20); // Starts the watchdog with a 20 seconds timeout
Blynk.begin(auth,ssid,pass);
// MyWebSetup(); // Starts ElegantOTA and WebSerial
// xFeedWatchdog(10); // feeds the watchdog with 10 seconds timeout, also starts the Pinging
X_CreateBlynkRunTask();
}
void PartsOfMyTestLoopCode(void)
{ // this code is part of a task that runs once a second just to print out som status information
Serial.printf("BlynkRunCtr:%ld, BlynkRunTaskCtr:%ld, Blynk.connected():%d, BlynkReconnectAttempts:%ld, WiFi.RSSI():%d\n",
BlynkRunCtr, BlynkRunTaskCtr, (int)Blynk.connected(),BlynkReconnectAttempts, (int)WiFi.RSSI());
}
/**** My BlynkRun implementation ****/
void BlynkRun(void)
{
if (Blynk.connected())
{
Blynk.run();
BlynkRunCtr++;
}
else
{
char _szDateTime[MY_STR_TIME_LENGHT];
strLocalDateTime(_szDateTime);
Serial.printf("BlynkRun: %s Blynk not connected!\nTrying to reconnect...\n", _szDateTime);
BlynkReconnectAttempts++;
while (Blynk.connect(BLYNK_CONNECT_TIMEOUT) != SUCCESS)
{
if (++BlynkReconnectCtr > MAX_BLYNK_RETRIES) {
Serial.println("BlynkRun: Blynk not responding! Rebooting now!");
ESP.restart();
}
else
{
Serial.println("BlynkRun: New attempt to reconnect to Blynk");
}
}
strLocalDateTime(_szDateTime);
Serial.printf("BlynkRun: %s Blynk has reconnected successfully\n",_szDateTime);
}
}
/**** BlynkRun task implementation ****/
void X_BlynkRun_Task( void * pvParameters ){
TickType_t xLastWakeTime;
const TickType_t xFrequency = 100/portTICK_PERIOD_MS; // every 100 ms
BaseType_t xWasDelayed;
// Initialise the xLastWakeTime variable with the current time.
xLastWakeTime = xTaskGetTickCount();
BlynkRunTaskCtr=0;
while(1){
BlynkRun(); // Blynk.run
if (BlynkRunTaskCtr++ % 50 == 0)
{
// watchdog code not included here xFeedWatchdog(10); // feeds the watchdog every 5 seconds
}
// Wait for the next cycle.
xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency );
if (xWasDelayed == pdFALSE)
{
BlynkRun_Task_overruns_ctr++;
//Serial.println("X_BlynkRun_Task() xTaskDelayUntil caused no delayed");
}
}
}
/**** Starting the BlynkRun Task ****/
TaskHandle_t t_X_BlynkRun_Task;
void X_CreateBlynkRunTask(void)
{
Serial.println("Creating BlynkRun task");
xTaskCreate(
X_BlynkRun_Task, // Function to implement the task
"BlynkRun", // Name of the task
4096, // Stack size in words
NULL, // Task input parameter
1, // | portPRIVILEGE_BIT. Priority of the task. Higher number , higher priority. Max is 24
&t_X_BlynkRun_Task);
}