Virtual Button Will not Work (Specifically Update when I push it from App)

I am trying to make a distance measurer by using only one button. I got it working without blynk and with a physical lcd Screen and button.I have the app button set up correctly so that when I push it it returns a 0. It seems like it does not update the button state except the first time i select it. I even tried adding another buttonPin=paramAsInt(); before everytime i needed it to reread the button State. If someone could just explain how i can read the button state each time so it doesn’t get stuck in my first while loop. The problem is I don’t know how to update the Button State.
• Arduino UNO Through Serial Connection on Mac
• Ios
• Blynk server

 int buttonPin;
  double startTime;
  double endTime;
  double totalTime;
  double avgTotalTime;
  double bucket= 0;
  double numThrows=3;
  double currentEndTime;
  double passingTime;
  double heightMeters;
  double heightFeet;
  //Declare calculation constants
  const double gravityMetric= 9.81;
  const double gravityFeet= 32.3;
  //Declare program neccesary objects
  int program =0;
  int selectProg=1;
  String method ="Drop";
#define BLYNK_PRINT SwSerial


#include <SoftwareSerial.h>
SoftwareSerial SwSerial(10, 11); // RX, TX

#include <BlynkSimpleStream.h>

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

WidgetLCD lcd(V1);
BLYNK_WRITE(V2)
{
  int buttonPin = param.asInt(); // assigning incoming value from pin V1 to a variable
  if (buttonPin==1){
    lcd.clear();
    switch(program){
    case(0)://Pick Method Drop Or Throw.
     //Print options on LCD Screen while loop allows top line to stay unaltered
      lcd.clear();
      lcd.print(0,0,"Drop or Throw?");
      buttonPin = param.asInt();
      while (buttonPin==1){
      buttonPin = param.asInt();
        
      }
        lcd.print(0,1,"     ");
        lcd.print(0,1,method);
        buttonPin = param.asInt();
        if (buttonPin==0){ 
          if (selectProg==1){
            //program=2;
            method= "Throw";
            selectProg=2;
            delay(100);
            }
          else if (selectProg==2){
            //program =3;
            method= "Drop";
            selectProg=1;
            delay(100);
            }
        }
        delay(1000);
        buttonPin = param.asInt();
        if(buttonPin==0){
          program=1;
          lcd.clear();
          break;
          
         }
      break;
     
     case(1)://Instructions for each Method and Arduino selecting proper program 
        lcd.clear();
        lcd.print(0,0,"You've Selected");
        lcd.print(0,1,method);
        delay(2000);
        lcd.clear();
                             
        if (method== "Drop"){
            lcd.print(0,0,"Push and hold ");
            lcd.print(0,1,"the button until");
            delay(2000);
            lcd.clear();
            lcd.print(0,0,"hits the ground");
            lcd.print(0,1,"I'll do the Rest.");
            
        }
        if (method== "Throw"){
            lcd.print(0,0,"Push and hold ");
            lcd.print(0,1,"the button until");
            delay(3000);
            lcd.clear();
            lcd.print(0,0,"you catch object");
            lcd.print(0,1,"Repeat 3 times");
            delay(2000);
           
        }
        if(selectProg==2){
          program=3;
          
        }
        if(selectProg==1){
          program=2;
        }
        break;
  
     case(2)://Drop Program
        delay(5000);
        lcd.clear();
        lcd.print(0,0,"Ready to Drop...");
        //Start Stopwatch
        buttonPin = param.asInt();
        while (buttonPin==1){
          buttonPin = param.asInt();
          delay(20);
        }
        buttonPin = param.asInt();
        if (buttonPin==0){
          startTime=millis();
        }
        //Display time passing
        buttonPin = param.asInt();
        while (buttonPin==0){
            buttonPin = param.asInt();
            currentEndTime=millis();
            passingTime = (currentEndTime - startTime)/1000.;
            lcd.print(0,1,passingTime);
            lcd.print(6,1,"Sec");
            delay(10);
            buttonPin = param.asInt();
        }
        //Stop Stopwatch and Calculate total time
        buttonPin = param.asInt();
        while (buttonPin==1){
            lcd.print(11,1,"Stop");
            endTime=millis();
            totalTime = (endTime - startTime)/1000;
            delay (1000);
            lcd.clear();
            lcd.print(0,0,"Total air time = ");
            lcd.print(0,1,totalTime);
            lcd.print(6,1," Seconds");
            delay(3000);
            //Uses Newtonian Kinematics[height= (1/2)*acceleration*time^2] to solve for height
            heightMeters=(1./2.)*gravityMetric*totalTime*totalTime;
            heightFeet=(1./2.)*gravityFeet*totalTime*totalTime;
            lcd.clear();
            lcd.print(0,0,"Height= ");
            lcd.print(0,1,heightFeet);
            lcd.print(6,1,"ft");
            lcd.print(9,1,heightMeters);
            lcd.print(15,1,"m");      
            delay(7000);
            break;
        }
        //Back to start Screen
        lcd.clear();
        lcd.print(0,0, "Reseting...");
        program=0;
        method= "Drop";
        bucket= 0;
        selectProg=1;
        delay (750);
      break;
     case(3)://Throw Program
       delay(5000);
       // Custom Function to get avg airtime of the three throws
       //for loop to allow getting average
        for (int j=1; j<=numThrows; j++){
            lcd.clear();
            lcd.print(0,0, "Ready to Drop");
            lcd.print(15,0, j);
            //Start StopWatch
            buttonPin = param.asInt();
            while (buttonPin==1){
              buttonPin = param.asInt();
              delay(10);
            }
            buttonPin = param.asInt();
            if (buttonPin==0){
              startTime=millis();
            }
            //Stop Stopwatch and calculate total time
            buttonPin = param.asInt();
            while (buttonPin==0){
                currentEndTime=millis();
                passingTime = (currentEndTime - startTime)/1000.;
                lcd.print(0,1,passingTime);
                lcd.print(6,1,"Sec");
                delay(10);
                buttonPin = param.asInt();
            }
            while (buttonPin==1){
                lcd.print(11,1,"Stop");
                endTime=millis();
                totalTime = (endTime - startTime)/1000;
                delay (1000);
                lcd.clear();
                lcd.print(0,0, "Total air time = ");
                lcd.print(0,1,totalTime);
                lcd.print(6,1," Seconds");
                delay(2000);
                bucket= bucket+totalTime;
                break;
                
           }
           avgTotalTime=bucket/numThrows;
         }
       //Uses Newtonian Kinematics[height= (1/2)*acceleration*time^2] to solve for height
       //In this case time is cut in half because we solve for max height where Velocity=0 (y-direction)
       heightMeters=(1./2.)*gravityMetric*((avgTotalTime*avgTotalTime)/4.);
       heightFeet=(1./2.)*gravityFeet*((avgTotalTime*avgTotalTime/4.));
       lcd.clear();
       lcd.print(0,0, "Max Height= ");
       lcd.print(0,1, heightFeet);
       lcd.print(6,1,"ft");
       lcd.print(9,1,heightMeters);
       lcd.print(15,1,"m");      
       delay(7000); 
       //Back to Start Screen
        lcd.clear();
        lcd.print(0,0, "Reseting...");
        program=0;
        method= "Drop";
        bucket= 0;
        selectProg=1;
        delay (750);
  //Back to start Screen
        lcd.clear();
        lcd.print(0,0, "Reseting...");
        program=0;
        method= "Drop";
        bucket= 0;
        selectProg=1;
        delay (750);
      break;
 }
  } 
  delay(10); 
}
 void setup()
{
  // Debug console
  SwSerial.begin(9600);

  // Blynk will work through Serial
  // Do not read or write this serial manually in your sketch
  Serial.begin(9600);
  Blynk.begin(Serial, auth);
  
  // Please use timed events when LCD printintg in void loop to avoid sending too many commands
  // It will cause a FLOOD Error, and connection will be dropped
}

void loop()
{
  Blynk.run();
}

I think that maybe you don’t understand how the BLYNK_WRITE(V2) callback function works.
Each time you press (or press or release if it’s in PUSH mode) the button widget attached to V2, BLYNK_WRITE(V2) is triggered again.
This means that you can’t use the same button to give you a parameter part way through processing the BLYNK_WRITE(V2) function, as another press or release of the button will start the whole function over again.

If you must have just one button then you’d need to do some very involved coding using global variables as flags to track the point you are at within the process and handle the result that you’re getting from V2 accordingly. You’d need to move almost all of your code out of BLYNK_WRITE(V2) into one or more separate functions that are called depending on the current state of your flag variables.

Pete.

1 Like

I was really hoping that wouldn’t be your answer haha, Thanks for the response. One more thing, would it work if I modified made a function of getHeight() having only the BLYNK_WRITE(V2) { int buttonPin = param.asInt(); }
and then within that function put the BLYNK_WRITE(V2) function whenever I need to read the button State or would that not work since it is a nested function?

You can’t put BLYNK_WRITE(V2) within another function, it is a function in its own right.

Pete.

1 Like

Ok makes sense now. If you were to go about this what would you do, is it easer to do it with 2 or more buttons, if so how would I separate the code?
Something like use one button to run the getHeight() function then us another button as a selector? Or basically is there other way than to make flags to track where I am in the function?

I’d probably go for a styled button or segmented switch as the selector, then another button to trigger the measurement.

I’d have a global “mode” variable set by the selector switch, and syncronised at startup using the BLYNK_CONNECTED callback function and a Blynk.syncVirtual(selectort virtual pin) command.

I’d have the measure callback (BLYNK_WRITE(V2)) with an if statement that says 'if mode == 1 then call this function, else call that function`.

Pete.

1 Like

Thanks for all your help Pete I will try that out.