Help with servo speed

Hi, I´m new to the whole Arduino-programming-thing…so I´ve got many questions, but this in particular!

My project is based on a IR-beam that tells a servo to move (open a barrier) when the beam breaks and some LED:s turns ON end OFF. So far so good!

The thing is that I want the servo to move slow from 0 degrees to 90 degrees and than back to 0 degrees when it is time to.
I´ve tried with all kind of delays and stuff, but don’t get it to work.
How do I get the servo to move slower!?

This is what the code looks like now

const int IRD = 10;                  // IR-detector connected to pin 10
const int led_go = 13;               // Green led to pin 13
const int led_stop = 12;             // Red led to pin 12

#include <Servo.h> 
 
Servo servo;  

void setup() 
{ 
  servo.attach(11);                    //Servo connected to pin 11
  pinMode(IRD, INPUT);                 //IR-led
  pinMode(led_go, OUTPUT);            //Green led
  pinMode(led_stop, OUTPUT);          //Red led
}
 
void loop() 
{ 
    boolean detected = digitalRead(IRD);

    if(detected){                            // When IR-Beam breakes,
           servo.write(90);                  // Servo turns 90 degrees and opens the barrier
           delay(500);                       // with a delay of half a second.
     digitalWrite(led_stop, LOW);            // The red "stoplight" turns off
     digitalWrite(led_go, HIGH);             // and the green light turns on
  }

else                                         //Otherwise,
{
  digitalWrite(led_stop, HIGH);              //the stoplight is turned on
  delay(2000);                               
  digitalWrite(led_go, LOW);                 // and the greenlight turns off
  servo.write(0);                            // aswell as the barrier goes down.
}
}

Your approach will cause the 90 degree move to happen at the servo's natural speed, one one go, followed by the delay.

You couild try do the move in steps of say 1 degree in a loop, with a short delay in between. Look at the sweep example

JimboZA:
Your approach will cause the 90 degree move to happen at the servo's natural speed, one one go, followed by the delay.

You couild try do the move in steps of say 1 degree in a loop, with a short delay in between. Look at the sweep example

Thanks for the post!

Yes, I´ve tried that one but the thing is that when the servo reaches 90 degrees it moves fast back to 0 degrees even though the IR-beam is broken... I want it to move slow to 90 and than stay there as long as the beam is broken.

kriha10:
Yes, I´ve tried that one but the thing is that when the servo reaches 90 degrees it moves fast back to 0 degrees even though the IR-beam is broken… I want it to move slow to 90 and than stay there as long as the beam is broken.

Post the sketch that is doing what you describe.

…R

Robin2:

kriha10:
Yes, I´ve tried that one but the thing is that when the servo reaches 90 degrees it moves fast back to 0 degrees even though the IR-beam is broken… I want it to move slow to 90 and than stay there as long as the beam is broken.

Post the sketch that is doing what you describe.

…R

Like this

const int IRD = 10;                  // IR-detector connected to pin 10
const int led_go = 13;               // Green led to pin 13
const int led_stop = 12;             // Red led to pin 12

#include <Servo.h> 
int pos = 0;

Servo servo;  

void setup() 
{ 
  servo.attach(11);                    //Servo connected to pin 11
  pinMode(IRD, INPUT);
  pinMode(led_go, OUTPUT);
  pinMode(led_stop, OUTPUT);
}
 
void loop() 
{ 
    boolean detected = digitalRead(IRD);

    if(detected){                            // When IR-Beam breakes,
   { 
  for(pos = 0; pos < 90; pos += 1)  // goes from 0 degrees to 90 degrees 
  {                                  // in steps of 1 degree 
   servo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15);                       // waits 15ms for the servo to reach the position 
     digitalWrite(led_stop, LOW);            // The red "stoplight" turns off
     digitalWrite(led_go, HIGH);             // and the green light turns on
  }
   }
    }
else                                         //Otherwise,
{
  digitalWrite(led_stop, HIGH);              //the stoplight is turned on
  delay(2000);                               
  digitalWrite(led_go, LOW);                 // and the greenlight turns off
  for(pos = 90; pos>=1; pos-=1);
  servo.write(pos);                            // aswell as the boom goes down.
  delay(15);
}
}

this may work

void loop() 
{ 
    if(digitalRead(IRD)==HIGH){                            // When IR-Beam breakes,
           servo.write(90);                  // Servo turns 90 degrees and opens the barrier
           delay(500);                       // with a delay of half a second.
     digitalWrite(led_stop, LOW);            // The red "stoplight" turns off
     digitalWrite(led_go, HIGH);             // and the green light turns on
  }

if that dosent work try a while loop

as far as the speed issue goes the idea of delaying in 30 degree incriment sounds promiseing.

keys-t:
this may work

Thanks for the effort, but it didn’t work. Will try the “while loop” later on

The first rule of debugging is "the code never makes mistakes" - it always does what it is supposed to do. If it is not behaving as you think it should you need to look for the "error" that is making it do the wrong thing.

Your code in Reply #4 has a simple error. Every time it runs through loop it starts the whole if (detected) part again and that always starts the servo at 0.

You need a variable (known as a state variable) which records the fact that the servo is already at 90 degrees and you should skip the servo move code if it is.

...R

a servo is controlled only by its position, in real it is a timesignal, but that is handled by the lib.
so when opening, you tell the servo to open only for 1 degree, wait a little then set it to 2 degrees etc.
if signal is open then open 1 degree until full open
if signal is not open(close) then close 1 degree until closed
wait a little (delay)
if this is working
get rid of the delay and use millis()

The below library might be of interest. Bottom is some code that also might be useable as it should sweep left or right depending on a condition, in this case “button” pushes.

http://forum.arduino.cc/index.php/topic,61586.30.html

//zoomkat servo button sweep test 12-23-2013
// Powering a servo from the arduino usually *DOES NOT WORK*.

#include <Servo.h>
int button1 = 6; //button pin, connect to ground to move servo
int press1 = 0;
int button2 = 5; //button pin, connect to ground to move servo
int press2 = 0;
Servo servo1;
int pos = 90; // variable to store and set the servo position 

void setup()
{
  Serial.begin(9600);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  servo1.attach(7);
  servo1.write(pos); //starting position
  digitalWrite(6, HIGH); //enable pullups to make pin high
  digitalWrite(5, HIGH); //enable pullups to make pin high
  Serial.println("servo button sweep test 12-23-2013");
}

void loop()
{
  press1 = digitalRead(button1);
  if (press1 == LOW)
  {
    pos=(pos+1);
    if(pos>180) pos=180; //limit upper value
    Serial.println(pos); //for serial monitor debug
    servo1.write(pos); // tell servo to go to position in variable 'pos' 
    delay(150); // waits 150ms to slow servo movement 
  }    

  press2 = digitalRead(button2);
  if (press2 == LOW)
  {
    pos=(pos-1);
    if(pos<0) pos=0; //limit lower value
    Serial.println(pos); //for serial monitor debug
    servo1.write(pos); // tell servo to go to position in variable 'pos' 
    delay(150); // waits 150ms to slow servo movement
  }
}

Nope, I can't get it to work as I want to =(

It´s something like this I´m trying to do Arduino Controlled Car Barrier Toy - YouTube
but only activated when breaking the IR-beam.

if(detected){                            // When IR-Beam breakes,
servoopen()
           servo.write(90);                  // Servo turns 90 degrees and opens the barrier so here it flips open within 0.2 seconds.
           delay(500);                       // with a delay of half a second.
     digitalWrite(led_stop, LOW);            // The red "stoplight" turns off
     digitalWrite(led_go, HIGH);             // and the green light turns on
  }

else                                         //Otherwise,
{
  digitalWrite(led_stop, HIGH);              //the stoplight is turned on
  delay(2000);                               
  digitalWrite(led_go, LOW);                 // and the greenlight turns off
  servo.write(0);  

void servoopen()
{for (int i=0,90,i++){
servo.write(i);
delay(100); // the gate will open in 9 seconds
}
}
void servoclose()
{for (int i=90,0,i--){
servo.write(i);
delay(100);
}
}

now for you the challenge:
if object under boom, change direction to open, without jumping hihi
please give us result.
and yes there is a lib for this, but better to find it yourself.

kriha10:
Nope, I can't get it to work as I want to

Have you read Reply #7 ?

...R

Robin2:
Have you read Reply #7 ?

…R

Yes I have. I understand what you mean but I don’t have the knowledge to do something about it…but I´m trying to learn.

I´ve tried this one though… a “do while”-thing but in this state the servo stays in 90 degrees and doesn’t go back to 0 degrees.

const int IRD = 10;                  // IR-detector connected to pin 10
const int led_go = 13;               // Green led to pin 13
const int led_stop = 12;             // Red led to pin 12
const int buttonPin = 2; 

#include <Servo.h> 
int pos = 0;

Servo servo;  

void setup() 
{ 
  servo.attach(11);                    //Servo connected to pin 11
  pinMode(IRD, INPUT);
  pinMode(led_go, OUTPUT);
  pinMode(led_stop, OUTPUT);
}
 
void loop() 
{ 
    boolean detected = digitalRead(IRD);

    if(detected){                            // When IR-Beam breakes,
   { 
  for(pos = 0; pos < 90; pos += 1)  // goes from 0 degrees to 90 degrees 
  {                                  // in steps of 1 degree 
    servo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(25);                       // waits 15ms for the servo to reach the position 
     digitalWrite(led_stop, LOW);            // The red "stoplight" turns off
     digitalWrite(led_go, HIGH);             // and the green light turns on
  }
  do
  {
    servo.write(90);
  }while(detected == 1);
   }
    }
else                                   //Otherwise,
{
  digitalWrite(led_stop, HIGH);              //the stoplight is turned on
  delay(2000);                               
  digitalWrite(led_go, LOW);                 // and the greenlight turns off
  for(pos = 90; pos>=1; pos-=1);
  servo.write(pos);                            // aswell as the boom goes down.
  delay(15);
}
}

I´m very thankful for your help, as I wrote earlier…I´m a total noob at this!

I have tried to tidy up the layout of your code. Laying it out carefully with proper indenting makes it much easier to see how the logic works - it’s not just for artistic effect.

I have simplified the code in the if (detected) part and I think this will do what you want.
I assume you only want the lights to change when the servo gets to 90 deg.
I don’t know what is supposed to happen is not detected (! detected) so I haven’t changed that.

Let me know if you don’t understand the changes I have made - or if I have made a mistake (which I do all the time).

I haven’t changed your use of the delay() function but you may find it gets in the way of detecting switches and you would probably be better replacing them with the technique in the Blink Without Delay example sketch.

const int IRD = 10;                  // IR-detector connected to pin 10
const int led_go = 13;               // Green led to pin 13
const int led_stop = 12;             // Red led to pin 12
const int buttonPin = 2; 

#include <Servo.h> 
int pos = 0;

Servo servo;  

void setup() 
{ 
  servo.attach(11);                    //Servo connected to pin 11
  pinMode(IRD, INPUT);
  pinMode(led_go, OUTPUT);
  pinMode(led_stop, OUTPUT);
}
 
void loop() 
{ 
  boolean detected = digitalRead(IRD);

  if(detected) {                            // When IR-Beam breakes,
     
       pos = pos + 1;        // in steps of 1 degree 
       if (pos > 90) {
            pos = 90;
       }
       servo.write(pos);     // tell servo to go to position in variable 'pos' 
       delay(25);            // waits for the servo to reach the position 
       
  }

  if (pos >= 90)
  {
       digitalWrite(led_stop, LOW);            // The red "stoplight" turns off
       digitalWrite(led_go, HIGH);             // and the green light turns on
  }
    
  if (! detected)                                    
  {
        digitalWrite(led_stop, HIGH);              //the stoplight is turned on
        delay(2000);                               
        digitalWrite(led_go, LOW);                 // and the greenlight turns off
        for(pos = 90; pos>=1; pos-=1);
        servo.write(pos);                            // aswell as the boom goes down.
        delay(15);
  }
}

…R

Robin2:
I have simplified the code in the if (detected) part and I think this will do what you want.
I assume you only want the lights to change when the servo gets to 90 deg.

...R

Thanks very much! Yes, this is what I meant to do!

Robin2:
I don't know what is supposed to happen is not detected (! detected) so I haven't changed that.

...R

I want the servo to move back in the same speed from 90 to 0 (the barrier goes down) as it goes from 0 to 90 (the barrier goes up). But I don't know if the (! detected) is the right/easiest way?

I´ve tried using the code;

pos = pos + 1;
       if (pos > 90) {
            pos = 90;

and changed the degrees to 0, but as You probably already knew...that didn't work....

I don't mean to let other people do the job, but this one just is out of my knowledge...so I´m truly thankful for your help!!

To make the servo go the other way you just need to repeat the code but change from addition to subtraction.

I have taken the liberty of making a couple of other changes.
The code to move the servo doesn't need to be within the IF DETECT statements - the same servo code applies whichever way the servo is moving.

I have added a variable (called redOn) to record the required state of the traffic light. It makes the lighting code easier because it is a simple true/false test rather than checking whether pos is 90 or 0.

const int IRD = 10;                  // IR-detector connected to pin 10
const int led_go = 13;               // Green led to pin 13
const int led_stop = 12;             // Red led to pin 12
const int buttonPin = 2; 

#include <Servo.h> 
int pos = 0;
boolean redOn = true;

Servo servo;  

void setup() 
{ 
  servo.attach(11);                    //Servo connected to pin 11
  pinMode(IRD, INPUT);
  pinMode(led_go, OUTPUT);
  pinMode(led_stop, OUTPUT);
}
 
void loop() 
{ 
  boolean detected = digitalRead(IRD);

  if(detected)          // When IR-Beam breakes,
  {
       pos = pos + 1;        // in steps of 1 degree 
       if (pos > 90) {
         pos = 90;
         redOn = false;
       }
  }
  else  
  {
       pos = pos - 1;        // in steps of 1 degree 
       if (pos <= 0) {
         pos = 0;
         redOn = true;
       }      
  }

  if (redOn)  
  {
       digitalWrite(led_stop, HIGH);            // The red "stoplight" turns on
       digitalWrite(led_go, LOW);             // and the green light turns off
  }
  else
  {
       digitalWrite(led_stop, LOW);            // The red "stoplight" turns off
       digitalWrite(led_go, HIGH);             // and the green light turns on
  }

  servo.write(pos);     // tell servo to go to position in variable 'pos' 
  delay(25);            // waits for the servo to reach the position 

}

...R

Robin2:
To make the servo go the other way you just need to repeat the code but change from addition to subtraction.

I have taken the liberty of making a couple of other changes.
The code to move the servo doesn't need to be within the IF DETECT statements - the same servo code applies whichever way the servo is moving.

I have added a variable (called redOn) to record the required state of the traffic light. It makes the lighting code easier because it is a simple true/false test rather than checking whether pos is 90 or 0.

...R

Thanks a lot!! That´s perfect, appreciated!

Sorry to bother again!! :roll_eyes:

It all works fine, but now I´m trying to expand the sketch into two barriers. One for incoming and one for outgoing.
The setup is the same, only that I´ve added one more equal setup and named all the IR, LED:s and things "number 2". Then I tried to duplicate the actions and just name it "2", instead of "IRD" the new one called "IRD2" and so on... But it just goes bananas!

The code I´m trying to expand is the one that Robin2 explains.

Grateful for all the help I can get!

You need to post your revised code if you need help with it.

"Goes bananas" is not a recognized diagnostic term.

...R