Delay() in blynk Sketch

I want to control a model Train with the blynk App over Wifi. Basically i want to use 3 different virtual Pins to control the Motor. One Switch (V2) to Switch between Forward and backward. One slider (V0) to set the Speed and another slider (V1) to control how fast the Motor changes the Speed (like a controllable soft start and soft break). So i wrote this sketch, it works but the Lokomotive acts delayed. Is it because i use delay()? and how i can change this?

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


#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

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

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


// motorshield - Arduino
int enA = 9;   //PWM
int in1 = 8;   //+
int in2 = 7;   //-

int prevSpeed;  //previous Value Slider V0
int OutSpeed;   //Current Ouput Speed
int SpeedV0;    //Slider "Geschwindigkeit" V0
int xV1;        //Slider "Beschleunigung" V1
int bckV2;      //Switch "Rückwärts"

// Hardware Serial on Mega, Leonardo, Micro...
//#define EspSerial Serial1

// or Software Serial on Uno, Nano...
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(10, 11); // RX, TX

// Your ESP8266 baud rate:
#define ESP8266_BAUD 9600

ESP8266 wifi(&EspSerial);

BLYNK_WRITE(V0)
{
  SpeedV0 = param.asInt(); // assigning incoming value from pin V1 to a variable
  // You can also use:
  // String i = param.asStr();
  // double d = param.asDouble();
  //Serial.print("V1 Slider value is: ");
  //Serial.println(pinValue);
}

BLYNK_WRITE(V1)
{
  xV1 = param.asInt(); // assigning incoming value from pin V1 to a variable
  // You can also use:
  // String i = param.asStr();
  // double d = param.asDouble();
  //Serial.print("V1 Slider value is: ");
  //Serial.println(pinValue);
}

BLYNK_WRITE(V2)
{
  bckV2 = param.asInt(); // assigning incoming value from pin V1 to a variable
  // You can also use:
  // String i = param.asStr();
  // double d = param.asDouble();
  //Serial.print("V1 Slider value is: ");
  //Serial.println(pinValue);
}

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

  delay(10);

  // Set ESP8266 baud rate
  EspSerial.begin(ESP8266_BAUD);
  delay(10);

  Blynk.begin(auth, wifi, ssid, pass);
  
  // set all the motor control pins to outputs
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  
  stop();
  xV1 = 30;
  bckV2 = LOW;
  
}

void loop()
{
  
  Blynk.run();
  
  if (SpeedV0 == 0){
    stop();
    Serial.println("Motorstate: STOPP");
  }
  if (bckV2 == HIGH){
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
    Serial.println("Motorstate: BACKWARD");
  }
  else
  {
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    Serial.println("Motorstate: VORWARD");
  }
  if (SpeedV0 > prevSpeed){
  SpeedUP();
  }
  if (SpeedV0 < prevSpeed){
  SpeedDOWN();
  }
  
  Serial.print("SpeedV0: ");
  Serial.print(SpeedV0);
  Serial.print(" / prevSpeed: ");
  Serial.println(prevSpeed);
  
  prevSpeed = SpeedV0;

}


void SpeedUP()
{
  // accelerate OutSpeed to SpeedV0
  for (int OutSpeed = prevSpeed; OutSpeed < (SpeedV0 + 1) ; OutSpeed++)
  { 
    analogWrite(enA, OutSpeed);
    delay(xV1);  
    Serial.print("Motor Speed+: ");
    Serial.println(OutSpeed);
  } 

}


void SpeedDOWN()
{  
  // decelerate OutSpeed to SpeedV0
  for (int OutSpeed = prevSpeed; OutSpeed > (SpeedV0 - 1); --OutSpeed)
  {
    analogWrite(enA, OutSpeed);
    delay(xV1);  
    Serial.print("Motor Speed-: ");
    Serial.println(OutSpeed);
  }
 
}

void stop(){
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  SpeedV0 = 0; 
}



Welcome,

Read the documents in the Help Center for more information on how to setup your sketches for best Blynk usage. Timers instead of delay() and timed functions instead of dumping everything into the void loop()

@p_wiedmer and for such a simple project we would recommend you switch from the old Arduino’s to the modern ESP8266 board’s that were designed for iOT.

Arduino/ESP also has a DCC library so you can actually make your ESP into a decoder to work with Roco and Fleischmann controller units :slight_smile:

So i read about timers, an changed my sketch to this. Does it look better now and could it work, bc i cannot test it right now.


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

#include <SimpleTimer.h>
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

char auth[] = "1"; //Auth Token

// WiFi credentials
char ssid[] = "iPhilion";
char pass[] = "12387654";

// motorshield - Arduino
int enA = 9;   //PWM
int in1 = 8;   //+
int in2 = 7;   //-

int OutSpeed;   //Current Ouput Speed
int SpeedV0;    //Slider "Geschwindigkeit" V0
int bckV2;      //Switch "Rückwärts"
int timerID;

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

// Your ESP8266 baud rate:
#define ESP8266_BAUD 9600

ESP8266 wifi(&EspSerial);

SimpleTimer timer;

BLYNK_WRITE(V0)
{
  SpeedV0 = param.asInt(); // assigning incoming value from pin V0 to a variable
}

BLYNK_WRITE(V1)
{
  int repeatTime = param.asInt(); //0-100  
  timer.deleteTimer(timerID);
  timerID = timer.setInterval(repeatTime * 1L, changeSpeed);
}

BLYNK_WRITE(V2)
{
  bckV2 = param.asInt(); // assigning incoming value from pin V2 to a variable
}

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

  delay(10);

  // Set ESP8266 baud rate
  EspSerial.begin(ESP8266_BAUD);
  delay(10);

  Blynk.begin(auth, wifi, ssid, pass);
  
  // set all the motor control pins to outputs
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  
  stop();
  
}


void TrainControl(){
  
  if (SpeedV0 == 0){
    stop();
    Serial.print("Motorstate: STOPP  ");
  }
  
  if (bckV2 == HIGH){
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
    Serial.print("Motorstate: BACKWARD  ");
  }
  
  else{
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    Serial.print("Motorstate: VORWARD  ");
  }
  
  analogWrite(enA, OutSpeed);
  Serial.print("Motor Speed: ");
  Serial.println(OutSpeed);
}


void stop(){
  
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  OutSpeed = 0; 
}


void changeSpeed(){
  
  if (OutSpeed < SpeedV0){  // Speed up
    OutSpeed++;
  }
  
  if (OutSpeed > SpeedV0){  // Speed down
  OutSpeed--;
  }
}  


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

  timer.run();

}

already have my materials but thanks and i will use it the next time

i don’t know a lot about model Trains so i’m just trying to work with arduino for a school project

I see, in that case this could work too :slight_smile:

Your sketch looks a bit better, but you cannot call TrainControl from the loop(). Use a timer with that too. There is no way you can notice a 200ms or 500ms reaction delay when controlling your train. It should be almost instant, but it’s a lot better for the stability of your program.

I don’t know why you’d want a variable timer setting, but I guess it could work this way, just make sure you also time the TrainControl() void.

thank you,
does it look better like this:

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

#include <SimpleTimer.h>
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

char auth[] = "87edecee065d471681b528250161f607"; //Auth Token

// WiFi credentials
char ssid[] = "iPhilion";
char pass[] = "12387654";

// motorshield - Arduino
int enA = 9;   //PWM
int in1 = 8;   //+
int in2 = 7;   //-

int OutSpeed;   //Current Ouput Speed
int SpeedV0;    //Slider "Geschwindigkeit" V0
int bckV2;      //Switch "Rückwärts"
int timerID;

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

// Your ESP8266 baud rate:
#define ESP8266_BAUD 9600

ESP8266 wifi(&EspSerial);

SimpleTimer timer;

BLYNK_WRITE(V0)
{
  SpeedV0 = param.asInt(); // assigning incoming value from pin V0 to a variable

  if (SpeedV0 == 0){
    stop();
    Serial.print("Motorstate: STOPP  ");
  }
  
}

BLYNK_WRITE(V1)
{
  int repeatTime = param.asInt(); //0-100  
  timer.deleteTimer(timerID);
  timerID = timer.setInterval(repeatTime * 1L, changeSpeed);
}

BLYNK_WRITE(V2)
{
  bckV2 = param.asInt(); // assigning incoming value from pin V2 to a variable

    if (bckV2 == HIGH){
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
    Serial.println("Motorstate: BACKWARD");
  }
  
  else{
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    Serial.println("Motorstate: VORWARD");
  }
}

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

  delay(10);

  // Set ESP8266 baud rate
  EspSerial.begin(ESP8266_BAUD);
  delay(10);

  Blynk.begin(auth, wifi, ssid, pass);
  
  // set all the motor control pins to outputs
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  
  stop();
  
}


void stop(){
  
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  OutSpeed = 0; 
}


void changeSpeed(){
  
  if (OutSpeed < SpeedV0){  // Speed up
    OutSpeed++;
  }
  
  if (OutSpeed > SpeedV0){  // Speed down
  OutSpeed--;
  }

  analogWrite(enA, OutSpeed);
  Serial.print("Motor Speed: ");
  Serial.println(OutSpeed);
}  


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

}

i dont know what you think of when you say " just make sure you also time the TrainControl() void.", how should i do this? i want it to run like it is in void loop.
“I don’t know why you’d want a variable timer Setting” this was just the solution i thougt of, to realize the controllable soft start/break

I think you are overthinking it.

Your last code looks nice and clean. I’d try it that way.

Again, you cannot run anything other than the timer and Blynk in the loop. You cannot run other functions from there because they will interfere with blynk since the loop gets executed hunders of thousands of time per second.

works like this thank you! :stuck_out_tongue_winking_eye::stuck_out_tongue_winking_eye: still some adjustments to do