How can I use a physical switch as input to a virtual pin/datastream

This is my first Blynk project, it is based on the Quickstart template on Free tier account. I can’t find anything on this.

I have a virtual switch on my phone that can activate a relay that supplies power to a light. It works fine, no issues. I’d like to add a physical monetary switch to the box that holds the ESP32 and relay module so someone without the app can turn the light off/on. Each press of the button would change the state of the light. I also want Blynk to know the state of the relay/light. If it was off and the button was pressed I want the light to come on and have the Blynk app on my phone show it is on.

How can I get a switch connected to a GPIO pin to ‘tell’ Blynk to (de)energize the relay? Can I simply control the pin directly with digitalWrite(relayPin,HIGH); or will that “break” Blynk ?

What is the best way to test the GPIO pin to see if the button is pressed? Can I put an IF to test the state of the GPIO to see if the button is pressed in ```void loop()```` or do I need an ISR.

Here is my sketch, any suggestions are welcome:


  This is a simple demo of sending and receiving some data.
  Be sure to check out other examples!
 *************************************************************/

// Template ID, Device Name and Auth Token are provided by the Blynk.Cloud
// See the Device Info tab, or Template settings
#define BLYNK_TEMPLATE_ID           "***"
#define BLYNK_DEVICE_NAME           "Quickstart Device"
#define BLYNK_AUTH_TOKEN            "***"

// Comment this out to disable prints and save space
#define BLYNK_PRINT Serial

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

char auth[] = BLYNK_AUTH_TOKEN;

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "***";
char pass[] = "***";

const int ledPin =33;//32;
const int relayPin =26;//32;

BlynkTimer timer;

// This function is called every time the Virtual Pin 0 state changes
BLYNK_WRITE(V0)
{
  // Set incoming value from pin V0 to a variable
  int value = param.asInt();

  // Update state
  Blynk.virtualWrite(V1, value);
}

BLYNK_WRITE(V4) // Executes when the value of virtual pin 0 changes
{
  if(param.asInt() == 1)
  {
    // execute this code if the switch widget is now ON
    digitalWrite(ledPin,HIGH);  // Set digital pin 2 HIGH
    digitalWrite(relayPin,HIGH);
    Serial.println("HIGH!");
  }
  else
  {
    // execute this code if the switch widget is now OFF
    digitalWrite(ledPin,LOW);  // Set digital pin 2 LOW   
    digitalWrite(relayPin,LOW); 
    Serial.println("low!");
  }
}

// This function is called every time the device is connected to the Blynk.Cloud
BLYNK_CONNECTED()
{
  // Change Web Link Button message to "Congratulations!"
  Blynk.setProperty(V3, "offImageUrl", "https://static-image.nyc3.cdn.digitaloceanspaces.com/general/fte/congratulations.png");
  Blynk.setProperty(V3, "onImageUrl",  "https://static-image.nyc3.cdn.digitaloceanspaces.com/general/fte/congratulations_pressed.png");
  Blynk.setProperty(V3, "url", "https://docs.blynk.io/en/getting-started/what-do-i-need-to-blynk/how-quickstart-device-was-made");

  Blynk.syncVirtual(V4);  // will cause BLYNK_WRITE(V4) to be executed
}

// This function sends Arduino's uptime every second to Virtual Pin 2.
void myTimerEvent()
{
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V2, millis() / 1000);
}

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

  Blynk.begin(auth, ssid, pass);
  // You can also specify server:
  //Blynk.begin(auth, ssid, pass, "blynk.cloud", 80);
  //Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8080);

  // Setup a function to be called every second
  timer.setInterval(1000L, myTimerEvent);

   pinMode(ledPin, OUTPUT);
   pinMode(relayPin, OUTPUT);
}

void loop()
{
  Blynk.run();
  timer.run();
  // You can inject your own code or combine it with other sketches.
  // Check other examples on how to communicate with Blynk. Remember
  // to avoid delay() function!
}

You can try this example

I agree with @John93 that the Sketch Builder example is the way to go.

To answer your questions…

You don’t “tell” Blynk to do that, you switch the GPIO with a digitalWrite command as you suggested then you update Blynk to reflect this with a Blynk.virtualWrite(vPin) command.

Using a BlynkTimer to poll the GPIO pin to see if it’s changed since state since last time. In the example linked above, the button is polled every 100ms

NO, ABSOLUTELY NOT!! the fist rule of Blynk programming is you keep your void loop clean (and the second rule of Blynk programming is you keep your void loop CLEAN! :wink:).

You can use an ISR instead of using a timer to poll the physical button, and this is sometimes a better approach, especially if you’re are wanting to check the status of multiple buttons attached to different GPIOs. Using the MCU’s built-in hardware interrupt handlers in this case is often neater than constantly polling lots of GPIOs in turn.
If you go down that route though, your ISRs need to each have a debounce routine and of course you need to follow ISR programming rules of using volatile variable types where required.
In the scenario you describe, the BlynkTimer approach to do brute-force polling of the GPIO is the better option.

Hope this helps.

Pete.