cant control servo motor speed

Good Morning.

I Have 5-button each of which gives the servo an angular position. This function work but I can’t get the servo to go slow. The speed function don’t work. Where am I wrong? Were is the mistake in the sketch ? May you help me please ?

what at moment happen is the servo reach all positions but I cant control its speed.

#include <Servo.h>

#define pinServo 9

#define pinButt1 1
#define pinButt2 2
#define pinButt3 3
#define pinButt4 4
#define pinButt5 5

const int angleIncrement = 1;
const int incrementDelay = 30;

Servo myservo;

void setup() {

myservo.attach (pinServo) ;

pinMode (pinButt1, INPUT);
pinMode (pinButt2, INPUT);
pinMode (pinButt3, INPUT);
pinMode (pinButt4, INPUT);
pinMode (pinButt5, INPUT);

}

void loop() {
  
 if (digitalRead (pinButt1) == 1) for (int angle = 0; angle < 30; angle += angleIncrement) // Posizionamento a 30 gradi con incremento a singolo grado
myservo.write (angle);
delay (incrementDelay);

if (digitalRead (pinButt2) == 1) for (int angle = 0; angle < 60; angle += angleIncrement) // Posizionamento a 60 gradi con incremento a singolo grado
myservo.write (angle);
delay (incrementDelay);

 if (digitalRead (pinButt3) == 1) for (int angle = 0; angle < 90; angle += angleIncrement) // Posizionamento a 90 gradi con incremento a singolo grado
myservo.write (angle);
 delay (incrementDelay); 

 if (digitalRead (pinButt4) == 1) for (int angle = 0; angle < 120; angle += angleIncrement) // Posizionamento a 120 gradi con incremento a singolo grado
myservo.write (angle);
 delay (incrementDelay); 

 if (digitalRead (pinButt5) == 1) for (int angle = 0; angle < 160; angle += angleIncrement) // Posizionamento a 160 gradi con incremento a singolo grado
myservo.write (angle);
 delay (incrementDelay); 
 
 
}

what at moment happen is the servo reach all positions but I cant control its speed.

If you put ONE statement per line, AND used curly braces, you could.

Right now, your code looks like:

 if (digitalRead (pinButt5) == 1)
 {
    for (int angle = 0; angle < 160; angle += angleIncrement) // Useless comment removed
    {
       myservo.write (angle);
    }
    delay (incrementDelay);
 }

It should be obvious that the delay() needs to be inside the curly braces for the for loop, not after them.

Like this ? (thank you very much - I spent hurs on this ! :confused: )

void loop() {
  
 {if (digitalRead (pinButt1) == 1) for (int angle = 0; angle < 30; angle += angleIncrement) // Posizionamento a 30 gradi con incremento a singolo grado
myservo.write (angle);
delay (incrementDelay);}

{if (digitalRead (pinButt2) == 1) for (int angle = 0; angle < 60; angle += angleIncrement) // Posizionamento a 60 gradi con incremento a singolo grado
myservo.write (angle);
delay (incrementDelay);}

 {if (digitalRead (pinButt3) == 1) for (int angle = 0; angle < 90; angle += angleIncrement) // Posizionamento a 90 gradi con incremento a singolo grado
myservo.write (angle);
 delay (incrementDelay);} 

 {if (digitalRead (pinButt4) == 1) for (int angle = 0; angle < 120; angle += angleIncrement) // Posizionamento a 120 gradi con incremento a singolo grado
myservo.write (angle);
 delay (incrementDelay);} 

 {if (digitalRead (pinButt5) == 1) for (int angle = 0; angle < 160; angle += angleIncrement) // Posizionamento a 160 gradi con incremento a singolo grado
myservo.write (angle);
 delay (incrementDelay);} 
 
 
}

Like this ?

No. That looks NOTHING like the code I posted.

Put EVERY { on a line BY ITSELF.
Put EVERY } on a line BY ITSELF.
Put ONE statement per line. An if statement and a for statement are TWO separate statements, and go on two separate lines.

Use Tools + Auto Format. It will make it MUCH more obvious what you program structure looks like.

Or just use VarSpeedServo instead of the standard Servo library.

Steve

Good evening, first of all thanks so much for your help. I think I have correctly written the sketch but despite the numerous attempts and trials the speed is always the same.

#include <Servo.h>

#define pinServo 9

#define pinButt1 1
#define pinButt2 2
#define pinButt3 3
#define pinButt4 4
#define pinButt5 5

const int angleIncrement = 1;
const int incrementDelay = 50;

Servo myservo;

void setup() {

myservo.attach (pinServo) ;

pinMode (pinButt1, INPUT);
pinMode (pinButt2, INPUT);
pinMode (pinButt3, INPUT);
pinMode (pinButt4, INPUT);
pinMode (pinButt5, INPUT);

}

void loop()  {
  
//If you put ONE statement per line, AND used curly braces, you could.
//It should be obvious that the delay() needs to be inside the curly braces for the for loop, not after them.
//Put EVERY { on a line BY ITSELF.
//Put EVERY } on a line BY ITSELF.
//Put ONE statement per line. An if statement and a for statement are TWO separate statements, and go on two separate lines.
//Use Tools + Auto Format. It will make it MUCH more obvious what you program structure looks like.
  
  
  if (digitalRead (pinButt1) == 1)
 {
    for (int angle = 0; angle < 30; angle += angleIncrement)
    {
       myservo.write (angle);
    }
    delay (incrementDelay);
 }
  
   if (digitalRead (pinButt2) == 1)
 {
    for (int angle = 0; angle < 60; angle += angleIncrement)
    {
       myservo.write (angle);
    }
    delay (incrementDelay);
 }
  
   if (digitalRead (pinButt3) == 1)
 {
    for (int angle = 0; angle < 90; angle += angleIncrement)
    {
       myservo.write (angle);
    }
    delay (incrementDelay);
 }
 
  if (digitalRead (pinButt4) == 1)
 {
    for (int angle = 0; angle < 120; angle += angleIncrement)
    {
       myservo.write (angle);
    }
    delay (incrementDelay);
 }
 
  if (digitalRead (pinButt5) == 1)
 {
    for (int angle = 0; angle < 150; angle += angleIncrement)
    {
       myservo.write (angle);
    }
    delay (incrementDelay);
 }
 
}

You still have the delay outside of the for loop.

Is it that you said ?

if (digitalRead (pinButt1) == 1)
 {
   for (int angle = 0; angle < 20; angle += angleIncrement) 

   myservo.write (angle);
   
   delay (incrementDelay);
   
 }

But it dont work. I tried a lot but the speed of the servomotor don’t change. Only that change is the time of bottons response. I need a slow response of the motor turn.

The delay is STILL outside the for loop.

Look at your {} brace placement

I dont uderdand sorry :confused:

if (digitalRead (pinButt1) == 1)
{
  for (int angle = 0; angle < 20; angle += angleIncrement) 

 delay (incrementDelay);
  
myservo.write (angle);
  
}

If I put in this way it get me an error

if (digitalRead (pinButt1) == 1)
 {
  for (int angle = 0; angle < 20; angle += angleIncrement)
  {
   myservo.write (angle);
   
   delay (incrementDelay);
  }
 }

Note that now, the delay is inside the for loop.

Thank you Awol, now the servo goes slow and reach the angle but before getting the angle it goes fast at the zero angle position; then turn back slowly at the right position. >:( >:( >:( :o

 if (digitalRead (pinButt1) == 1)
  {
    for (int angle = 0; angle < 30; angle += angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }
  }

  if (digitalRead (pinButt2) == 1)
  {
    for (int angle = 0; angle < 60; angle += angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }
  }
  
  if (digitalRead (pinButt3) == 1)
  {
    for (int angle = 0; angle < 90; angle += angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }
  }

if (digitalRead (pinButt4) == 1)
  {
    for (int angle = 0; angle < 120; angle += angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }
  }
  
  if (digitalRead (pinButt5) == 1)
  {
    for (int angle = 0; angle < 150; angle += angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }
  }

}

I'm sorry, I don't know what you mean.

You could add some debug prints to your code, to get it to tell you what it is doing.

You need another for loop between those two to return to 0 slowly:

   for (int angle = 30; angle >= 0; angle -= angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }

Thank you very mutch for you help. I have done two videos.

The first configuration is good for the movement but the servomotor goes too fast

The second configuration as resolved the speed problem but the servomotor does not go directly to the assigned position

The First configuration is the same I posted in the first post

The second configuration is that one we worked on to correct only the speed problem

#include <Servo.h>

#define pinServo 9

#define pinButt1 1
#define pinButt2 2
#define pinButt3 3
#define pinButt4 4
#define pinButt5 5

const int angleIncrement = 1;
const int incrementDelay = 50;

Servo myservo;

void setup() {

  myservo.attach (pinServo) ;

  pinMode (pinButt1, INPUT);
  pinMode (pinButt2, INPUT);
  pinMode (pinButt3, INPUT);
  pinMode (pinButt4, INPUT);
  pinMode (pinButt5, INPUT);

}

void loop()  {

  //If you put ONE statement per line, AND used curly braces, you could.
  //It should be obvious that the delay() needs to be inside the curly braces for the for loop, not after them.
  //Put EVERY { on a line BY ITSELF.
  //Put EVERY } on a line BY ITSELF.
  //Put ONE statement per line. An if statement and a for statement are TWO separate statements, and go on two separate lines.
  //Use Tools + Auto Format. It will make it MUCH more obvious what you program structure looks like.


  if (digitalRead (pinButt1) == 1)
  {
    for (int angle = 0; angle < 30; angle += angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }
  }

  if (digitalRead (pinButt2) == 1)
  {
    for (int angle = 0; angle < 60; angle += angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }
  }
  
  if (digitalRead (pinButt3) == 1)
  {
    for (int angle = 0; angle < 90; angle += angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }
  }

if (digitalRead (pinButt4) == 1)
  {
    for (int angle = 0; angle < 120; angle += angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }
  }
  
  if (digitalRead (pinButt5) == 1)
  {
    for (int angle = 0; angle < 150; angle += angleIncrement)
    {
      myservo.write (angle);

      delay (incrementDelay);
    }
  }

}

As I said earlier it is a lot easier to use VarSpeedServo.h. Instead of the for loops with their start points and delays you just need

myservo.write(AngleYou Want, Speed); // where Speed is a number between 1 (very slow) and 255 (fast)

Steve

oh my Good Steve !!! :slight_smile: :slight_smile: :slight_smile: :slight_smile:

Done ! I imported that library and writed my first working skech as I want to work. Iam Very very happy

#include <VarSpeedServo.h>

#define pinServo 9
#define pinButt1 1
#define pinButt2 2
#define pinButt3 3
#define pinButt4 4
#define pinButt5 5

VarSpeedServo myservo;

void setup() {
  // put your setup code here, to run once:

  myservo.attach (pinServo) ;

  pinMode (pinButt1, INPUT);
  pinMode (pinButt2, INPUT);
  pinMode (pinButt3, INPUT);
  pinMode (pinButt4, INPUT);
  pinMode (pinButt5, INPUT);

}

void loop() {

  //myservo.write(AngleYou Want, Speed);

  if (digitalRead (pinButt1) == 1) myservo.write (30, 10);

  if (digitalRead (pinButt2) == 1) myservo.write (60, 10);

  if (digitalRead (pinButt3) == 1) myservo.write (90, 10);

  if (digitalRead (pinButt4) == 1) myservo.write (120, 10);

  if (digitalRead (pinButt5) == 1) myservo.write (160, 10);


}

Well done for getting it working but a word of caution.

It is not a good idea to use pin 1 as an input because it is used by the Arduino Serial interface. Not a problem with this program but you should steer away from using it unless you know exactly what you are doing.

Some other comments :

How are the inputs wired ? If you don't have pulldown resistors to keep them LOW when the button is not pressed then they will be floating at an uncertain voltage which could cause digitalRead() to return a HIGH value when the button is not actually pressed.

You can avoid the use of external pulldown resistors by using

pinMode(buttonPin, INPUT_PULLUP);

which will activate the Arduino internal pullup resistor which will keep the input normally HIGH. If you do this you need to change your circuit to take the inputs to GND when a button is pressed and change the logic of the program to test for LOW instead of HIGH but that is a small price to pay.

My mention of LOW and HIGH brings me to another point. Whilst you can test for 0/1 as an input state it makes more sense to use the built in LOW/HIGH constants as it makes the code more readable, particularly in parallel with using INPUT_PULLUP

UKHeliBob:
Well done for getting it working but a word of caution.

It is not a good idea to use pin 1 as an input because it is used by the Arduino Serial interface. Not a problem with this program but you should steer away from using it unless you know exactly what you are doing.

Very importanti information I didn't know. I will study better when use it correctly.

UKHeliBob:
How are the inputs wired ?

I put a 1K resistor for each button connected to the ground as you can see in the video. Should be correct I Think......

UKHeliBob:
You can avoid the use of external pulldown resistors by using
which will activate the Arduino internal pullup resistor which will keep the input normally HIGH. If you do this you need to change your circuit to take the inputs to GND when a button is pressed and change the logic of the program to test for LOW instead of HIGH but that is a small price to pay.
My mention of LOW and HIGH brings me to another point. Whilst you can test for 0/1 as an input state it makes more sense to use the built in LOW/HIGH constants as it makes the code more readable, particularly in parallel with using INPUT_PULLUP

I Will study to better understand this subject very thank you for your advice. :slight_smile:

I put a 1K resistor for each button connected to the ground as you can see in the video. Should be correct I Think......

That's fine.

Give it a try with INPUT_PULLUP and simplify the circuit by removing the need for external resistors. It is a very useful technique especially when testing on a breadboard as it requires less wiring