I have to add a button in the app for a pin to work as expected

Hey guys! I have a problem with my project. I have an indoor control system. Lights turn on and off depending on the time set.
The program works almost perfectly except for one thing:
When i power up the device the only way the light turn on as it should is if I add a button with for that pin in the app and then erase it. After that the program works ok, until it reboots for whatever reason.
I don’t know what it could be happening.

Im using NodeMCU ESP8266 (via wifi) with blynk library v 0.6.1.
Blynk server, and app on MotoG5 with android 10.
Here’s my code:

#include <Wire.h>
#include "BlueDot_BME280.h"
#define builtLed0 2
#define builtLed1 16
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>


char auth[] = "HozCiU_f-EmZ92-Esnux3U-GoAwDlZ_b";
String currentTime;
char ssid[] = "Nahuel's Fiber";
char pass[] = "fernandez1";
float lastTemp;
float currentTemp;
float lasthum;
float currenthum;
long lightoffT;
int fotoperiodo;
long secs;
long minutooff;
long horaoff;
long horaon;
long minutoon;
String fp;

BlynkTimer timer;
WidgetRTC rtc;
WidgetTerminal term(V6);

BlueDot_BME280 bme280 = BlueDot_BME280();

void get_temphum(){
   lastTemp = currentTemp;
   lasthum = currenthum;
   currentTime = String(hour()) + ":" + minute();
   Blynk.virtualWrite(V1, currentTime); //updates current ESP time in the app.
   float temp = bme280.readTempC();
   float  hum = bme280.readHumidity();
   float  presion = bme280.readPressure();   
   
   currentTemp = temp;
   currenthum = hum;
   Serial.println(temp);
   Serial.println(bme280.readHumidity()); 
   Serial.println(presion);
   Blynk.virtualWrite(V2, temp);
   Blynk.virtualWrite(V3, hum);
   Blynk.virtualWrite(V4, presion);
 
   if (currentTemp > 27 and lastTemp<=27) {
    Blynk.notify("Floración: Temperatura alta. >27°C");
    term.println("HIGH TEMP!");
    term.flush();
   }
   else if (currentTemp < 16 and lastTemp>=16) {
    Blynk.notify("Floración: Temperatura baja. <16°C");
    term.println("LOW TEMP!");
    term.flush();
    }
    if (currenthum > 60 and lasthum<=60){
      Blynk.notify("Floración: Humedad alta. >60%");
      term.println("HIGH HUM!");
      term.flush();
    }
    else if (currenthum < 40 and lasthum>=40){
      Blynk.notify("Floración: Humedad baja. <40%");
      term.println("LOW HUM!");
      term.flush();
    }
   }
void light_stat(){ //Status indicator
  if (digitalRead(5)== HIGH){
    Blynk.virtualWrite(V0, 0);
  }
  else if(digitalRead(5)== LOW ){
    Blynk.virtualWrite(V0, 255);
  }
}
void blk_sync(){
  Blynk.syncAll();
  currentTime = String(hour()) + ":" + String(minute());
  
}

 //Enciende o apaga las luces segun fotoperiodo.
void light_time(){
  //Fotoperiodo 20/4.
  if (fotoperiodo == 1){
    fp = "Fotoperiodo: 20/4"; 
    secs = lightoffT;
    minutooff = ( secs %3600) /60;
    horaoff = secs / 3600;
    horaon = horaoff + 4;
    minutoon= minutooff;
    if (horaon >= 24){
      horaon= horaon - 24;
    }
    
    
    if (horaon == hour() and minutoon <= minute()){
      digitalWrite(5, LOW);
      term.println(F("Luces encendidas. FP: 20/4"));
      term.flush();
    }
    if (horaoff == hour() and minutooff<= minute()){
      digitalWrite(5, HIGH);
      term.println(F("Luces apagadas. FP: 20/4"));
      term.flush();
    }
  }
  if (fotoperiodo == 2){
    fp = "Fotoperiodo: 18/6";
    secs = lightoffT;
    minutooff = ( secs %3600) /60;
    horaoff = secs / 3600;
    horaon = horaoff + 6;
    minutoon= minutooff;
    if (horaon >= 24){
      horaon= horaon - 24;
    }
    
    if (horaon == hour() and minutoon <= minute()){
      digitalWrite(5, LOW);
      term.println(F("Luces encendidas. FP: 18/6"));
      term.flush();
    }
    if (horaoff == hour() and minutooff <= minute()){
      digitalWrite(5, HIGH);
      term.println(F("Luces apagadas. FP: 18/6"));
      term.flush();
    }
  }
  if (fotoperiodo == 3){
    fp = "Fotoperiodo: 12/12";
    secs = lightoffT;
    minutooff = ( secs %3600) /60;
    horaoff = secs / 3600;
    horaon = horaoff + 12;
    minutoon= minutooff;
    
    if (horaon >= 24){
      horaon = horaon - 24;
    }
   
    
    if (horaon == hour() and minutoon <= minute()){
      digitalWrite(5, LOW);
      term.println(F("Luces encendidas. FP: 12/12"));
      term.flush();
    }
    if (horaoff == hour() and minutooff <= minute()){
      digitalWrite(5, HIGH);
      term.println(F("Luces apagadas. FP: 12/12"));
      term.flush();
    }
  }
}
BLYNK_CONNECTED(){
  rtc.begin();
  Blynk.syncAll();
 
}
BLYNK_APP_CONNECTED(){
  Blynk.syncAll();
  
}
BLYNK_WRITE(V6){ //terminal widget
  String command = (param.asString());
  if (command == "getTime(on)"){
    
    term.println("Hora encendido: " + String(horaon) + ":" + String(minutoon));
    term.flush();
  }
  else if (command == "getTime(off)"){
    
    term.println("Hora apagado: " + String(horaoff) + ":" + String(minutooff));
    term.flush();
  }
  else if (command == "clear"){
    term.clear();
  }
  else if (command == "fp"){
    term.println(fp);
    term.flush();
  }
  else if(command == "luz.on"){
    digitalWrite(5, LOW);
    term.println(F("Luz Encendida."));
    term.flush();
  }
  else if(command == "luz.off"){
    digitalWrite(5, HIGH);
    term.println(F("Luz Apagada."));
    term.flush();
  }
  
}
BLYNK_WRITE(V8){//time input widget. sets lights off time.
  lightoffT = param.asLong();
  secs = lightoffT;
  minutooff = ( secs %3600) /60;
  horaoff = secs / 3600;
  light_time();
}
BLYNK_WRITE(V10){//photoperiod menu widget
  
  switch (param.asInt()){
    case 1:
      fotoperiodo = 1;
      break;
    case 2:
      fotoperiodo = 2;
      break;
    case 3:
      fotoperiodo = 3;
      break;
  }
}
void setup()
{
  // Debug console
  Serial.begin(9600);
  //BME280 config.
  bme280.parameter.communication = 0;
  bme280.parameter.I2CAddress = 0x76;
  bme280.parameter.sensorMode = 0b11; 
  bme280.parameter.IIRfilter = 0b000; 
  bme280.parameter.humidOversampling = 0b001;
  bme280.parameter.tempOversampling = 0b001;
  bme280.parameter.pressOversampling = 0b001;
  bme280.parameter.pressureSeaLevel = 1013.3; 
  bme280.parameter.tempOutsideCelsius = 15;  
  bme280.init();
  
 
  Blynk.begin(auth, ssid, pass);
  setSyncInterval(600);
  timer.setInterval(5000L, get_temphum);
  timer.setInterval(1000L, light_stat);
  timer.setInterval(1000L, blk_sync);
  timer.setInterval(60000L, light_time);
  
  digitalWrite(builtLed1, HIGH);
  digitalWrite(builtLed0, HIGH);
}


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

It seems to be your light_time() function that does the calculations about on/off times, and this function is called from a timer every 60 seconds.
Maybe it should be called at the end of BLYNK_WRITE(V8) so that new times are re-calculated when the value of V8 (the time input widget) changes, or when it is triggered by a Blynk.syncAll.

BTW, you don’t need 4 separate times, one timer can handle up to 16 events…

BlynkTimer timer;
  timer.setInterval(5000L, get_temphum);
  timer.setInterval(1000L, light_stat);
  timer.setInterval(1000L, blk_sync);
  timer.setInterval(60000L, light_time);
void loop()
{
  Blynk.run();
  timer.run();
}

It’s also good practice to add comments about what type of widget is attached to each virtual pin…

BLYNK_WRITE(V8) // Time input widget
{

Pete.

Thanks a lot for replying. I made the changes you suggested and I’m gonna see how it behaves. In about 15 mins lights should go on.
Anyway, it’s not clear to me why the program works ok after I add a button to control the lights pin.

Edit. Even after the changes i still have to add a button in order to lights to go on.

This is an odd way to sync, normally a syncAll() is only required when reconnecting to the server, not the app.

You have not clarified what pin/vpin you are needing to set your temporary button with, but syncing all pins/vpins every time the App connects might play a part in the issue.

Sorry, the pin I have problem is D1 or GPIO5.
I will change that and see what happens.

I remembered that even these commands doesn’t work. I mean, i get the response on the terminal, but the pin doesnt change its state until i asign a button to pin D1 and then erase it.

If you are using Blynk’s direct pin control (AKA NOT virtual pins and functions), then yes, the widget is what does the real “state change” work of that GPIO.

Basically, Blynk had two methods of controlling GPIO…

A) Directly, which is rather limiting (and doesn’t really require pinMode() as that is somehow built into the library operation).

B) Via Virtual Pins that call programed functions, that within those you can directly control GPIO the “normal” arduino way with proper pinMode(), digitalWrite(), etc.

And on that note… I do not see any pinMode() commands in your setup… better to have them then not.

In my experience, it is best to NOT mix the two methods.

You don’t have any pinMode commands in your void setup.

Pete.

Thanks again to all for replying.
Not having pinMode(5, OUTPUT); it’s the first thing I think of when I saw my program not working as i wanted.
But if I add that line. Then, the pin turns on and off every minute.
Should I try to go with virtual pin and assign a function that changes GPIO5 state depending on that virtual pin state?

Possibly. I’ve not dissected your code and stepped through it line by line to work out what is happening, and the code structure is rather messy.

I’d start by adding serial print statements that print-out your variable values at various points throughout the code along with messages that are verbose enough to allow you to understand which part of the code is being executed at the time.

Pete.

I gave a try at putting again the pinMode(5, OUTPUT); sentence and it seems that worked.
I may have another code mistake back then.
I’m gonna try it a few days to see if it works as it should.

Thanks a lot for your help.

PS: I took the time to make the code a little less messy and added comments to know what each function does.