Blynk 2.0 and Accelstepper enable pin

Hi, I’m tryng to develop a catfeeder in which a stepper motor turn an auger. Up to now I’ve been able to develop the web dashboard on desktop and mobile and to run the steppr for a certain number of step. I’m using a nema 17 stepper motor, the A4988 driver and the lolin D1 mini pro. All works fine except the fact that the stepper driver is always enabled and i would like to enable it just before run and desable it when the feeding has been finished.
I’ve tried using “mystepper.enableOutputs();” and disable output but it doesn’t work.

Here below the code i used:

// Fill-in information from your Blynk Template here
#define BLYNK_TEMPLATE_ID "xxxx"
#define BLYNK_DEVICE_NAME "Stepper"

#define BLYNK_FIRMWARE_VERSION        "0.1.0"

#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG

#define APP_DEBUG

// Uncomment your board, or configure a custom board in Settings.h
//#define USE_SPARKFUN_BLYNK_BOARD
//#define USE_NODE_MCU_BOARD
//#define USE_WITTY_CLOUD_BOARD
#define USE_WEMOS_D1_MINI

#include <AccelStepper.h>

#include "BlynkEdgent.h"
int LED = 16; //GPIO16 -- D0
int DIR = 4; //GPIO04 -- D2 
int STEP = 12; // GPIO12 --D6 
int EN = 14; //GPIO14 -- D5;//Enable Pin - active low
int steps = 30000;
int Direction = 0;
int Run = 0;
AccelStepper mystepper(1,STEP, DIR);


BLYNK_WRITE(V0)
{
int pinValue=param.asInt(); //assigning icoming valure from pin V0 to a variable
  digitalWrite(LED, pinValue); // low activate led High switch off

}

BLYNK_WRITE(V1)
{
  Direction=param.asInt(); //assigning icoming valure from pin V1 to a variable
}

BLYNK_WRITE(V2)
{
 steps=param.asInt(); //assigning icoming valure from pin V2 to a variable
}
BLYNK_WRITE(V3)
{
  Run=param.asInt(); //assigning icoming valure from pin V3 to a variable
           mystepper.enableOutputs();
           Serial.println("--------------------------");
           Serial.println("RUN");
           Serial.println(Run);
           Serial.println("Direzione");
           Serial.println(Direction);
           Serial.println("Numero steps");
           Serial.println(steps);
           Serial.println("--------------------------");
    if (Run == 1) {

         if (Direction == 1) { 
         mystepper.move(steps); // 
            } else {
               mystepper.move(-steps);
               }
  
         }      
}
 

void setup()
{
 pinMode(LED, OUTPUT); 
 pinMode(DIR, OUTPUT); 
 pinMode(STEP, OUTPUT); 
 pinMode(EN, OUTPUT); 
 Serial.begin(115200);
 
 delay(100);
   mystepper.setEnablePin(EN);
   mystepper.setPinsInverted(false, false, true);
   mystepper.setMaxSpeed(50); // valore originale 50
   mystepper.setAcceleration(50);

  BlynkEdgent.begin();
}

void loop() {
  digitalWrite(DIR, Direction); 
  BlynkEdgent.run();
  mystepper.run();
  mystepper.disableOutputs();
}

I’ve tried also to use digitalwrite(EN, LOW) to enable it or digitalwrite(EN, HIGH); within the BLYNK_WRITE(V3) function but seems that the code don’t wait the completion of “mystepper.move(steps)” before to go to the next line that is the digitalwrite(EN, HIGH);, so the enable pin is enabled and immediatly after disabled.

Thnaks a lot,
Mario

@Skid72 Please edit your post, using the pencil icon at the bottom, and add triple backticks at the beginning and end of your code so that it displays correctly.

Triple backticks look like this:
```

Pete.

Thanks Pete, I’ve just updated it.

I’d start here…

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

Pete.

Do you thi k there Is a problema with loop?

Mario

Of course!

Pete.

I’ll check it.
Thanks

I think you will find issues with trying to run a stepper with blynk. Blynk requires a clean loop. Accelerstepper requires that it is called very often in the loop for each step it takes. That there is a conflict. What I did instead to get blynk and accelerstepper run together was to use an esp to handle all the blynk interface connected to arduino nano via I2C which handled the stepper. Therefore you have 2 sketches one fir esp and one for nano

The other solution is to use an ESP32 and separate Blynk and the stepper motor on the 2 cores

1 Like

What about using .runToNewPosition() inside the blynk function? According to the documentation the .runToNewPosition() doesn’t need run() in the loop and It doesn’t return until the position isn’t reached.
Off course the proposed solutions are more elegant and they not interfere with blynk.
Thanks a lot.

Yes, you only need the stepper to run for short periods of time in certain situations. It doesn’t need the stepper code in the void loop, being executed hundreds of times per second, 24 hours per day.

Moving that code into a different function, and executing it in a loop within that function only when it is required is the better option.
Just because example sketches are written in a way which constantly monitors a physical switch then moves the stepper accordingly doesn’t mean that this is the best approach in a real world scenario.

I’m not sure that the proposed solutions are more elegant, and having two boards connected via I2C certainly isn’t the direction I’d go.

The issue

I’m not exactly sure what you mean by “inside the Blynk function”, but I’d put the code inside it’s own function and call it either by a timer or a Blynk button widget as required.
If it takes too long (more than about 10 seconds) to complete the stepper cycle then you will need some Blynk.run commands inside the stepper loop to ensure you don’t get Blynk disconnections.

Pete.

@pete, thaks for the info provided, I’ll try to write something and I’ll come back here.
Now the way to proceed should be more clear to me.
Ciao,
Mario

Dear all,
I’ve updated the code as following. I removed everything from main loop and I’ve used “runToNewPosition()” that is blocking function. But the stepper doesn’t function as expected. I activated also the serial monitor to better understand.

// Fill-in information from your Blynk Template here
#define BLYNK_TEMPLATE_ID "TMPLQkw4XhUu"
#define BLYNK_DEVICE_NAME "Stepper"

#define BLYNK_FIRMWARE_VERSION        "0.1.0"

#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG

#define APP_DEBUG

// Uncomment your board, or configure a custom board in Settings.h
//#define USE_SPARKFUN_BLYNK_BOARD
//#define USE_NODE_MCU_BOARD
//#define USE_WITTY_CLOUD_BOARD
#define USE_WEMOS_D1_MINI

#include <AccelStepper.h>

#include "BlynkEdgent.h"
int LED = 16; //GPIO16 -- D0
int DIR = 4; //GPIO04 -- D2 
int STEP = 12; // GPIO12 --D6 
int EN = 14; //GPIO14 -- D5;//Enable Pin
double meal = 1.0;
int Totalsteps = 0;
int steps = 7500;
//int Direction = 0;
int Run = 0;
AccelStepper mystepper(1,STEP, DIR);


BLYNK_WRITE(V0)
{
int pinValue=param.asInt(); //assigning icoming valure from pin V0 to a variable
  digitalWrite(LED, pinValue); // low activate led High switch off
}

//BLYNK_WRITE(V1)
//{
//  Direction=param.asInt(); //assigning icoming valure from pin V1 to a variable
//}

BLYNK_WRITE(V2)
{
 meal=param.asDouble(); //assigning icoming valure from pin V2 to a variable
 
}

BLYNK_WRITE(V3)
{
  Run=param.asInt(); //assigning icoming valure from pin V3 to a variable
 // digitalWrite(EN, LOW);

    Totalsteps = meal*steps*2;
    if (Run == 1) {
       Serial.println("-----------Led ON------");
       digitalWrite(LED, HIGH);
                   while  (Totalsteps > steps) {
                       Serial.println("---inside while loop-----------------");
                       Serial.println("RUN");
                       Serial.println(Run);
                       Serial.println("meal");
                       Serial.println(meal);
                       Serial.println("numero totali steps");
                       Serial.println(Totalsteps);
                       Serial.println("--------------------------");
                       mystepper.runToNewPosition(steps); // 
                       Serial.println("---eseguiti steps-----------------"); 
                       Serial.println(steps);
                       Serial.println("-------------------------");
                       Totalsteps= Totalsteps-steps;   
                    //   BlynkEdgent.run();

                       }    
                    if (Totalsteps <= steps){
                         Serial.println("----out of while loop ----------------");
                         Serial.println("Ultimo batch steps");
                         Serial.println( Totalsteps);
                         Serial.println("--------------------------");
                         mystepper.runToNewPosition(Totalsteps);
                         Serial.println("-----------eseguiti last steps------");
                         Serial.println(Totalsteps);
                         Serial.println("--------------------------");
                      //   BlynkEdgent.run();

                  }
                   // digitalWrite(EN, HIGH);
                    Serial.println("-----------Led OFF------");
                    digitalWrite(LED, LOW);
                 }
 
}
void setup()
{
 pinMode(LED, OUTPUT); 
 pinMode(DIR, OUTPUT); 
 pinMode(STEP, OUTPUT); 
 pinMode(EN, OUTPUT); 
 Serial.begin(115200);
 
 delay(100);

 mystepper.setMaxSpeed(300); // valore originale 50
 mystepper.setAcceleration(1000);


  BlynkEdgent.begin();
}

void loop()
{
 
  BlynkEdgent.run();
 //mystepper.runSpeed();

}

This is the serial monitor after I sent “run” from the blynk app, I get in the serial monitor:

-----------Led ON------
---inside while loop-----------------
RUN
1
Meal
1.20
Numero totali steps
18000
--------------------------

And up to now it is fine, so the stepper execute 7500steps and then since the remain steps is greater than 7500 another run it is expected and in fact the stepper run again but now seems that the function “runToNewPosition()” is not blocking now and after another 7500steps, the stepper stop to run and the last block of steps will not be executed. This is the serial monitor as soon as the second block of steps is started.

-----------Led ON------
---inside while loop-----------------
RUN
1
Meal
1.20
Numero totali steps
18000
--------------------------
---eseguiti steps-----------------
7500
-------------------------
---inside while loop-----------------
RUN
1
Meal
1.20
Numero totali steps
10500
--------------------------
---eseguiti steps-----------------
7500
----out of while loop ----------------
Ultimo batch steps
3000
--------------------------

Just after completion of last step, I get:

-----------Led ON------
---inside while loop-----------------
RUN
1
Meal
1.20
Numero totali steps
18000
--------------------------
---eseguiti steps-----------------
7500
-------------------------
---inside while loop-----------------
RUN
1
Meal
1.20
Numero totali steps
10500
--------------------------
---eseguiti steps-----------------
7500
----out of while loop ----------------
Ultimo batch steps
3000
--------------------------
-----------eseguiti last steps------
3000
--------------------------
-----------Led OFF------

Another issue is related to the rotation direction. At the first run (first 7500steps), the stepper rotate clockwise, and at second run in the opposite direction. For what I understood, the direction is provided with the sign of the number of steps. To rotate clockwise, pass positive number, i.e. “runToNewPosition(+7500)” , while for anticlockwise rotation “runToNewPosition(-7500)”.

Thanks and have a nice day,
Mario

@Skid72 please edit your post and replace the serial monitor screenshots with the text copied and pasted from your serial monitor, with triple backticks at the beginning and end.

Pete.

@Pete, I’ve update the post.
I hope it is fine.
Ciao,
Mario

What type of widget is attached to V3 and how is it configured?

Pete.

It is a switch with ON value=1 and OFF value =0.

Mario

Okay, so its a switch widget on the web dashboard.
Unlike the app switch widgets, which can be set to push (momentary) or Switch (toggle) mode, this widget only works in Switch mode.

You don’t have any code to set your Run to 0 and turn the V3 widget off once the stepper actions have completed, and I think that’s why you’re seeing the re-triggering.

I think you’d need to be using signed integers for this to be read correct, but instead you’re doing math operations between integers and floats, which probably generates warning in your verbose compiler messages.

I’m not really clear why you say…

or why you’ve bothered to split the stepping process into smaller chunks to allow you to insert some BlynkEdgent.run() commands, yet have this command commented out.

Pete.

I replicated the widget on the app and I’m using the app instead of web dashboard. But since i’m writing on laptop it was easier to take a print screen on the web dashboard.
I’ll try to experiment with signed integer for the direction.
About the splitting I limited the numebr of step to avoid disconnection of the blynk adgent beacouse I inderstood that since RunToNewPosition() is blocking, there is a risk of disconnection in case of long run.
The reason for using blocking function was to allow me to use one pin for the enable on the stepper driver. In the current code I used the PIN 16 and connect a led to it to check if it remain on during the stepper rotation and it goes OFF at the end. It function correctly.
The issue I’ve now is the rotation direction that is not always cloclwise and the fact that anly two batch of steps are performed as if the blocking function was ignored the second time.
Thanks,
Mario

Just because you split the blocking function into smaller blocking functions run one after another doesn’t help Blynk.
It’s not until BlynkEdgent.run() is executed again - which in your case will be when code execution returns to the void loop, that the device and the Blynk server get chance to communicate again.

Also, if you think that an LED can be used as an indicator of whether code indication has been blocked then you’re mistaken - unless you turn that LED on/off constantly with another piece of code.

Pete.