How to use Blynk.run() properly on ESP32 for AccelStepper library

If you are having issues with AccelStepper (or any other blocking code) working with Blynk on an ESP32, here is how to fix it.

DO NOT place Blynk.run() into the loop on an ESP32.

AccelStepper uses very intensive blocking code to run. To get around this, I originally placed the motor code into the second core and left Blynk.run() in the main loop.

This partially worked but caused major chattering in the motor, because something was periodically blocking the motor on the second core when Blynk established a connection.

I learned that in Arduino, all WiFi code is run on Core 0, and your main code is run on Core 1 (which is the loop). You can change this in FreeRTOS, but not in Arduino.

If you place Blynk.run() in the loop, it will take up processes on both Core 1 and Core 0, resulting in problems with AccelStepper.

We need to place Blynk.run() on Core 0, and NOT in the loop.

Here is the code to fix it below. Let me explain what is going on.

in setup()

disableCore0WDT(); will disable the watchdog timer. For some reason, it doesn’t stop going off.

Then we create the second core (Core 0):

xTaskCreatePinnedToCore(
   core0assignments,        // Function that should be called
   "Core_0",          // Name of the task (for debugging)
   10000,                   // Stack size (bytes)
   NULL,                   // Parameter to pass
   1,                      // Task priority//0
   &C0,                 // Task handle
   0);                     // Core you want to run the task on (0 or 1)

Then we create this function to run our Blynk.run() loop in Core 0:

void core0assignments( void * pvParameters ) { 
for (;;) {
     Blynk.run();
  }
}

Here is my entire code which uses accelstepper, I’ve removed as much as possible to clean it up.

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

#include <HardwareSerial.h>
#include <TMCStepper.h>
#include <AccelStepper.h>

#define DIAG_PIN_2         12          // STALL motor 2
#define DRV_ENN            32          // Enable
#define DIR_PIN_2          14          // Direction
#define STEP_PIN_2         13          // Step

#define SERIAL_PORT_2      Serial2    // TMC2208/TMC2224 HardwareSerial port
#define DRIVER_ADDRESS_2   0b00       // TMC2209 Driver address according to MS1 and MS2
#define R_SENSE_2          0.12f      // E_SENSE for current calc.  

#define SPEED              7000

#define btn1 18
#define btn2 21

char AUTH[] = "AUTH";
char SSID[] = "WIFI";
char PASSWORD[] = "PASS";

TMC2209Stepper driver2(&SERIAL_PORT_2, R_SENSE_2 , DRIVER_ADDRESS_2 );
AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN_2, DIR_PIN_2);
TaskHandle_t C0;

void setup() {

  disableCore0WDT();
  
  xTaskCreatePinnedToCore(
   core0assignments,        // Function that should be called
   "Core_0",          // Name of the task (for debugging)
   10000,                   // Stack size (bytes)
   NULL,                   // Parameter to pass
   1,                      // Task priority//0
   &C0,                 // Task handle
   0);                     // Core you want to run the task on (0 or 1)

   
  Serial.begin(250000);         // Init serial port and set baudrate
  delay(200);
  
  SERIAL_PORT_2.begin(115200);
  
  pinMode(DIAG_PIN_2 ,INPUT);
  pinMode(DRV_ENN ,OUTPUT);
  pinMode(STEP_PIN_2 ,OUTPUT);
  pinMode(DIR_PIN_2 ,OUTPUT);
  pinMode(btn1,INPUT_PULLUP);
  pinMode(btn2,INPUT_PULLUP);
  driver2.begin();
  driver2.toff(4);
  driver2.blank_time(24);
  driver2.rms_current(300); 
  driver2.microsteps(16);
  driver2.TCOOLTHRS(300); // 
  driver2.semin(0);
  driver2.semax(2);
  driver2.shaft(true);
  driver2.sedn(0b01);
  driver2.SGTHRS(80);//Stall Value
  driver2.en_spreadCycle(false);
  driver2.pdn_disable(true);
  stepper.setEnablePin(DRV_ENN);
  stepper.setPinsInverted(false, false, true);
  stepper.disableOutputs();
  stepper.setMaxSpeed(SPEED);
  stepper.setSpeed(SPEED);
  stepper.setAcceleration(3000);
  stepper.setCurrentPosition(0);
  
  Serial.println("DONE Setting");

  Blynk.begin(AUTH, SSID, PASSWORD);
  
}


void core0assignments( void * pvParameters ) { 
for (;;) {
     Blynk.run();
  }
}


void loop() {
  
  if(digitalRead(btn1)==LOW){
      stepper.moveTo(500000);
      move_motor();
    }
    
    if(digitalRead(btn2)==LOW){
      stepper.moveTo(0);
      move_motor();
    }
}



void move_motor(){
  Serial.println(stepper.currentPosition());
  Serial.println(stepper.targetPosition());
  stepper.setMaxSpeed(SPEED);
  stepper.setAcceleration(1000);
  stepper.enableOutputs();
  while(stepper.currentPosition() != stepper.targetPosition() ){
  stepper.run();
  }
  stepper.disableOutputs();
  Serial.println("finished moving");
 }