SyncPhysicalButton.ino modify

Hello,
What I’m trying to do is to modify the SyncPhysicalButton.ino file that I have found in the blynks github and make it work with a one way physical switch.

My project is based on controlling a relay from a one way wall physical switch and also control the relay from Blynk button widget.
I managed to make the two of them work but if I open the relay from the wall switch the button widget won’t update so I found this code and it worked fine but for a physical push button and not for my one way switch.

The SyncPhysicalButton.ino file:

Since the App/Device is unable to physically walk over and flip your physical switch, it will not synchronize :stuck_out_tongue:

Although I did see a post here somewhere how a servo was used to physically flip a switch back and forth.

It can Synchronize with a push button why it can’t with a switch?? I’m trying to figure this question the past week without any luck…

Fairly sure I just answered that already :stuck_out_tongue: While a device can send a signal to the App to “flip” a virtual switch to it’s opposite state, there is no such command in any programming language that can physically flip a physical switch without mechanical intervention.

Unfortunately you haven’t understood my problem…

What I’ve tried so far :
I tried to control the relay only with the physical switch and without Blynk. It worked after some searching for INPUT_PULLUP.
Then I tried to control the relay with the button widget of blynk and a virtual pin.
Tried to merge them and finish my project. It works correctly. For example if I open the relay from the switch it turns on and if I close the relay from the app it also turns off.
The problem is :
When I open the relay from the switch the widget button don’t indicate as on.
If I open the relay from the widget button and close the relay from the switch the widget button stays on instead of going off.

After lots of searching I came across the SyncPhysicalButton.ino file and uploaded it to the ESP8266 instantly (with the modification for wifi virtual pin relay pin and switch pin) and realized that it works only for a push button so I tried to examine the code and add the useful parts to my code. This was a terrible mistake and the relay end up flickering on off when I turn the switch on.

I hope I made things a little bit clearer.
I’m not trying to automatically turn on and off the switch with magic I want the switch to update the widget button

I am fairly well versed in English and understood what you wrote :wink:

… Thus you might have started with that :stuck_out_tongue_winking_eye:

The only way your device will know if the switch has moved, or that whatever the switch is controlling has changed state, is with another sensor of some sort… either a current sensor on the wiring that the switch is activating/deactivating, or with some form of indication from the switch itself (i.e optical sensor or use a DPDT switch, one for the action, one for feedback… etc… )

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>

#include <BlynkSimpleEsp8266.h>


char auth[] = "YourAuthToken";


char ssid[] = "YourNetworkName";

char pass[] = "YourPassword";


void setup()

{

  // Debug console

  Serial.begin(9600);


  Blynk.begin(auth, ssid, pass);
    pinMode(13, OUTPUT)
    pinmode(9, INPUT_PULLUP)
}

int btnstate;
BLYNK_WRITE(V3){
    int btnstate = param.asInt();
    digitalWrite(13, btnstate)
}


void loop()

{

  Blynk.run();
    int status = DigitalRead(9);
    If (status == 1){
        digitalWrite(13, HIGH);
        Blynk.virtualWrite(V3, HIGH);
    }else {
        digitalWrite(13, LOW);
        Blynk.virtualWrite(V3, LOW);
    }

}

This is the code that worked but made a new problem… The button widget is ON and the physical switch is off. If I turn on the switch the button widget will go crazy for half a second and the relay will go on off and then on again very fast.
Is there a solution for this problem?

All of this is running at hundreds/thousands of times a second… aside from being advisable to not put code like this in your void loop() when running Blynk… you may also be running into switch bounce (Google that).

And this should be up before the void setup()

And this should also be declared Globally.

#define BLYNK_PRINT Serial



#include <ESP8266WiFi.h>

#include <BlynkSimpleEsp8266.h>


char auth[] = "YourAuthToken";


char ssid[] = "YourNetworkName";

char pass[] = "YourPassword";

int btnstate;


void setup()

{

  // Debug console

  Serial.begin(9600);


  Blynk.begin(auth, ssid, pass);
    pinMode(13, OUTPUT)
    pinmode(9. INPUT_PULLUP)
}


BLYNK_WRITE(V3){
    int btnstate = param.asInt();
    DigitalWrite(13, btnstate)
}


void loop()

{

  Blynk.run();
    int status = DigitalRead(9);
    int priv = 0;
    
    if (status == 1 && priv == 0){
        digitalWrite(13, HIGH);
        Blynk.virtualWrite(V3, HIGH);
        priv = 1;
    }
    if (status == 0 && priv == 1) {
        digitalWrite(13, LOW);
        Blynk.virtualWrite(V3, LOW);
        priv = 0;
    }

}

Yes forgot some things there… (excuse the bad coding in Greece right now is 1 am and I’m creating similar code with the tested ones right now from arduinodroid)

If int status is in global how will it get updated when the switch is on or off?

You still have unwanted code in your void loop()

Use timers or interrupts, not rapid polling.

https://playground.arduino.cc/Code/Interrupts

The scope of the variable has absolutely nothing to do with sensors… it has to do with whether a variable can be used only in the function it is declared in, or anywhere in the sketch.

https://playground.arduino.cc/Code/VariableScope

PS, teaching how to program is NOT really what this Blynk forum is about :wink:

:joy::joy::joy: Obviously…
Ok so the problem right now is:
In the beginning button widget is off and switch is off
Turn on button widget
Relay goes on
Turn on switch
Button widget goes on then off and finally on
And same with the relay

I searched about switch bounce and I don’t think that this is the problem because it happens to both and relay and widget… I might be wrong. If this is the case can you suggest me how to fix it Google haven’t done a great job

If the contacts on the wall switch ‘bounce’ then any code that is run when the switch is activated will be executed by the bouncing of the contacts. As you code changes the state of both the relay and the widget button then of course bounce will affect both.

However, if the results are consistent and 100% repeatable each time then it may not be switch bounce.

I have a feeling that the problem is being caused by a sort of feedback loop. The physical switch changes the state of the widget button and this then flips the power in the opposite direction again. It’s not until the next time around the loop that the physical switch state is read again and the relay state stabilizes.
You’d probably need an If statement in the BLYNK_WRITE(V3) routine that mirror’s what’s happening with the physical switch.

The easiest way to diagnose exactly what’s happening is to put some serial monitoring code in your sketch and see if the process of activating the switch triggers the BLYNK_WRITE(V3) code.

Having said all of that, before ytou do anything else you need to move everything out of the void loop and into it’s own function that’s called by a timer (except Blyn.run of course) as @Gunner has already said.

Pete.

#define BLYNK_PRINT Serial


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

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "xxxxxx";

char ssid[] = "xxx";
char pass[] = "xxxx";

const int relayPin = 13;
const int btnPin = 14;

BlynkTimer timer;

void checkPhyButton();

int btnstate = LOW;
int relaystate = LOW;

BLYNK_WRITE(V3)
{
  relaystate = param.asInt();
  digitalWrite(relayPin, relaystate);
}

void checkPhyButton()
{
  if(digitalRead(btnPin) == LOW){
    btnstate = LOW;
    if(relaystate == HIGH){
      relaystate = LOW;
      digitalWrite(relayPin, relaystate);
      Blynk.virtualWrite(V3, relaystate);
    }
  } else {
    btnstate = HIGH;
    if(relaystate == LOW){
      relaystate = HIGH;
      digitalWrite(relayPin, relaystate);
      Blynk.virtualWrite(V3, relaystate);
    }
  }
}

void setup()
{
  // Debug console
  Serial.begin(9600);

  Blynk.begin(auth, ssid, pass);

  pinMode(relayPin, OUTPUT);
  pinMode(btnPin, INPUT_PULLUP);
  digitalWrite(relayPin, relaystate);

  timer.setInterval(100L, checkPhyButton);
}

void loop()
{
  Blynk.run();

  timer.run();
}

This is the latest code that i have tested,
the problem with this is that when i push the button widget the button and the relay goes to the physical switch state.

(i hope i fixed a bit the code …)

I saw what you suggested to add in the BLYNK_WRITE(V3) but I’m afraid I didn’t understand it completely. Can you explain it please?

You appear to be declaring void checkPhyButton() twice in your code.

I think that what’s happening in your code is this:

  • When the position of the physical switch changes, it activates the relay then updates the button widget on V3.

  • The change of state of the widget button on V3 is triggering the BLYNK_WRITE(V3) function, which toggles the relay again

  • Next time the timer checks the state of the physical switch the relay is updated again, and the the button widget on V3 is also updated, but this time it’s updated with the same value is before (the state doesn’t’ change), so the BLYNK_WRITE(V3) function isn’t triggered.

If you change the code in your void checkPhyButton() and BLYNK_WRITE(V3) functions to this, you’ll see what’s happening in the serial monitor:

void checkPhyButton()
{
  if(digitalRead(btnPin) == LOW){
    btnstate = LOW;
    if(relaystate == HIGH){
      relaystate = LOW;
      digitalWrite(relayPin, relaystate);
Serial.println("Relay pulled LOW by physical switch"); 
      Blynk.virtualWrite(V3, relaystate);
    }
  } else {
    btnstate = HIGH;
    if(relaystate == LOW){
      relaystate = HIGH;
      digitalWrite(relayPin, relaystate);
Serial.println("Relay pulled HIGH by physical switch"); 
      Blynk.virtualWrite(V3, relaystate);
    }
  }
}

BLYNK_WRITE(V3)
{
  relaystate = param.asInt();
  digitalWrite(relayPin, relaystate);
Serial.print("Relay set to "); 
Serial.print(relaystate); 
Serial.print(" by BLYNK_WRITE(V3) function"); 
}

If I’m correct and you’re seeing the physical switch and the button widget working against each other in the serial monitor
then you’ll need to use a flag which is set in your void checkPhyButton() function to indicate if the next update from BLYNK_WRITE(V3) should be actiuoned or ignored.
This flag would be reset next time the timer calls BLYNK_WRITE(V3) and the BLYNK_WRITE(V3) function would contain an ‘if’ statement that checked the status of the flag and only updated the relay if it was supposed to.

Pete.

Ok, i did what you said and i received this in the Serial Monitor:

Relay pulled LOW by physical switch
Relay pulled HIGH by physical switch
Relay pulled LOW by physical switch
Relay set to 1 by BLYNK_WRITE(V3) functionRelay pulled LOW by physical switch
Relay pulled HIGH by physical switch
Relay set to 0 by BLYNK_WRITE(V3) functionRelay pulled HIGH by physical switch

when i press the widget button this:
Relay set to 1 by BLYNK_WRITE(V3) functionRelay pulled LOW by physical switch
gets printed at the same time.

@Smackflad sorry, I was looking a your latest code, but trying to make sense of the results that you were seeing with your previous code, so some of my comments about the cause are obviously nonsense!

In your latest code, the checkPhyButton function doesn’t appear to have any way of taking in to account what the widget button is doing. This means that the widget button will change the state of the relay, then the checkPhyButton function will immediately change it back to whatever state the physical button is in - which is exactly what you’re seeing.

You need to use a flag to I’d identify what the actual power state should be. A change to the physical switch will toggle the power state, as will a change to the widget button.

I think that this is what your original code was trying to achieve in the checkPhyButton function, but the corresponding logic hadn’t been incorporated into the widget button code.

Pete.

The last 4 hours I’m trying different combinations of variables and states non-stop…
I can not figure it out
I’d love the changes that I have to do in the code please…

Latest code:

#define BLYNK_PRINT Serial


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

char auth[] = "xxx";

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

const int relayPin = 13;
const int btnPin = 14;

BlynkTimer timer;


int btnstate = LOW;
int relaystate = LOW;
int widstate = LOW;
int btnflag = LOW;
int widflag = LOW;

BLYNK_WRITE(V3)
{
  widstate = param.asInt();
  if (widstate == widflag)
  {
    if(btnstate == 1 && widstate == 0)
    {
      widstate = 0;
      widflag = 1;
      Serial.print("Widget buton is ");
      Serial.println(widstate);
      Serial.print("Widget flag is ");
      Serial.println(widflag); 
    }
    widflag = !(widstate);
    Serial.print("Widget buton is "); 
    Serial.println(widstate);
    Serial.print("Widget flag is ");
    Serial.println(widflag);
    digitalWrite(relayPin, widstate);
  }
}

void checkPhyButton()
{
  btnstate = digitalRead(btnPin);
  if (btnstate == btnflag)
  {
    btnflag = !(btnstate);
    Serial.print("Physical Switch is: ");
    Serial.println(btnstate);
    Serial.print("Phys flag is ");
    Serial.println(btnflag);
    Blynk.virtualWrite(V3, btnstate);
    digitalWrite(relayPin, btnstate);
    Serial.println("1 state");
  }
}

void setup()
{
  // Debug console
  Serial.begin(9600);

  Blynk.begin(auth, ssid, pass);

  pinMode(relayPin, OUTPUT);
  pinMode(btnPin, INPUT_PULLUP);
  digitalWrite(relayPin, relaystate);

  timer.setInterval(100L, checkPhyButton);
}

void loop()
{
  Blynk.run();

  timer.run();
}

with this code:
switch turn relay on and off
switch controls the widget button
widget button controls the relay

Only problem:
switch is on then widget button turns on and relay turns on
after this if i turn off relay from widget button nothing happens.
to make it work i have to turn off the relay from widget button then turn it on and then turn it off again.

My thoughts:
Because of the fact that the switch controls the widget button the data of the widstate and widflag wont change because BLYNK_WRITE(V3) wont get triggered.
how can i trigger BLYNK_WRITE(V3) from checkPhyButton()???