Non blocking code

hello, i’m tryng to use this project below:

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

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

IPAddress local_IP(192, 168, 1, 212);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);

const int BUTTON = 2; //collegare al pin D4 nodemcu esp8266
const int RELE = 4; //collegare al pin D2 nodemcu esp8266

int BUTTONstate = 0;
boolean flag = true;
int i=0;

void setup()

{
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS)) {
  Serial.println("STA Failed to configure");

  }
 // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  delay(10);



ESP.wdtDisable();
ESP.wdtEnable(WDTO_8S);

  Blynk.begin(auth, ssid, pass);
  delay(20);
  pinMode (BUTTON, INPUT);
  pinMode(RELE, OUTPUT);
  pinMode(0, LOW);

}

void loop()

{

  Blynk.run();
  BUTTONstate = digitalRead(4);

  if  ( (BUTTONstate == 1) && (flag == true)) {
    for (i = 0; i < 3; i++) {
      Blynk.notify("Allarme in corso");
      flag = false;
      delay (5000);
    }

When it reach “for” and its “delay” , the code become blocking.

How can I do to have the three notify without blocking code?
Is it possible?

Thanks Fabio

First, you have to clean your loop like this :

void loop()
{
  Blynk.run();
}

use interrupt or timer to read button state , and remove delay(5000) replace it by a timer.

Dear, you should use Timer instead of delay, following link will help you out, you can also try yield(); after delay. Good Luck!

thanks for yours suggestions, but I don’t know how I can use timer in this case.
Have you an example to do it? I have read the link but i didn’f found what I need.

Thanks Fabio

Read this document:

It explains why you should have a minimalistic void loop, and gives an example of using a timer to call functions rather than having all the code in your void loop along with a delay to control timing.

Pete.

Even “clean” code can run into blocking problems when the loops in your external functions run too long.

In a pinch, you can add an additional Blynk.run(); statement into the offending loop. For ESP8266 users who run into watchdog timeout crashes, add a delay(0); into the crashing loop.

1 Like

I read a lot today and I found this example:

 void notifyOnButtonPress()
 { 
 // Invert state, since button is "Active LOW"
 int isButtonPressed = !digitalRead(BUTTON);
 if (isButtonPressed) {
 Serial.println("Button is pressed.");
    
// Note:
//   We allow 1 notification per 5 seconds for now.
Blynk.notify("Allarme in corso");   

}
}

This could clean the loop, but I couldn’t use for cycle to have three notify , one in a minute for three nminute becouse it is blocking.
Is the upper code correct for my use?
thanks Fabio

That’s correct :stuck_out_tongue_winking_eye:

you can use timer to call blynk.notify
Try that

void notifyOnButtonPress()
 { 
 // Invert state, since button is "Active LOW"
 int isButtonPressed = !digitalRead(BUTTON);
 if (isButtonPressed) {
 Serial.println("Button is pressed.");
Notify(); //first time, immediately .
timer.setTimer(60000L, Notify, 3);  //  every 60 sec, 3 times more
  }
}
void Notify()
 { 
Blynk.notify("Allarme in corso");   
}

Thanks for code, but I have some problems :
i can see the state of button on dashboard when changing, but not any notify;

on serial monitor I can see the connection to server blynk but I can’t see " button is pressed";
This is the code used:

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
BlynkTimer timer;

char auth[] = "************";
 // Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "*************";
char pass[] = "************";
IPAddress local_IP(192, 168, 1, 212);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
const int BUTTON = 2; //collegare al pin D4 nodemcu esp8266
const int RELE = 4; //collegare al pin D2 nodemcu esp8266

void setup()
{
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS)) {
    Serial.println("STA Failed to configure");
  }
  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  delay(10);
  //**    can be commented out, test only
  Serial.begin(115200);                           // Open serial console.
  Serial.println();
  Serial.println("Connecting to " + String(ssid));      // Connected to WiFi network
  //**
  Blynk.begin(auth, ssid, pass);
  delay(20);
  pinMode (BUTTON, INPUT);
  pinMode(RELE, OUTPUT);
  pinMode(0, LOW);
  //**    can be commented out, test only
  Serial.println(WiFi.localIP());                    //this is local IP for this board
  Serial.println("WiFi connected");

}
void notifyOnButtonPress()
{
  // Invert state, since button is "Active LOW"
  int isButtonPressed = !digitalRead(BUTTON);
  if (isButtonPressed) {
    Serial.println("Button is pressed.");
    Notify();
    Blynk.notify("Allarme in corso");
    timer.setTimer(60000L, Notify, 3);

  }
}
void Notify()
{
  Blynk.notify("Allarme in corso");
}


void loop()
{
  Blynk.run(); // all the Blynk magic happens here
  timer.run(); // BlynkTimer is working...
  Blynk.syncAll(); // This synchronises all pins
}

thanks Fabio

I don’t see any interrupt or timer to check physical button state in your code :thinking:

you could probaly use something like that

 // Setup a function to be called every 500 ms
  timer.setInterval(500L, notifyOnButtonPress);

else you can use interrupt to check when button is pressed.

1 Like

could i write this line in the loop?

It goes in void setup.

And PLEASE remove this from your void loop:

Pete.

could I write Blynk.syncAll(); in the void setup too?

Why do you need it?

Pete.

yes, it is very important for the case, and it works fine…

No it doesn’t work fine. It causes all sorts of problems with the Blynk server when you have it in the void loop.
But, what function do you believe it serves in your code?

Pete.

i need syncronization of the app to the lamp: I must know the right state of lamp without turn on and off the button when have a blackout

Blynk.syncAll doesn’t synchronise the app with the device, it synchronises the device with the app - which is very different…

If, after a power outage, you want the lamp to be in whatever state the app shows, then add a BLYNK_CONNECTED callback function and put your Blynk.syncAll in there.

However, doing this can have safety/cost implications. If you leave the house when the power or internet connection is off, and the lamp is off, then it may come on (because that’s the state in the app) when you don’t actually want it to be on. Think through the scenario carefully, and think which is the master system, and which you want to synchronise to that.
If the lamp is the master system then do t use Blynk.syncAall.

Pete.

1 Like

I would like to keep the status set by the application: if I had turned on the lamp from app, when the power returns, it must remain on. On the contrary, it must turn off
Fabio

If you want to keep the state of the lamp in any cases (power lost, reset, etc…) you have to save the state into the spiffs.