Button press blocked by running function

Hi,

I’m trying to control some roller blinds using a stepper motor and an ESP8266 (Wemos D1 Mini).
I have set up two virtual pins connected to two buttons in Blynk app, each triggering a different function to rotate the motor CW or CCW. I also have 2 HALL sensors that detect position and break the function execution. Everything works fine.
I now want to add a third virtual pin that will set a boolean variable and stop the function execution based on it’s value. However, when I press the V7 button in the application, it’s not detected until the function already completes it’s execution, making it useless.
I need help in modifying the code so that the controller detect the virtual pin value just like it does for the physical pins.

My code below:

// Arduino Program to control blinds using stepper motor 


#define BLYNK_TEMPLATE_ID           "asd" //The template ID can be find in Blynk web console
#define BLYNK_TEMPLATE_NAME           "asd" // Device name can be found in Blynk Console
#define BLYNK_AUTH_TOKEN            "asd" //Auth token can be found in Blynk web console
#define BLYNK_PRINT Serial

#include <FastLED.h>

#include <ESP8266WiFi.h> // Library for ESP8266 chip

#include <BlynkSimpleEsp8266.h> //Library for Blynk

#define BLYNK_PRINT Serial
#define LED_PIN D0
#define NUM_LEDS 1

CRGB leds[NUM_LEDS];

const int stepPin = D1; 
const int dirPin = D2; 
const int TMC2208enablePin = D3;
const int hall1Pin = D5;
const int hall2Pin = D6;
const int MS1Pin = D7;
const int MS2Pin = D8;

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "asd";
char pass[] = "asd";

boleean stopbutton = false;


///////////////////////////////////////
//   SETUP AREA                     //
/////////////////////////////////////


void setup()
{
  Serial.begin(115200);

  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
  FastLED.clear();
  FastLED.show();

  delay(100);
  Serial.print("Connecting to "); // Waiting for network connection
  Serial.println(ssid); 
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid,pass); 


  while (WiFi.status() != WL_CONNECTED) //You will hang up in this loop until you connect...
  { delay(1000); 
  Serial.println("."); 
  FastLED.clear();
  FastLED.show();
  }
  Serial.print("\r\nConnected: local ip address is http://"); // Now it's connected to network
  Serial.println(WiFi.localIP());
  Serial.println();

  Blynk.config(auth); // For connecting to Blynk service

  pinMode(stepPin,OUTPUT); 
  pinMode(dirPin,OUTPUT);
  pinMode(TMC2208enablePin,OUTPUT);
  pinMode(hall1Pin,INPUT);
  pinMode(hall2Pin,INPUT);
  pinMode(MS1Pin,OUTPUT); //Used for Microstepping
  pinMode(MS2Pin,OUTPUT); //Used for Microstepping

  digitalWrite(TMC2208enablePin,HIGH); //D3 High disables the A4988 driver to prevent overheating
  digitalWrite(MS1Pin,HIGH); 
  digitalWrite(MS2Pin,LOW);

  leds[0] = CRGB(0, 0, 255);
  FastLED.show();
}


//////////////////////////////////
// BLYNK FUNCTIONS             //
////////////////////////////////


BLYNK_WRITE(V1) //OPEN the BLINDS
{
    Serial.println("V1 pressed");
    openblinds();
}


BLYNK_WRITE(V2) //CLOSE the BLINDS
{
    Serial.println("V2 pressed");
    closeblinds(); 
}

BLYNK_WRITE(V7)
{    
    Serial.println("V7 pressed");
    stopbutton = true;
}

///////////////////////////
//    LOOP              //
/////////////////////////


void loop()
{
  Blynk.run(); // We run blynk continously
  if (WiFi.status() == WL_CONNECTED)
  {
  ledblue();
  }
}

//////////////////////////////////
//FUNCTIONS                    //
////////////////////////////////


  void openblinds() //  This is called by Blynk pin V1 to OPEN the BLINDS
{

if (digitalRead(hall1Pin) == HIGH) 
{
    digitalWrite(MS1Pin,HIGH);
    digitalWrite(MS2Pin,LOW);
    leds[0] = CRGB(0, 255, 0 );
    FastLED.show();
    digitalWrite(TMC2208enablePin,LOW);
    digitalWrite(dirPin,HIGH); // Enables the motor to move in a particular direction
    for(int x = 0; x < 8000; x++) {
    digitalWrite(stepPin,HIGH); 
    delay(1); 
    digitalWrite(stepPin,LOW); 
    delay(1);
    if (digitalRead(hall2Pin) == LOW) {
      break;
      FastLED.clear();
    }
  }
  }
    digitalWrite(TMC2208enablePin,HIGH); //We disable the stepper.
}

    void closeblinds() // This is called by Blynk pin V2 to CLOSE the BLINDS
{
  if (digitalRead(hall2Pin) == HIGH) {
    digitalWrite(MS1Pin,HIGH);
    digitalWrite(MS2Pin,LOW);
    leds[0] = CRGB(255, 0, 0 );
    FastLED.show();
    digitalWrite(TMC2208enablePin,LOW);
    digitalWrite(dirPin,LOW); // Enables the motor to move in a particular direction
    for(int x = 0; x < 8000; x++) {
    digitalWrite(stepPin,HIGH); 
    delay(1); 
    digitalWrite(stepPin,LOW); 
    delay(1);
        if (digitalRead(hall1Pin) == LOW) {
      break;
      FastLED.clear();
    }
    }
  }
    digitalWrite(TMC2208enablePin,HIGH); //We disable the stepper.
}


  void ledblue()
  {
  leds[0] = CRGB(0, 0, 255 );
  FastLED.show();
  }

Well, first of all, you’re not doing anything with your stopbutton Boolean variable. Simply changing the variable from false to true won’t magically make the blind stop.

Your openblinds and closeblinds functions need to check the state of the stopbutton variable in the same way that they check the state of the Hall effect switches after each iteration of the for loop.

However, because the BLYNK_WRITE(vPin) functions aren’t processed until a Blynk.run() command is processed, you also need to add Blynk.run() into your for loop before testing tge stopbutton variable value.

Pete.

Thank you for your answer and sorry for not being more specific. I know that I’m not doing anything with the variable. The code is still work in progress and I wanted to test if pressing V7 in the Blynk app does it’s job. And it works, but only after the openblinds function finish to execute.
I have tried adding Blynk.run() to the for loop of openblinds, but it’s producing the exact result as before. The V7 press is detected only after the openblinds function finishes executing

Here’s my updated code:

// Arduino Program to control blinds using stepper motor 

#define BLYNK_TEMPLATE_ID           "asd" //The template ID can be find in Blynk web console
#define BLYNK_TEMPLATE_NAME           "asd" // Device name can be found in Blynk Console
#define BLYNK_AUTH_TOKEN            "asd" //Auth token can be found in Blynk web console
#define BLYNK_PRINT Serial

#include <FastLED.h>

#include <ESP8266WiFi.h> // Library for ESP8266 chip

#include <BlynkSimpleEsp8266.h> //Library for Blynk

#define BLYNK_PRINT Serial
#define LED_PIN D0
#define NUM_LEDS 1

CRGB leds[NUM_LEDS];

const int stepPin = D1; 
const int dirPin = D2; 
const int TMC2208enablePin = D3;
const int hall1Pin = D5;
const int hall2Pin = D6;
const int MS1Pin = D7;
const int MS2Pin = D8;

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "asd";
char pass[] = "asd";

boolean stopbutton = false;


///////////////////////////////////////
//   SETUP AREA                     //
/////////////////////////////////////


void setup()
{
  Serial.begin(115200);

  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
  FastLED.clear();
  FastLED.show();

  delay(100);
  Serial.print("Connecting to "); // Waiting for network connection
  Serial.println(ssid); 
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid,pass); 


  while (WiFi.status() != WL_CONNECTED) //You will hang up in this loop until you connect...
  { delay(1000); 
  Serial.println("."); 
  FastLED.clear();
  FastLED.show();
  }
  Serial.print("\r\nConnected: local ip address is http://"); // Now it's connected to network
  Serial.println(WiFi.localIP());
  Serial.println();

  Blynk.config(auth); // For connecting to Blynk service

  pinMode(stepPin,OUTPUT); 
  pinMode(dirPin,OUTPUT);
  pinMode(TMC2208enablePin,OUTPUT);
  pinMode(hall1Pin,INPUT);
  pinMode(hall2Pin,INPUT);
  pinMode(MS1Pin,OUTPUT); //Used for Microstepping
  pinMode(MS2Pin,OUTPUT); //Used for Microstepping

  digitalWrite(TMC2208enablePin,HIGH); //D3 High disables the A4988 driver to prevent overheating
  digitalWrite(MS1Pin,HIGH); 
  digitalWrite(MS2Pin,LOW);

  leds[0] = CRGB(0, 0, 255);
  FastLED.show();
}


//////////////////////////////////
// BLYNK FUNCTIONS             //
////////////////////////////////


BLYNK_WRITE(V1) //OPEN the BLINDS
{
    Serial.println("V1 pressed");
    openblinds();
}


BLYNK_WRITE(V2) //CLOSE the BLINDS
{
    Serial.println("V2 pressed");
    closeblinds(); 
}

BLYNK_WRITE(V7)
{    
    Serial.println("V7 pressed");
    stopbutton = true;
}

///////////////////////////
//    LOOP              //
/////////////////////////


void loop()
{
  Blynk.run(); // We run blynk continously
  if (WiFi.status() == WL_CONNECTED)
  {
  ledblue();
  }
}

//////////////////////////////////
//FUNCTIONS                    //
////////////////////////////////


  void openblinds() //  This is called by Blynk pin V1 to OPEN the BLINDS
{

if (digitalRead(hall1Pin) == HIGH) 
{
    digitalWrite(MS1Pin,HIGH);
    digitalWrite(MS2Pin,LOW);
    leds[0] = CRGB(0, 255, 0 );
    FastLED.show();
    digitalWrite(TMC2208enablePin,LOW);
    digitalWrite(dirPin,HIGH); // Enables the motor to move in a particular direction
    for(int x = 0; x < 2000; x++) {
    Blynk.run();
    digitalWrite(stepPin,HIGH); 
    delay(1); 
    digitalWrite(stepPin,LOW); 
    delay(1);
    if (digitalRead(hall2Pin) == LOW || stopbutton == true) {
      break;
      FastLED.clear();
    }
  }
  }
    digitalWrite(TMC2208enablePin,HIGH); //We disable the stepper.
}

    void closeblinds() // This is called by Blynk pin V2 to CLOSE the BLINDS
{
  if (digitalRead(hall2Pin) == HIGH) {
    digitalWrite(MS1Pin,HIGH);
    digitalWrite(MS2Pin,LOW);
    leds[0] = CRGB(255, 0, 0 );
    FastLED.show();
    digitalWrite(TMC2208enablePin,LOW);
    digitalWrite(dirPin,LOW); // Enables the motor to move in a particular direction
    for(int x = 0; x < 8000; x++) {
    digitalWrite(stepPin,HIGH); 
    delay(1); 
    digitalWrite(stepPin,LOW); 
    delay(1);
        if (digitalRead(hall1Pin) == LOW) {
      break;
      FastLED.clear();
    }
    }
  }
    digitalWrite(TMC2208enablePin,HIGH); //We disable the stepper.
}


  void ledblue()
  {
  leds[0] = CRGB(0, 0, 255 );
  FastLED.show();
  }

I’d suggest that you do some testing with a simplified version of the sketch, without all of the unnecessary stuff.

Pete.

Hi, Pete!
Thank you for your help!

I tried what you suggested and I have the same behavior. I modified the code to do the simplest task I could think of, while allowing me to observe the behavior. So I now have 2 Blynk buttons connected to two virtual pins (V1 and V7). After connecting to Blynk server, V1 prints an output to serial when pressed and then loops through Blynk.run() and some delays. V7 is only printing to serial when pressed.
Expected behavior would be to press V1 and see the output in serial monitor. Then, when I press V7, while V1 does it’s stuff, to see the V7 output printed to serial monitor. Real life result is the same as before: I press V1 and after 1-2 seconds, I press V7. V1 shows the output in the serial monitor. V7 only shows it after V1 finishes it’s for loop.
My conclusion is that Blynk.run() is just ignored in the for loop and only executes inside the void loop.

Probably not very relevant, but I also tried the code on an ESP32 board and I got the exact same behavior.

My code below:


#define BLYNK_TEMPLATE_ID           "asd" //The template ID can be find in Blynk web console
#define BLYNK_TEMPLATE_NAME           "asd" // Device name can be found in Blynk Console
#define BLYNK_AUTH_TOKEN            "asd" //Auth token can be found in Blynk web console
#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h> // Library for ESP8266 chip

#include <BlynkSimpleEsp8266.h> //Library for Blynk


#define BLYNK_PRINT Serial

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "asd";
char pass[] = "asd";


void setup()
{
  Serial.begin(115200);

  delay(100);
  Serial.print("Connecting to "); // Waiting for network connection
  Serial.println(ssid); 
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid,pass); 


  while (WiFi.status() != WL_CONNECTED) //You will hang up in this loop until you connect...
  { delay(1000); 
  Serial.println("."); 
  }
  Serial.print("\r\nConnected: local ip address is http://"); // Now it's connected to network
  Serial.println(WiFi.localIP());
  Serial.println();

  Blynk.config(auth); // For connecting to Blynk service

}

BLYNK_WRITE(V1)
{
    Serial.println("V1 pressed");
    for(int x = 0; x < 2000; x++) {
    delay(1);
    Blynk.run();
    delay(1);
    }
}

BLYNK_WRITE(V7)
{    
    Serial.println("V7 pressed");
}


void loop()
{
  Blynk.run(); // We run blynk continously
}

a quick test revealed that within a timer function, a Blynk.run() as part of a for loop will run and will allow Blynk_writes to be executed, even when the timer function is still be executed.

Why don’t you give it a try to move the contents of your Blynk_Writes into timer functions and use the Write function itself just to enable the execution of the body of the timer function.

regards,

piet.

Hi Pierre!
Thank you for your help. I was also investigating how I could use the timer function, but my coding skills are not the best, so I did manage to get a working demo. Could you please share the code that you tested with?

I did not use your code to test but simple added some testcode to one of my running device along the following lines:

boolean hit = 0;

BLYNK_WRITE(V1)
{
    hit = 1;
}

void timertest() {
Serial.println("start");    
for(int x = 0; x < 2000; x++) {
    delay(1);
    Blynk.run();
    if (hit = 1) {
     Serial.println(hit);
     hit = 0;
    }
    delay(1);
}
Serial.println("stop");


timer.setInterval(10000L, timertest);

The timer function runs every 10 seconds and will display “hit” between “start” and “stop”, whenever you hit V1 (during the execution of the timer function).

If you want to take this approach, then I leave it up to you to change your code accordingly.

Piet.

Putting a for loop inside a BLYNK_WRITE function certainly isn’t wat I suggested, and is complicating things rather than simplifying them.
The use of delays doesn’t help either, as they just block all code execution.

Pete.