DC Motor Speed Control with Blynk

Hello,
I am trying to control the speed of a DC motor using the slider widget on Blynk. I am using an arduino mega, a motor shield, and an esp8266 module. If this isn’t possible with the slider, do you know of better widgets to use? I have posted my code and the error below. I removed my wifi info for privacy reasons. Thank you!

I’ve also noticed that when I add more void loops, the Blynk app reconnects/connects over and over. I try not to add to the main void loop because I know it should stay “clean”

#define BLYNK_PRINT Serial

#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <AFMotor.h>


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

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "";
char pass[] = "";
// Hardware Serial on Mega, Leonardo, Micro...
#define EspSerial Serial1

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

// Your ESP8266 baud rate:
#define ESP8266_BAUD 115200

ESP8266 wifi(&EspSerial);

AF_DCMotor motor(2);

int x = 0;

BlynkTimer timer;


void myTimerEvent()
{
  // You can send any value at any time.
  // Please don't send more that 10 values per second.
  Blynk.virtualWrite(V5, millis() / 1000);

}


void getMotor()
{
    motor.run(FORWARD);
  static int value = 0;
  static int delta = 30;
  value += delta;
  if (value > 255 || value < 0) {
    delta = -delta;
  } else {
    Serial.print("LED on V2: ");
    Serial.println(value);
    motor.setSpeed(value);
    
  }
  x = motor.setSpeed(value);
   
   Blynk.virtualWrite(V20, x );
 
  
}
void setup()
{
  // Debug console
  Serial.begin(9600);
 // pinMode(dataIN,INPUT);
  // Set ESP8266 baud rate
  EspSerial.begin(ESP8266_BAUD);
  delay(10);

  Blynk.begin(auth, wifi, ssid, pass);
  // You can also specify server:
  //Blynk.begin(auth, wifi, ssid, pass, "blynk-cloud.com", 80);
  //Blynk.begin(auth, wifi, ssid, pass, IPAddress(192,168,1,100), 8080);

  // Setup a function to be called every second
  timer.setInterval(1000L, myTimerEvent);
  timer.setInterval(5000L, getMotor);
  
#ifndef ESP8266
    while (!Serial);     // will pause Zero, Leonardo, etc until serial console opens
  #endif

//motor.run(RELEASE);
   motor.run(FORWARD);
}

void loop()
{
  Blynk.run();
  timer.run(); // Initiates BlynkTimer
}



wififix_motor:63:5: error: void value not ignored as it ought to be

   x = motor.setSpeed(value);

     ^

Multiple libraries were found for "BlynkSimpleShieldEsp8266.h"
 Used: C:\Users\Arduino\Documents\Arduino\libraries\Blynk
 Not used: C:\Users\Arduino\Documents\Arduino\libraries\blynk-library-0.6.1
exit status 1
void value not ignored as it ought to be




The function is called not correctly, function prototype is

void setSpeed(uint8_t);

You can change getMotor() as follows:


void getMotor()
{
  static int value = 0;
  static int delta = 30;

  motor.run(FORWARD);

  value += delta;
  if (value > 255 || value < 0) 
  {
    delta = -delta;
    value += delta;
  }

  Serial.print("LED on V2: ");
  Serial.println(value);
  motor.setSpeed(value);    
  Blynk.virtualWrite(V20, value ); 
}
2 Likes

Thank you!
It runs, but the slider moves by itself. I won’t touch it and it goes from 240 to 7 etc.

That is what the code is telling it to do. @khoih just fixed the code you had provided.

Remove the void getMotor() function, and try replacing it with something like this:

 BLYNK_WRITE(V20)
{
  int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable
  
  motor.run(FORWARD);
  Serial.println(pinValue);
  motor.setSpeed(pinValue);    

}
2 Likes

Thank you!

Would you know how to have an input voltage control the speed of the motor?
I have this so far

#define BLYNK_PRINT Serial
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <SPI.h>
#include <AFMotor.h>


//Assign volt valuesto somenumbertostart with
float volt1 = 2;

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

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

// Hardware Serial on Mega, Leonardo, Micro...
//Location of RX and TX pins on Arduino board
#define EspSerial Serial3

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

// Your ESP8266 baud rate:
#define ESP8266_BAUD 115200

ESP8266 wifi(&EspSerial);

//Identify location of motor on shield
AF_DCMotor motor(1);
void setup()
{
  // Debug console
  Serial.begin(115200);
  EspSerial.begin(ESP8266_BAUD);
  delay(2000);

  Blynk.begin(auth, wifi, ssid, pass);
  Blynk.begin(auth, wifi, ssid, pass, "blynk-cloud.com", 8442);
  //Blynk.begin(auth, wifi, ssid, pass, IPAddress(192,168,1,100), 8442);

  timer.setInterval(5000L, getVolt);

motor.run(RELEASE);
  //motor.run(FORWARD);
}



void getVolt()
{
  //assign the volt readings to an analogue pin 
  //volt1
volt1 = analogRead(A1);//Read the value of the potentiometer to val
  volt1 = volt1/1024*5.0;
Blynk.virtualWrite(V1, volt1);

}
BLYNK_WRITE(V20)
{
  //Connect a virtual pin to the motor to control its speed
  int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable
  //Tell motor to run in one direction, forward
  motor.run(FORWARD);
  Serial.println(pinValue);
  motor.setSpeed(pinValue);    
if (V1 >=5)
{
  motor.setSpeed(pinValue/2);
}


}

void loop()
{
  //Keep loop clean
  //run blynk app and timer
 Blynk.run();
 timer.run(); // Initiates BlynkTimer
}
    ```

You could either set the speed within the function measuring the voltage, or trigger the slider function from within the function measuring the voltage.

You will also not want the potentiometer reading to constantly override the slider value, so you will need to make sure the potentiometer has changed before executing that part of the code.

I would also map the incoming values, instead of performing the math as you have done. Although I do not know exactly how your setup functions.

Some untested code snippets that may/maynot work, but should give you an idea.

//Assign volt valuesto somenumbertostart with
int volt1 = 0; // same as volt 2 so you need to move potentiometer upon startup
int volt2 = 0;

void setup()
{
  // Debug console
  Serial.begin(115200);
  EspSerial.begin(ESP8266_BAUD);
  delay(2000);

  Blynk.begin(auth, wifi, ssid, pass);
  //Blynk.begin(auth, wifi, ssid, pass, "blynk-cloud.com", 8442);
  //Blynk.begin(auth, wifi, ssid, pass, IPAddress(192,168,1,100), 8442);

   motor.run(RELEASE);
  //motor.run(FORWARD);
   motor.setSpeed(volt1); //start at volt1 speed, 0

 timer.setInterval(100L, getVolt);//run every .1 seconds to be somewhat responsive, increase if necessary
}
void getVolt()
{
  //assign the volt readings of the analogue pin to volt1
  volt1 = analogRead(A1);//Read the value of the potentiometer to volt1
 Serial.print("volt1 =");
 Serial.println(volt1);
if (volt1 != volt2)
   {
   Serial.println("Motor Speed Changed Via Pot");
   volt2 = volt1;
   volt1 = map(volt1, 0, 1023, 0, 255); //assuming 0 = motor off, 255 = motor full speed
   Blynk.virtualWrite(V20, volt1); //set slider to reading of poteniometer
   motor.setSpeed(volt1); 
    // or
   //Blynk.syncVirtual(V20); //runs BLYNK_WRITE(V20) function; comment out motor.setSpeed(volt1); above
   }  
}

BLYNK_WRITE(V20)
{
  //Connect a virtual pin to the motor to control its speed
  int pinValue = param.asInt(); // assigning incoming value from pin V20 to a variable
  Serial.println("Motor Speed Changed Via Slider");
  //Tell motor to run in one direction, forward
  motor.run(FORWARD);
  Serial.println(pinValue);
  motor.setSpeed(pinValue);    
}

Thank you for your help!
To explain:
I am connecting the motor’s current output to volt1, and have that as an input value in the arduino. I’m trying to get a feedback loop. Where if the current reaches a certain limit, then the motor would slow down .

Then what I provided will most likely not work for what you are trying to achieve.

You will need to convert the motor current to a voltage output. This will most likely be done with a current sensor that has an analog output. Then just check that value every so often and take the appropriate action when it reaches your predetermined value. As an example:

int maxValue = 3; // current sensor value that will trigger slowdown
int safeValue = 100; //safe motor speed

void getVolt()
{
  //assign the volt readings of the analogue pin to volt1
  volt1 = analogRead(A1);//Read the value of the current sensor to volt1
 Serial.print("volt1 =");
 Serial.println(volt1);
if (volt1 >= maxValue)
   {   
   motor.setSpeed(safeValue); 
   }  
}

Thank you this worked!
Is it possible to make the speed go back to its slider speed once the current is at an acceptable value? I tried making it a while loop, but I get more Packet too big errors.

If the slider is setting the speed, wouldn’t it just go back to the speed that caused the current to go to high in the first place?

Why not just limit the slider so the speed doesn’t go too high in the first place?

:sweat_smile: Good point.

You can adjust the slider up gradually if the current fell back lower than certain threshold. Use a timer to check and make decision.

For example, pseudo-code based on @Toro_Blanco code


int maxValue = 3; // current sensor value that will trigger slowdown
int safeValue = 100; //safe motor speed
int currentMotorSpeed;

#define SPEED_STEP   5       // Just example
#define SET_SPEED     250    // Just example

void motorControl()
{
  //assign the volt readings of the analogue pin to volt1
  volt1 = analogRead(A1);//Read the value of the current sensor to volt1
  Serial.print("volt1 =");
  Serial.println(volt1);

  if (volt1 >= maxValue)
  {   
    // Overload, reduce speed immediately to very low
    currentMotorSpeed = safeValue;     
   }
  else if (volt1 < someSmallerValue)
  {   
   // Gradually increase speed if current OK
    currentMotorSpeed += SPEED_STEP;     
   }
   else if (volt1 > someBiggerValue)
  {   
    // Gradually decrease speed if current > some limit to avoid overload
    currentMotorSpeed -= SPEED_STEP;     
   }

   if (currentMotorSpeed > SET_SPEED)
     currentMotorSpeed = SET_SPEED;

   motor.setSpeed(currentMotorSpeed);
   // Change slider speed display
   Blynk.virtualWrite(BLYNK_VPIN_SLIDER, currentMotorSpeed);
}

void setup()
{
   ...

   timer.setInterval(2000, motorControl);
   ...
}

I see you’re interested in embedded control system.

Although it might be not closely related to this project, I think you’d better read the PID library and functions as you can apply it somewhere sometime in your future project.

https://playground.arduino.cc/Code/PIDLibrary/

http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/

1 Like

I’ll try this out, thank you!