Detectar estado de la luz con optocoplador y Blynk [NodeMCU 3.0]

Hola, tengo este circuito diseñado con un NodeMCU 3.0:


El modulo optocoplador que uso es este:

Y el código que tengo es este:

#include <Blynk.h> 
#include <ESP8266WiFi.h> 
#include <BlynkSimpleEsp8266.h> 
#include <SPI.h> 
#include <SimpleTimer.h> 

SimpleTimer timer; 
char ssid[] = "xxxxxx"; 
char pass[] = "xxxxxx"; 
char auth[] = "xxxxxxx";
int BotonRele = 0;

BLYNK_WRITE(V5) { 
  BotonRele = param.asInt(); 
  } 
  
  void setup() { 
    pinMode(2, OUTPUT); 
    Serial.begin(9600); 
     Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100)); 
    timer.setInterval(2000L, activacion); 
  } 
    
  void loop() { 
    Blynk.run(); 
    timer.run(); 
  } 
      
  void activacion() { 
    if(BotonRele==1){ 
      digitalWrite(2, HIGH); 
      }
    else if (BotonRele==0){ 
      digitalWrite(2, LOW); 
    } 
 }

Necesito que en la aplicación Blynk el estado del botón virtual cambie según si la luz está encendida o apagada.
Para eso he implementado el optocoplador, pero no sé como hacer que lea el estado y lo cambie ya que también se usa el interruptor físico.

Ejemplo: Si apago la luz con el botón de la aplicación, enseñará «apagado» pero al encenderla con el interruptor físico, la aplicación seguirá enseñando «apagado».

Tu código es un código ejemplo de Blynk.
Que puedes decirnos del detector de 220VAC?

Qué optoacoplador tiene? l
Coloca el link a la página donde lo compraste, por favor.

http://s.aliexpress.com/2iUVnAJZ?fromSns=
Es este.

Moderador: No repitas lo que se lee arriba

Yo no veo de que optos se trata.
Si tu que lo tienes delante no puedes leerlo? No se como ayudarte.

Porque la pregunta? Por que, es posible que el sistema te de un pulso con cada cruce por cero, tmb es posible que no porque veo una capacitor electrolítico y es posible que esos pulsos sean para cargar dicho capacitor y que te de un pulso de nivel logico tal que sea tan simple como esta ON u OFF.

surbyte:
Yo no veo de que optos se trata.
Si tu que lo tienes delante no puedes leerlo? No se como ayudarte.

Porque la pregunta? Por que, es posible que el sistema te de un pulso con cada cruce por cero, tmb es posible que no porque veo una capacitor electrolítico y es posible que esos pulsos sean para cargar dicho capacitor y que te de un pulso de nivel logico tal que sea tan simple como esta ON u OFF.

No entiendo muy bien lo que me quieres decir.
El modulo optocoplador es este: https://www.aliexpress.com/item/1-Bit-AC-220V-Optocoupler-Isolation-Module-Voltage-Detect-Board-Adaptive-For-PLC-Isolamento-Fotoaccoppiatore-Module/32828243283.html

Sé recoger el valor del optoacoplador, pero lo que no sé es como decirle al Blynk que cambie el estado del botón de «Off» a «On» según se encienda o apague la luz con el interruptor físico.
No tengo mucha idea de electrónica o programar estos cacharros la verdad.

Olvida a Blynk. Conecta todo en un simple código con una entrada digital y que te diga ON OFF

Como si fuera un pulsador.
Cuando funcione me dices si funciona como supongo con estados estables para 220 o nada o si da pulsos.

surbyte:
Olvida a Blynk. Conecta todo en un simple código con una entrada digital y que te diga ON OFF

Como si fuera un pulsador.
Cuando funcione me dices si funciona como supongo con estados estables para 220 o nada o si da pulsos.

#define BLYNK_PRINT Serial
#include <Blynk.h> 
#include <ESP8266WiFi.h> 
#include <BlynkSimpleEsp8266.h> 
#include <SPI.h> 
#include <SimpleTimer.h> 
char auth[] = "xxxxx";
char ssid[] = "xxxxx";
char pass[] = "xxxxx";
SimpleTimer timer;
int BotonRele = 0;
int opto;

BLYNK_WRITE(V5) { 
  BotonRele = param.asInt(); 
  } 
  void setup() { 
    pinMode(2, OUTPUT); 
    pinMode(5, INPUT); 
    Serial.begin(9600); 
     Blynk.begin(auth, ssid, pass); 
    timer.setInterval(2000L, activacion); 
  } 
    
  void loop() { 
    opto = digitalRead (5);
    Blynk.run(); 
    timer.run(); 
  } 
      
  void activacion() { 
    if(BotonRele==1){ 
      digitalWrite(2, HIGH);
      if (opto==1){
       Blynk.setProperty(V5,"onLabel", "ON"); 
      }
    else if (BotonRele==0){ 
      digitalWrite(2, LOW); 
      if (opto==0){
       Blynk.setProperty(V5,"offLabel", "OFF"); 
    } 
 }

}
  }

Tengo esto, pero ya digo, soy un manco con el código y necesito ayuda con el mismo.
Con esto no leo el opto ni cambia el botón, sin el código para leer el opto el programa funciona bien para apagar y encender la luz desde la aplicación.

Para la proxima un par de consejos:

Los esquemas de Fritzing son sinceramente horribles para entender un esquema.
Intenta tu entender que dice ahí, yo no puedo.
No puede ampliarse el esquema y por lo tanto no se puede ver donde esta conectado qué?
Se puede suponer y con algún buen tiempo detectar que era aca y allá pero.. estamos para ayudar no para estar haciendo del Sherlock.
Perdona mi crítica pero .... llevo varios minutos para responder algo que con 2 minutos estaría.

Tu código además no esta comentado asi que de nuevo a deducir por los pines y lo que dice.

Algo tan simple como decir:
OptoDetector conectado a pin tal.
esto mira. yo he resuelto basado en lo que deduje que estan acá.

const byte BotonPin   = 0; 
const byte optoPin    = 5;
const byte relePin    = 2;

Para mi el RELE asi como esta conectado no funciona pero ya nos diras.
Los reles de 5V conectados a 3.3V no funcinan bien, suelen ponerse a vibrar.

Como debe ir conectado tmb esta explicado en el foro y en Documentación =>Indice de temas tutoriales

Ahora te paso un pequeño código con los pines conectados a los GPIOXX
cuando digo 0 es
GPIO0 o sea D3
GPIO2 o sea D4
GPIO5 o sea D1

const byte BotonPin   = 0; // GPIO0 o sea D3 
const byte optoPin    = 5;           // GPIO5 o sea D1 
const byte relePin    = 2;            // GPIO2 o sea D4
bool opto, optoAnt = false;         // variable para estado del sensor 220VAC. optoAnt para conocer cambios
bool status, statusAnt = false;    // variable de estado del pulsador conectado entre GND y pin D3

void setup() { 
    pinMode(relePin, OUTPUT); 
    pinMode(optoPin, INPUT); 
    pinMode(BotonPin, INPUT_PULLUP);

    Serial.begin(9600); 
}
    
void loop() { 
    opto = digitalRead (5);
    if (opto != optoAnt)
        Serial.println(opto?"ON":"OFF");
   optoAnt = opto; 
   delay(1000); // si no pongo una pausa se llena la pantalla del Monitor Serie.
    

    status = digitalRead(BotonPin);
    if (status && !statusAnt) {
        estado != estado;
    }
    if (estado)
        digitalWrite(relePin, LOW);   // activo RELE
    else 
        digitalWrite(relePin, HIGH);   // desactivo RELE
}

con este código veras el estado del sensor ON OFF que debería coincidir con la lampara.
Tambien presionando en el boton conectado a D3 podras activar/desactivar el RELE y por ende la lámpara pero si no conectas debidamente el RELE, asi como lo veo en tu esquema fallará.