Blynk Virtual Pin Input Can't Interrupt While Loop with Time Condition

Hey all,

Im having issues with Blynk Virtual Pins as an input from user. I wanted to make the virtual button to break the while loop but I cant seem to make the Blynk virtual pin inputting data reliably.

Board : Nano 33 IoT
IDE : Arduino IDE 2.0
Blynk Server

Here is my code (a simple replication code, cuz Im trying to integrate it into a bigger code):

#define BLYNK_TEMPLATE_ID "TMPLcs7W8DPD"
#define BLYNK_DEVICE_NAME "Virtual Pin"
#define BLYNK_AUTH_TOKEN "qjLKuRCsBbX105veJMmLc_b4Md5hnHOJ"

#include <SPI.h>
#include <WiFiNINA.h> 
#include <WiFiUdp.h>
#include <RTCZero.h>
#include <BlynkSimpleWiFiNINA.h>

// WiFi Credentials (edit as required)
char ssid[] = "";      // Wifi SSID
char pass[] = "";       // Wifi password

// Object for Real Time Clock
RTCZero rtc;

int status = WL_IDLE_STATUS;

const int GMT = +8; // Time zone constant

int btnV5;
int btn;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  // Print connection status
  WiFiConnect();
  printWiFiStatus();
  
  // Start Real Time Clock
  rtc.begin();
  
  // Variable to represent epoch
  unsigned long epoch;
 
 // Variable for number of tries to NTP service
  int numberOfTries = 0, maxTries = 6;

 // Get epoch
  do {
    epoch = WiFi.getTime();
    numberOfTries++;
  }

  while ((epoch == 0) && (numberOfTries < maxTries));

    if (numberOfTries == maxTries) {
    Serial.print("NTP unreachable!!");
    while (1);
    }

    else {
    Serial.print("Epoch received: ");
    Serial.println(epoch);
    rtc.setEpoch(epoch);
    Serial.println();
    }

    Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
}
//**********************************************************************************
void loop() {
  Blynk.run();
  // put your main code here, to run repeatedly:
  btn = btnV5;
  printTime();
  delay(1000);

  //now = rtc.getHours() + GMT; //get hour now
  int now = rtc.getSeconds();

  while (now >= 30 && btnV5 != 1 && btn != 1) {
    now = rtc.getSeconds();
    BLYNK_WRITE(V5);

    Serial.println("while loop");
    delay(2000);

    Serial.println("btnV5 :" + String(btnV5));
    Serial.println("btn   :" + String(btn));

    int btn = digitalRead(12);
    if (btnV5 == 1) break;
    else if (btn == 1) break;
  }*/
}

//##################################################################################
void WiFiConnect() {
  // Check if the WiFi module works
  if (WiFi.status() == WL_NO_SHIELD) {
    // Wait until WiFi ready
    Serial.println("WiFi adapter not ready");
    while (true);

  }

      // Establish a WiFi connection
  while ( status != WL_CONNECTED) {

    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);

    // Wait 10 seconds for connection:
    delay(10000);

  }
}

void printWiFiStatus() {

  // Print the network SSID
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  
  // Print the IP address
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  
  // Print the received signal strength
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

void print2digits(int number) {

  if (number < 10) {
    Serial.print("0");
  }
  Serial.print(number);
}

void printTime()
{

  print2digits(rtc.getHours() + GMT);
  Serial.print(":");
  
  print2digits(rtc.getMinutes());
  Serial.print(":");
  
  print2digits(rtc.getSeconds());
  Serial.println();
}

BLYNK_WRITE(V5)
{
  int btnV5 = param.asInt();
  Serial.println("blynk:" + String(btnV5));
}

I printed out the output, but when it was in the while loop, Blynk virtual button doesn’t relay into the loop. It only works outside of the loop.

Here is the output when it is not in the while loop. (Underlined)
& at the bottom (boxed) is when it is inside the loop. The virtual button can’t send the input data here.

My objective is to get the while loop to break when there is an input via the virtual button.

-Danial.

Https://docs.blynk.io/en/legacy-platform/legacy-articles/keep-your-void-loop-clean

You shouldn’t use delay in a Blynk sketch because it is a blocking function. The blocking function prevents the program from executing any additional actions until the current task has been completed.

1 Like

That’s not really possible. The change of state of the virtual pin is only detected by the sketch when Blynk.run() is executed.

You could try to put a Blynk.run() in your while loop, but in reality the best approach is not to use while loops - except in your void setup when doing things like trying to connect to WiFi.

Also, you shouldn’t be using delays in your sketch, except in your void setup, as these block all code execution and therefore prevent Blynk.run() from being processed.

The solution is to use BlynkTimer as a non-blocking way of executing code every x milliseconds. This is explained further in the link that @Madhukesh provided.

Also, you don’t need to use an NTP server to get the time, you can get this from the Blynk server.

In addition, you can’t do this in your void loop…

BLYNK_WRITE(vPin) is a callback function which is triggered when Blynk.run() is executed and the server tells the client that the value of vPin has changed. You can’t use this function as a command.

Pete.

1 Like