Wifi connection timeout

Hello everyone, I’m making a garden watering and lights controller and want to also use Blynk as a controlling measure in my garden.
I have a standalone RTC and do not use the Blynk RTC Widget - meaning I dont rely on Blynk to run my controller.
That being said, I was wondering what is the best way to configure Blynk with my Wifi network while restricting the time it takes for Blynk to try to connect to the network (so that my program will continue and not get stuck be trying to connect a wifi network the might not work ).
I am thinking of a way to go like -

  1. Try to connect for 15 seconds
  2. If connected all good
  3. If not - try again in 1 minute (by intervals or RTC)
  4. repeat.

You don’t need an external RTC for that.

thank you, another question if i may -
im using a physical button in my project, which i monitor constantly for press. using the serial monitor i noticed the the blynk.run function is making my program get stuck for a few seconds every other time. the blynk.run function is in my loop.
Can i read the blynk commands coming from the app every X seconds?
ty

Due to it nature of a networking link to a server, Blynk.run() needs the priority of process.

Proper timing of your code, AKA not running it all in the void loop(), but using BlynkTimer function loops, as well as use of interrupts for external buttons, etc. is required to balance everything.

If you use a timer to sample the physical button, say every 250 milliseconds then you’ll probably find that it works really well. You’ll get some denouncing effect by doing it that way, and you’ll never have to keep the button pressed for more than 1/4 second before the button press is identified and auctioned. On average the button press will be detected after just 1/8 second and it’ll feel responsive without any noticeable lag.

You’ll only normally need to use interrupts if you’re trying to count incoming pulses from something like an anemometer, where you can’t afford to miss any of the pulses.

Either way, you certainly don’t need to sample the button constantly.

Pete.

Thank you so much for the answer, actually I do sample the button once every 280millis using intervals , not the timer function, perhaps I will switch to the timer function later on.

Anyways, the problem still stays, blynk.run() still lags my whole program. Fortunately I found online a method to run blynk.run() only if WiFi.status()==WL_CONNECTED - meaning nodemcu it’s connected to a WiFi network ( not necessarily to the blynk server ).

I’m currently on my mobile phone, when I’ll get to my laptop I’ll submit the code here if you would like to advise me on some improvements.

Thanks!

?? A timer function IS an interval function.

Sound like a good idea :slight_smile:

Okay before I post my code I want to explain what is the purpose of it and what it should do.
My esp8266 is going to be in charge of my solar energy usage in my garden, which includes watering with an electronic water valve and turning on with a Relay some LED Strips.
With the following tasks:

  1. Watering -
  • 2 periods, one at early morning and one in the evening in which it will water for some time.
  • Pushing a physical button or a Blynk button while it is one of the periods will skip the current period
  • Pushing the same button while it not a watering period will water for X time =“force watering”.
    in case watering period is happening while “force watering” is on, force watering will stop and water period will continue is usual.
  1. Lights
  • Currently not implemented in the code, basicaly the same as the watering just with one period from the evening to 1AM, with the option of pushing a button for turning on and off.

Note : This project is in use for 6 months in my garden with an arduino uno. The original reason for which I am moving to the NodeMCU is that I wanted to add an OLED Display and simply the uno does not have enough memory. So by moving to the NodeMCU I said to myself - Why not involving Blynk also :slight_smile:

For your eyes and advice -

#define BLYNK_PRINT Serial
#include <BlynkSimpleEsp8266.h>
char auth[] = "";
char ssid[] = "";
char pass[] = "";

//Display Libraries
#include "SSD1306Wire.h"
SSD1306Wire display(0x3c, D3, D5);
#include "OLEDDisplayUi.h"
#include "images.h"
OLEDDisplayUi ui(&display);

//RTC Libraries
#include <TimeLib.h>
#include <WidgetRTC.h>
WidgetRTC rtc;


//Pins Defining
int WATER_RELAY_PIN = 16; //D0
int WATER_BUTTON_PIN = 5; //D1
int LIGHT_RELAY_PIN = 4; //D2
int LIGHT_BUTTON_PIN = 0; //D3

//Timed Actions Defining
int WATER_START_1_HOUR = 6;
int WATER_START_1_MINUTE = 45;
int WATER_STOP_1_HOUR = 7;
int WATER_STOP_1_MINUTE = 15;
int WATER_START_2_HOUR = 16;
int WATER_START_2_MINUTE = 95;
int WATER_STOP_2_HOUR = 17;
int WATER_STOP_2_MINUTE = 20;
int TIME_TO_START_LIGHTS = 19;
int TIME_TO_STOP_LIGHTS = 1;

// Cacculating Watering Time To Double
double WATER_START_DOUBLE_1 = WATER_START_1_HOUR+(double(WATER_START_1_MINUTE)/60);
double WATER_STOP_DOUBLE_1 = WATER_STOP_1_HOUR+(double(WATER_STOP_1_MINUTE)/60);
double WATER_START_DOUBLE_2 = WATER_START_2_HOUR+(double(WATER_START_2_MINUTE)/60);
double WATER_STOP_DOUBLE_2 = WATER_STOP_2_HOUR+(double(WATER_STOP_2_MINUTE)/60);

//Control and Managment booleans
boolean wateringTime=false;
boolean isWatering = false;;
boolean forceWatering = false;
int skippedWaterPeriod = 0;
long startForceWateringTimeStamp;
long FORCE_WATERING_TIME_IN_MS = 9000;

boolean isLights = false;
boolean forceLights = false;
boolean lightsTime = false;

//Buttons
boolean lastWaterButtonState = false;
boolean lastLightsButtonState = false;

//runWaterLogic timing ( readCounterLimit X blynkAndButtonRead timing) == 2500ms
int readCounter=0;
int readCounterLimit=10;

//Debugging
int logCounter = 0;


BlynkTimer timer;

void setup()
{
  Serial.begin(115200);
  pinMode(WATER_RELAY_PIN, OUTPUT);
  pinMode(WATER_BUTTON_PIN, INPUT);
  pinMode(LIGHT_RELAY_PIN, OUTPUT);
  pinMode(LIGHT_BUTTON_PIN, INPUT);
  stopWatering(); // Stopping watering as a starting point.
  WiFi.begin(ssid, pass); // Connection to a wifi network
  Blynk.config(auth); // Connection to Blynk servers, 5 seconds timeout
  timer.setInterval(250L, blynkAndButtonRead);
 // timer.setInterval(2500L, runWaterLogic); // Watering methods
  timer.setInterval(15000L, rtcCheck); // RTC Module time update every 15 seconds
}



void loop(){
  timer.run();
  // Data updates
  //rtcCheck(); //RTC Module currently not connected - 
  //ui.update(); //Screen updating
    if (readCounter>readCounterLimit){
      runWaterLogic();
      readCounter = 0;
  }
}
void blynkAndButtonRead(){
  if (WiFi.status()==WL_CONNECTED){
    Blynk.run();
    Serial.println("Blynk timer run");
  }
  waterButtonListen();
  readCounter++;
  
}

BLYNK_CONNECTED() {
  // Synchronize time on connection
  rtc.begin();
}
void runLightsLogic(){
  
}
void runWaterLogic(){
  Serial.println();
  Serial.print("========== ");
  Serial.print(logCounter++);
  Serial.print(" ==========");
  Serial.println();
  
  wateringTime=waterTimeCheck();
  boolean lastWateringTime=wateringTime;

  //Timed Watering
  if(wateringTime && skippedWaterPeriod==0){
    Serial.println("It is watering time and not a skipped period");
    startWatering();
  }
  if(skippedWaterPeriod>0){
    checkSkippedWaterPeriod();
  }
  if(forceWatering){
    checkForceWatering();
  }
  if(!wateringTime && lastWateringTime!=wateringTime){
    stopWatering();
    Serial.println("Watering time is over");
  }
}

void checkSkippedWaterPeriod(){
  Serial.println("--Checking is skip period has passed--");
  Serial.print("Checking if current time - ");
  Serial.println(getTimeAsDouble());
  Serial.print("Is between ");
  Serial.print(WATER_STOP_DOUBLE_1);
  Serial.print(" and ");
  Serial.println(WATER_START_DOUBLE_2);
  Serial.print("Or is between ");
  Serial.print(WATER_STOP_DOUBLE_2);
  Serial.print(" and ");
  Serial.println("23.99 ");
    if (WATER_STOP_DOUBLE_1 < getTimeAsDouble() && getTimeAsDouble() < WATER_START_DOUBLE_2) {
    Serial.println("Watering range 1 skip period has passed");
    skippedWaterPeriod = 0;
  }

  if (WATER_STOP_DOUBLE_2 < getTimeAsDouble() && getTimeAsDouble() < 23.99) {
    Serial.println("Watering range 2 skip period has passed");
    skippedWaterPeriod = 0;
  }
}

void checkForceWatering(){
  Serial.println("Force watering calculation begun");
  if (startForceWateringTimeStamp == 0) {
    startForceWateringTimeStamp = millis();
    Serial.println("Force watering begin is");
    Serial.println(startForceWateringTimeStamp);
  }  if (millis() <= startForceWateringTimeStamp + FORCE_WATERING_TIME_IN_MS) {
    Serial.println("Force watering begun");
    Serial.println("Count is:");
    Serial.println(millis());
    forceWatering = true;
  } else {
    Serial.println("Force watering stopped");
    stopForceWatering();
  }
}

void waterButtonListen(){
  boolean currentState = digitalRead(WATER_BUTTON_PIN);
  if(currentState!=lastWaterButtonState){
    Serial.println("Water button state changed");
    if (currentState==true){
      Serial.println("Water button pressed");
      Serial.println("++++++++++++++++++++++++++++++++++");
      waterButtonLogic();
    }else if(currentState==false){
      Serial.println("Water button Released");
    }
  }
  lastWaterButtonState=currentState;
}
void lightsButtonListen(){
  
}

void waterButtonLogic(){
  if (wateringTime){
    Serial.println("It is watering time and button pressed");
    skipCurrentWatering();
  }
  if(!wateringTime && forceWatering){
    Serial.println("Force watering stop");
    stopForceWatering();
  }
  else if(!wateringTime && !forceWatering){
    Serial.println("Force watering begin");
    startForceWatering();
  }
  
}


void skipCurrentWatering(){
  Serial.println("Skipping current timed watering");
  double skippedWaterTimestamp = getTimeAsDouble();
  stopWatering();
    if (WATER_START_DOUBLE_1 <= skippedWaterTimestamp && skippedWaterTimestamp < WATER_STOP_DOUBLE_1) {
    Serial.println("Watering range 1 is skipped");
    skippedWaterPeriod = 1;
  }

  if (WATER_START_DOUBLE_2 <= skippedWaterTimestamp && skippedWaterTimestamp < WATER_STOP_DOUBLE_2) {
    Serial.println("Watering range 2 is skipped");
    skippedWaterPeriod= 2;
  }
}

void startForceWatering(){
  startWatering();
  forceWatering=true;
}
void stopForceWatering(){
  stopWatering();
 Serial.println("Force watering elapsed time is ");
  Serial.println((millis()-startForceWateringTimeStamp));
  startForceWateringTimeStamp = 0;
  Serial.println("Resetting force watering time stamp");
  Serial.println("Stopping force watering");
  forceWatering=false;
}

boolean lightsTimeCheck() {
  if (TIME_TO_START_LIGHTS > TIME_TO_STOP_LIGHTS) {
    if ((TIME_TO_START_LIGHTS <= getCurrentHour() && getCurrentHour() <= 23) || (0 <= getCurrentHour() && getCurrentHour() < TIME_TO_STOP_LIGHTS)) {
      return true;
    }
  } else {
    if ((getCurrentHour() >= TIME_TO_START_LIGHTS && getCurrentHour() < TIME_TO_STOP_LIGHTS)) {
      return true;
    }
  }
  return false;
}

boolean waterTimeCheck() {
  Serial.println("Checking if watering time is now");
  Serial.print("Now = ");
  Serial.println(getTimeAsDouble());
  if (WATER_START_DOUBLE_1 <= getTimeAsDouble() && getTimeAsDouble() < WATER_STOP_DOUBLE_1) {
    Serial.println("Watering range 1 is now");
    return true;
  }

  if (WATER_START_DOUBLE_2 <= getTimeAsDouble() && getTimeAsDouble() < WATER_STOP_DOUBLE_2) {
    Serial.println("Watering range 2 is now");
    return true;

  }
  return false;
  Serial.println("Watering time is not now");
}


void startWatering() {
  if (!isWatering) {
    digitalWrite(WATER_RELAY_PIN, HIGH);
    isWatering = true;
    Serial.println("WATERING ACTIVATED");
  }
  else{
    Serial.println("startWatering function activated but watering is already on");
  }
}

void stopWatering() {
  if (isWatering) {
    digitalWrite(WATER_RELAY_PIN, LOW);
    isWatering = false;
    Serial.println("WATERING DEACTIVATED");
  }
  else{
    Serial.println("stopWatering function activated but watering is already off");
  }
}


//RTC and Timing
void rtcCheck(){
    //now = clock.getDateTime();
    Serial.println("RTC Clock Checked");
  }
int getCurrentHour() {
  return int(hour());
}

double getCurrentMinute() {
  return int(minute());
}
double getTimeAsDouble() {
  return double(hour()) + (double(minute()) / 60);
}