BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

How to read blynk button pressed inside the arduino sketch?

#1

Hi all,

it’s the first time i will use blink, and have some doubts.

I create on the app a panel with 3 buttons (push buttons).

My physical device have 3 push buttons which are read by

#include <Button.h>
int newDebounceDelay = 60;
....
Button automatic(10, LOW);
char operation_mode;

.......

operation_mode = EEPROM.read(0);
  msgnum = EEPROM.read(1);
  if ((operation_mode != 'A') && (operation_mode != 'C') && (operation_mode != 'O') && (operation_mode != 'P')) {
    operation_mode = 'A';
    digitalWrite(LedAuto, HIGH);
  }

void loop() {
check_button();
}

void check_button() {
  automatic.listen();

  if (automatic.onPress()) {
    if (operation_mode == 'A') {
      operation_mode = 'P';
      digitalWrite(LedAuto, LOW);
      digitalWrite(LedOpen, LOW);
      digitalWrite(LedClose, LOW);
      msgnum = 3;
    } else {
      operation_mode = 'A';
      digitalWrite(LedAuto, HIGH);
      digitalWrite(LedOpen, LOW);
      digitalWrite(LedClose, LOW);
      msgnum = 0;
    }
  }

how could i read the blynk push button, like:

 if (automatic.onPress() || virtualRead(10)) {
  do whatever;
}

and have it true || high?

Is this correct?

Sorry if it’s basic… it’s my first atempt…

TIA

0 Likes

#2

https://examples.blynk.cc/?board=Arduino%20Uno&shield=Arduino%20WiFi%20Shield&example=More%2FSync%2FButtonInterrupt

0 Likes

#3

thank you.

regarding keep your void loop() clean, could you please educate me in how to have it cleaner?

0 Likes

#4

You are calling that function thousands of times a second by having it directly in the void loop() like that.

I don’t know what automatic.listen() is, probably a part of some button reading library, but if conditions are right then you are potentially also running those digitalWrite() commands hundreds or thousands of times a second.

While this works just fine in Arduino world, once you start entering IoT world there are lots of other tasks, like maintaining a communication link, that need to share the Arduino’s clock time.

Thus, as described in that document I linked to, you use timer based functions instead of filling the void loop() with code or directly calling other functions from it (basically the same thing).

1 Like

#5

BTW, I think I misunderstood your question… I thought you needed to match your physical and Blynk buttons.

For best performance with Blynk… use code and virtual pins instead of direct GPIO control from the App…

Then you could do something like this…

// This function is called whenever the assigned Widget changes state
BLYNK_WRITE(vPin) {  // vPin is the Virtual Pin assigned to a Button Widget
int pinValue = param.asInt();
 if (pinValue == 1) {
  do whatever;
 }
}

Can also be written shorthand like this…

// This function is called whenever the assigned Widget changes state
BLYNK_WRITE(vPin) {  // vPin is the Virtual Pin assigned to a Button Widget
 if (param.asInt()) {  // Assumes if 1 then follow through..
  do whatever;
 }
}
0 Likes

#6

well, thanks, and i did not get it.

as far i know, on arduino, void setup() is used to set all and prepare for the loop().

And once inside loop(), only what’t inside is executed. So, to be able to change any behavior, the sketch needs to check if button was pressed or not, and it must be done inside loop.

BTW, automatic.listen() uses the function listen, and it’s on Arduino_Library_Button_master library (makes use of buttons - debounce, etc, much simpler).

My question is quite simple: the same way i press the physical button on the circuit, how can i perform the same action with the button widget.

What i understood from your answers:

  • blynk_write(vpin) shall be defined at setup();
  • having the physical button at physical digital pin 10, so i shall define the vPin to 10 too.
  • when the widget button is pressed, blynk library runs the blynk_write function, so no need to check it inside loop.

In this case,

// This function is called whenever the assigned Widget changes state
BLYNK_WRITE(10) {  // vPin is the Virtual Pin assigned to a Button Widget
int pinValue = param.asInt();
 if (pinValue == 1) {
  virtual_automatic_button = 1;
 }
}

and so,

void setup() {
BLYNK_WRITE(10) {  // vPin is the Virtual Pin assigned to a Button Widget
int pinValue = param.asInt();
 if (pinValue == 1) {
  virtual_automatic_button = 1;
 } else  {
 virtual_automatic_button = 0;
}
}
}

void loop() {
check_button;
}

void check_button() {
  automatic.listen();

  if (automatic.onPress() || virtual_automatic_button == 1)  {
    if (operation_mode == 'A') {
      operation_mode = 'P';
      digitalWrite(LedAuto, LOW);
      digitalWrite(LedOpen, LOW);
      digitalWrite(LedClose, LOW);
      msgnum = 3;
    } else {
      operation_mode = 'A';
      digitalWrite(LedAuto, HIGH);
      digitalWrite(LedOpen, LOW);
      digitalWrite(LedClose, LOW);
      msgnum = 0;
    }
  }

considering the automatic.listen(), when have button pushed, turn digital pin 10 to HIGH, and funcion is excuded, is there a way that when virtual (wdget) button is pressed, write directly to physical digital pin?

TIA

0 Likes

#7

You can’t bury your head in the sand about the advice @Gunner has given you about keeping your void loop clean. If you ignore this advice then you will run into problems with Blynk disconnections.

[Potentially useful advice regarding alternative solutions removed following the comment below from @pw44]

Pete.

1 Like

#8

sorry… but i think you got it wrong. i asked to understand. if your are not able to objectively answer and clarify the questions, please do not answer.

Thank you.

0 Likes

#11

My interpretation of this sentence:

is that you are adamant that the checking of the button needs to be done inside the void loop.
If that’s not what you meant then maybe the way you’ve structured this sentence is the cause of the confusion, or maybe I’m just being dumb?

But don’t worry, this is the last time you’ll be hearing from this particular ‘Smart Alec’.

Pete.

0 Likes

#12

when i said that i need to check physical buttons inside the loop, it has a reason. they control the enable/disable and direction of a stepper motor.

and the code inside the automatic.listen() is only checked and executed if the push button is pressed, so, if state of digital pin related to button is LOW, it does not even check the code:

 if (automatic.onPress())  {
    if (operation_mode == 'A') {
      operation_mode = 'P';

so, the “then if / else” inside the “if (automatic.onPress())” is only verified when button is pressed, which is no different than:

void loop()
{
  Blynk.run();
  if (pinChanged) {

    // Process the value
    if (pinValue) {
      led1.on();
    } else {
      led1.off();
    }

    // Clear the mark, as we have processed the value
    pinChanged = false;
  }
}

that’s why i asked how were i burying the head in the sand by not taking the advice.

The complete loop()

// LOOP BEGIN

void loop() {
  currentMicros = micros();
  ldr_val = analogRead(ldr_pin);
// debug 
//  Serial.print(ldr_val);
//  Serial.print("\r\n");
  check_button();
  switch (operation_mode) {
    case 'A': Automatic_Mode(); break;
    case 'C': Manual_Close();   break;
    case 'O': Manual_Open();    break;
    case 'P': motor_mode = 'S'; break;
  }
  if (msgnum != prevmsgnum) {
    prevmsgnum = msgnum;
    switch (msgnum) {
      case 0: Display_Automatic_Mode();       break;
      case 1: Display_Automatic_Mode_Open();  break;
      case 2: Display_Automatic_Mode_Close(); break;
      case 3: Display_Automatic_Mode_Pause(); break;
      case 4: Display_Manual_Close();         break;
      case 5: Display_Manual_Close_Pause();   break;
      case 6: Display_Manual_Open();          break;
      case 7: Display_Manual_Open_Pause();    break;
      case 8: Display_Stop_Close();           break;
      case 9: Display_Stop_Open();            break;
    }
    EEPROM.update(0, operation_mode);
    EEPROM.update(1, msgnum);
  }

  // motor run

  if (motor_mode == 'R') {
    digitalWrite(MotorEnable, LOW);
    digitalWrite(MotorSleep, HIGH);

    if (dir != prevdir) {
      prevdir = dir;
      delay(1500); // pause to change direction run
    }

    if (currentMicros - previousmotorMicros > motorinterval) {
      previousmotorMicros = currentMicros;
      if (stepp == LOW)
        stepp = HIGH;
      else
        stepp = LOW;
      digitalWrite(MotorDir, dir);
      digitalWrite(MotorStep, stepp);
    }
  }
  if (motor_mode == 'S') {
    digitalWrite(MotorEnable, HIGH);
    digitalWrite(MotorSleep, LOW);
  }
}

// LOOP END

there are two ways to handle it:

either an ESP8266 connected to the arduino board and having blynk library set a value by key and treat it (ESP8266 as the wifi interface for the arduino board)

or

a standalone ESP8266 (sketch on it) having two digital outputs set to high/low which are read by the arduino board which will treat it.

I’m looking for the most effective way.

0 Likes

#13

That fact gets clearer as I read the rest of your post :slight_smile:

Yes… which is why Blynk.run() and timer.run() are usually the only things needed in the void loop() for a Blynk compatible sketch. One runs the Blynk library background operations and housekeeping and the other runs the timers.

Other libraries may also have master commands that can go there as well, but general code and function calls should NOT… Rather, they get called from timers or interrupts instead.

NOPE - BLYNK_WRITE() is a free standing function that runs when a widget value changes state (Did you NOT read the documentation and the comments in my example??)

Not necessary. Virtual pins are separate entities from physical pins, so V127 can link to a Blynk button that transfers it’s state to digital pin 3, etc. (Again… already explained in the Documentation… see below for another example)

Correct…ish… see above answers

I already supplied such an example… but here is a clarification…

// This function is called whenever the assigned Widget changes state
BLYNK_WRITE(V127) {  // vPin is the Virtual Pin assigned to a Button Widget, need NOT match the GPIO pin number
digitalWrite(3, param.asInt());  // Assign digital pin the value from the virtual pin
}

By continuing to fill the void loop() like you have no alternatives :stuck_out_tongue_winking_eye: Had you read the documents provided you would have seen the Blynk compatible way.

Nope, he got it correct… I already supplied references and examples and you seemingly discarded the documentation and bent my examples to fit your partial understanding.

Then when advised to rethink those actions you lash out against a valid advisors recommendations, thinking that you know better then @PeteKnight, a long term and very experienced Blynk user who… YES, definitely knows more than you about it.

At this point I redirect you back to your own (later removed) commentary… if you are unable to listen and learn when provided advice, then perhaps you are asking in the wrong place?

Here is my funny smiley face to go with this :crazy_face:

1 Like

#14

Sorry, i read it, and i did not discarded the documentation for my partial understanding… got it from the following code., where the same kind of logic is considered inside the loop(), performing actions when triggered.

/*************************************************************
  Download latest Blynk library here:
    https://github.com/blynkkk/blynk-library/releases/latest

  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
    Sketch generator:           http://examples.blynk.cc
    Blynk community:            http://community.blynk.cc
    Follow us:                  http://www.fb.com/blynkapp
                                http://twitter.com/blynk_app

  Blynk library is licensed under MIT license
  This example code is in public domain.

 *************************************************************

  This example shows how to monitor a button state
  using interrupts mechanism.

  App project setup:
    LED widget on V1
 *************************************************************/

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


#include <SPI.h>
#include <WiFi.h>
#include <BlynkSimpleWifi.h>

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

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

WidgetLED led1(V1);

// We make these values volatile, as they are used in interrupt context
volatile bool pinChanged = false;
volatile int  pinValue   = 0;

// Most boards won't send data to WiFi out of interrupt handler.
// We just store the value and process it in the main loop.
void checkPin()
{
  // Invert state, since button is "Active LOW"
  pinValue = !digitalRead(2);

  // Mark pin value changed
  pinChanged = true;
}

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

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

  // Make pin 2 HIGH by default
  pinMode(2, INPUT_PULLUP);
  // Attach INT to our handler
  attachInterrupt(digitalPinToInterrupt(2), checkPin, CHANGE);
}

void loop()
{
  Blynk.run();
  if (pinChanged) {

    // Process the value
    if (pinValue) {
      led1.on();
    } else {
      led1.off();
    }

    // Clear the mark, as we have processed the value
    pinChanged = false;
  }
}

0 Likes

#15

Yes, that particular example does show specific code that is ONLY ran upon an interrupt signal, thus relatively safe to leave in the main loop. But then this is just an example, not a larger project that may have many such interrupts, etc. and thus coded in various different ways.

The “clean void loop” is a valid and important recommendation, not a hard and fast rule… as experienced programmers CAN get away with some coding methods that will trip up inexperienced users.

I am NOT an experienced programmer… more like an insufferably OK self learner :smile: But here is an example of needing code in the void loop()… but set in such a way as to ONLY run under specific conditions, and even then ONLY once every prescribed timeframe.

0 Likes

#16

well, i’m also not a good programmer, but i try.

in my code, the check_button() checks and perform if button is triggered. Other funcions only are performed when state changes, and the stepper are done with non blocking code.

The only stop is when motor changes direction… delay of 1500, but i decided so, instead of use non blocking code (with millis, etc)…

What i’m just trying is to thave 3 virtual buttons for it, and there are three options:

  1. have it on the main board having esp8266 (in at mode) as the wifi interface

  2. program the esp8266 as standalone device having 2 gpio’s as digital outputs being read by the mainboard.

EDIT:

  1. having the necessary char sent from esp8266 to the nano via i2c bus…

either solution will satisfy me.

0 Likes

#17

I have done some testing using Blynk control of Stepper Motors, using both standalone ESP and dual MCU (ESP and Arduino)

0 Likes

#18

so you got what i’m aiming to do :wink: and congrats. for both.

i need first bring my esp8266 to work, and after that i will continue. at least part of the answers i have. thx.

0 Likes

#19

I was quite shocked to see that this code example came from the Sketch Builder. I’ve raised this as an issue, along with some suggested revised code:

Pete.

1 Like

#20

oh boy… it happens… :wink: the devil is in the detail.

but when using i.e nano, attachinterrupt
(https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/) would not allow me checking the state of 3 physical buttons, as only pin 2 and 3 are useable for interrupts.

0 Likes

#21

Thas is an Arduino issue, not Blynk specific.

However, God is in the detail :wink: and there are other ways to monitor GPIO inputs, like a fast timed function that uses digitalRead() commands. I find scanning every 250ms (1/4 second) is sufficient for most basic button pressing needs, but if really wanting to play Space Invaders, then I imagine even 50-100ms scans can be handled for a small handful of buttons.

I use something similar on a Sonoff AC power switch based on ESP8266 to monitor the manual button on the device.

0 Likes

#22

Yes, attachinterrupt is an Arduino issue.

As i told, and not ironically, i’m far from being a good programmer for Arduino and likes (my experience comes from Mainframes and later from Unix and *X likes), nothing with devices and likes and object programing. But i’m trying, learning the basics of electronics, figuring out how steppers works and timing for it (for speed and torque), buttons and it’s debounce, analog values reading and so on.

From my experience, and trying to understand, there are definitions, setup and void sections.

by definitions, i include the libraries, by setup i initialize all, and by loop, all is run. subroutines (functions), i have it after loop (ok, can be also done inside the setup section).

from all i tested, after entering loop, what is defined by setup is gone (except the subroutines, when called inside loop).

that’s why i asked ;-), and got surprised when based on an official example , indicated by you, i received a reply that i should take the advice (which i did :wink:).

I’m not a beginner in logic, but an absolute beginner in IoT and Arduino. Sure i have a lot to learn, but i need to understand what’s behind the scenes, so i can at least try to make the best translation from logic to code.

As driving the stepper and reading buttons seams to be a little critical, i used the non blocking trick to have the stepper running while being able to read the buttons.

Sorry for the long text, but i wanted to clarify all.

BR

0 Likes