How to monitor button pushing time

Dear friends,
I am looking for an implementation as follows:

In my sketch I use a virtual button in order to execute special code. Due to the fact that I don’t want to press this button by accident or users fault, I am thinking to implement “button pressing duration”, let’s say to have this button pressed down for 3 seconds and THEN to execute my special code.
The problem is I don’t know how can this be implemented in the blynk ecosystem and using ESP8266 as a micro controller.
Please if you can, guide me to the right direction, please with details because I am not programmer…
(Hint: As I understood I should use millis() to measure the time…)

Thanks and Best Regards,
Mike Kranidis

Hello. Pseudo code :

int start = 0;
BLYNK_WRITE(V1)  {
    if (param.asInt()) {
       //button pressed
        start = millis();
    } else {
       //button released
          if (millis() - start > SOME_INTERVAL_MILLIS) {
              //do something after long button press.
          }
    }
    
}
1 Like

Thanks a lot Dmitriy. I will try it probably tomorrow and I will let you know about the result.

Dear Dmitriy,
Do you know why using the following real code inspired by your suggestion, after a few seconds my ESP8266 (OAK) is doing what it is supposed to do after pushing V3 button for 3 or more seconds (Oak.rebootToConfig())?
(Of course without any button pushing in blynk app)

unsigned long previousMillis = 0;
const long interval = 3000;
unsigned long currentMillis = 0;

BLYNK_WRITE(V3)
{
if (param.asInt()) {
/// button pressed ///
currentMillis = millis();
} else {
/// button released ///
if (millis() - currentMillis > interval) {
/// do something after long button press.
lcd.clear(); //Use it to clear the LCD Widget;
lcd.print(0, 0, “Rebooting…”);
lcd.print(0, 1, “in WiFi Config!”);
delay(500);
Oak.rebootToConfig();
}
}
}

Dear Dmitriy,
I can imagine that you have a lot of work to do, but in case you have a little time for me, please see my implementation based on your Pseudo code. As I already reported, it does not work and I can not find the root cause… Please give an eye, THANKS!

Sorry, I didn’t understand this phrase.

what this code suppose to do?

It is not recommended to use delays within BLYNK_WRITE.

Dear Dmitriy,
fist of all I really sorry because I did not explain the problems to you better.
Well, using the code that I implemented based on you Pseudo code, I have a very strange behavior.
Without pushing the software button V3 at my Android Blynk app, (that is configured as push button and not as switch), when the ESP8266 (OAK variation) started from Power-OFF to Power-ON, after a few seconds, the ESP8266 behaves exactly the same as the V3 has been pushed for 3 and more seconds but I state again, without any pushing at V3 button…

Regarding your question, what does this Oak.rebootToConfig(); it is an API call to reboot ESP8266 in software access point mode (nothing to do with the sketch under question).

To get an additional idea, if I change the code as following then everything is working fine but the problem is if I accidentally or unwanted push the V3 button then executes the lcd writes and then Oak.rebootToConfig() (for this reason I asked to implement 3 or more seconds pushing demand, in order to execute Oak.rebootToConfig()
I hope that this time I explained better.
Thanks for your help.

P.S. the delay(500) does not make any change if I omitted in both sketches

BLYNK_WRITE(V3)
{
if (param.asInt()) {
/// button pressed ///
lcd.clear(); //Use it to clear the LCD Widget;
lcd.print(0, 0, “Rebooting…”);
lcd.print(0, 1, “in WiFi Config!”);
delay(500);
Oak.rebootToConfig();
}

Ok. Could you please post full sketch as this behaviour could be in part you didn’t show :wink:? Also please use </> sign for code posting.

OK here is the full sketch:
</>

#define Version "1.1"
/**************************************************************
 * Blynk is a platform with iOS and Android apps to control
 * Arduino, Raspberry Pi and the likes over the Internet.
 * You can easily build graphic interfaces for all your
 * projects by simply dragging and dropping widgets.
 *
 *   Downloads, docs, tutorials: http://www.blynk.cc
 *   Blynk community:            http://community.blynk.cc
 *   Social networks:            http://www.fb.com/blynkapp
 *                               http://twitter.com/blynk_app
 *
 * Blynk library is licensed under MIT license
 * This example code is in public domain.
 *
 **************************************************************
 * Blynk using a LED widget on your phone!
 *
 * App dashboard setup:
 *   LED widget on V1
 *   LED widget on V2
 *
 *
 * WARNING :
 * For this example you'll need SimpleTimer library:
 *   https://github.com/jfturcot/SimpleTimer
 * Visit this page for more information:
 *   http://playground.arduino.cc/Code/SimpleTimer
 *
 **************************************************************/
#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleOak.h>
#include <SimpleTimer.h>

// Use Virtual pin 5 for uptime display
#define PIN_UPTIME V5

/// Use Virtual pin 3 for rebootToConfig() ///
#define REBOOT_TO_CONFIG V3

/// the bellow variables are for 3 sec push mode for V3 button in order to get in softAP mode ///
unsigned long previousMillis = 0; ///
const long interval = 3000; ///
unsigned long currentMillis = 0; ///

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "Auth here";
WidgetLED led1(V1);
WidgetLED led2(V2); /// reports the actual logic of GP5 pin///

WidgetLCD lcd(V7);

SimpleTimer timer;

// This function sends Arduino's up time every 4 seconds to Virtual Pin (6).
// In the app, Widget's reading frequency should be set to PUSH. This means
// that you define how often to send data to Blynk App.
void sendTemperature()
{
  // Generate random temperature value 00.0 to 18.0 (for example)
  float t = float(random(000, 180))/10;

  // Format: 1 decimal place, add ℃
  String str = String(t, 1) + "℃";
  String strV6 = String(t, 1);
  // Send it to the server
  Blynk.virtualWrite(V6, strV6);
  lcd.clear(); //Use it to clear the LCD Widget
  lcd.print(5, 1, str); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
  lcd.print(1, 0, "The temp. is:");

}


void setup()
{
  Serial.begin(9600); // See the connection status in Serial Monitor

  Blynk.begin(auth);

  /// initializing the GP5 that goes to the Relay, for output and set it to HIGH ("1") in order to have water heater Relay turned OFF ///
  pinMode(5, OUTPUT); //LED on Oak
  digitalWrite(5, HIGH);   // turn the LED on (HIGH is the voltage level)
  
  while (Blynk.connect() == false) {
    // Wait until connected
  }

  timer.setInterval(1000L, blinkLedWidget);
///  timer.setInterval(200L, fadeLedWidget);
  // This function tells Arduino what to do if there is a Widget
  // which is requesting data for Virtual Pin (5)

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

  lcd.clear(); //Use it to clear the LCD Widget
  lcd.print(1, 0, "Not final yet!");
  lcd.print(4, 1, "Ver=");
  lcd.print(8, 1, Version); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
}

  BLYNK_READ(PIN_UPTIME)
  {
  // This command writes Arduino's uptime in seconds to Virtual Pin (5)
  Blynk.virtualWrite(PIN_UPTIME, millis() / 1000);
  }

/// press V4 button in order to get the Software Version printed on app's screen ///
  BLYNK_WRITE(V4)
  {
    if (param.asInt()) {
  lcd.clear(); //Use it to clear the LCD Widget
  lcd.print(1, 0, "Not final yet!");
  lcd.print(4, 1, "Ver=");
  lcd.print(8, 1, Version); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
  delay(400);
    } 
  }

/// start of testing routine for correct driving using inverse logic, the external Relay. The Virtual Button SW V8 <==> GP5///
  BLYNK_WRITE(V8)
  {
    if (param.asInt()) {
    digitalWrite(5, LOW);
    } else {
    digitalWrite(5, HIGH);
      }
  }
/// end of testing routine for correct driving external inverse logic Relay using Virtual Button SW ///

/// start of rebootToConfig() routine for ISSUE reset to config to OAK if V3 button pressed for >= 3 seconds ///
  BLYNK_WRITE(V3)
  {
    if (param.asInt()) {
      /// button pressed ///
    lcd.clear(); //Use it to clear the LCD Widget;
    lcd.print(0, 0, "Rebooting.....");
    lcd.print(0, 1, "in WiFi Config!");
    delay(400);
    Oak.rebootToConfig();
    } 
  }


/*  THIS DOES NOT WORK AS EXPECTED 
  BLYNK_WRITE(V3)
  {
    if (param.asInt()) {
      /// button pressed ///
      currentMillis = millis();
    } else {
      /// button released ///
      if (millis() - currentMillis > interval) {
              /// do something after long button press.
              lcd.clear(); //Use it to clear the LCD Widget;
              lcd.print(0, 0, "Rebooting.....");
              lcd.print(0, 1, "in WiFi Config!");
              delay(500);
              Oak.rebootToConfig();
          }
      }
  }
*/

void blinkLedWidget()
{
  if (led1.getValue()) {
    led1.off();
    BLYNK_LOG("LED1: off");
  } else {
    led1.on();
    BLYNK_LOG("LED1: on");
  }
}

// Every time we connect to the cloud synchronize all the values from Widgets...
BLYNK_CONNECTED() {
///  if (isFirstConnect) 
///  {
// Request Blynk server to re-send latest values for all pins
    Blynk.syncAll();
///  }
}


void loop()
{
  Blynk.run();

  if (digitalRead(5)== 1)
  { 
    led2.on();
    }
  else 
  { 
    led2.off();
    }

  timer.run();
}

</>

That’s the reason. On start you get BLYNK_WRITE with value 0. (as button not pressed and yes, we send sync for buttons too).

You have 2 options to solve issue :

  • either request sync for specific pins and without button pin; (recommended)
  • or add one more flag and check if syncAll operation was finished to be sure BLYNK_WRITE is called from button clikc and from syncAll.

OK thanks a lot. Just for my curiosity, how can code the option 2 (using the flag)?