Pages: [1] 2   Go Down
Author Topic: Slowing down servos. How to write it into the program.  (Read 1563 times)
0 Members and 1 Guest are viewing this topic.
Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi everyone,
                   I am very new to all of this and have been tinkering extensively for several days working on a program to change the position of a servo between 0, 45 and 90 degrees by using a digital input. No input = 0 degrees, a HIGH input on digital pin 3 moves the servo to 45 degress and a HIGH input on digital pin 4 moves the servo to 90 degrees. What I am now having trouble programming is how to slow the movement of the servo down. What I am trying to emulate is a old style of railway signal used in NSW Australia for many years known as an upper quadrant signal. See photo  http://www.flickr.com/photos/robertstrains/5767145547/ . They are driven off a motor that moves realatively slowly i nreal life and that is what I am trying to emulate. I have been using the sweep sketch in the examples as a reference but have come up trumps after reading all the posts forums and books I have acess to and searching you tube. There is obviously something I am missing. If you need to see the sketch I am happy to post it. But the notes are incomplete at this stage.

Thanks in advance,
Briggsy
« Last Edit: January 30, 2013, 06:23:02 am by briggsy » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26637
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Write small angular increments to the Servo, with a delay between the writes.
Bonus marks for not using "delay()".

If you post your code, we can help you with it.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is the sketch.
Code:
//Upper Quadrant servo sketch 1
#include <Servo.h>
 
Servo myservo;  // create servo object to control a servo
               
int yellowState;
int greenState;
   
// constants won't change. They're used here to
// set pin numbers:

const int yellowPin = 3;
const int greenPin = 4;

void setup()
{
 
 // initialize the trigger pins as an input:
   
pinMode(yellowPin, INPUT);
pinMode(greenPin, INPUT);
myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}
 
void loop(){
 // read the state of the trigger value:
yellowState = digitalRead(yellowPin);
greenState = digitalRead(greenPin);

  // check if either of the triggers are HIGH
  // if it is, the relavant State is HIGH:
                     
if (yellowState == HIGH) 
                                   
    myservo.write(45);     //sends servo to 45 degrees         
   
if (greenState == HIGH)

   myservo.write(90);      //sends servo to 90 degrees
   
if ((yellowState == LOW) && (greenState == LOW))
   myservo.write(0);



Thanks for taking the time to have a look. I worked out how to play with the delay in the sweep example but I could never get it to work in my sketch.

Briggsy
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26637
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As written, your servo will move as quickly as it can from one position to the next.
If, instead of a simple "servo.write (90);" you did something like (and I'm going to lose marks for this)
Code:
for (int angle = 0; angle < 90; angle+=10) {
  servo.write (angle);
  delay (50);
, your sweep will take longer.

Play with it, change the values, particularly the start, end and increment values (you don't want to go back to zero if you're already at 45 and moving to 90)
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

AWOL,
         Thanks for the help but that has not appeared to have worked. I have tinkered gto the best of my knowledge. I there a way to just slow down the PWM change to the servo so that all of it's movements are slowed to the same rate? It just waved the servo about like a crazy thing.

Briggsy
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 654
Posts: 50945
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
It just waved the servo about like a crazy thing.
Time to put up or shut up. Where IS your code?
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

that has not appeared to have worked. I have tinkered gto the best of my knowledge.

Post your new code.

I there a way to just slow down the PWM change to the servo so that all of it's movements are slowed to the same rate? It just waved the servo about like a crazy thing.


Yes there is. It'd need some changes to your code, though. The approach I'd take is to add a variable holding the current position of the servo, and a variable that holds the target position. At the point in your code where you currently move the servo, just update the target position instead.

Add some code that runs at regular intervals - every 10 ms would be a reasonable starting point. Look at the 'blink without delay' example sketch to see how to do things at regular intervals. Every interval, compare the current and target position of the servo. If they're different then move the servo one unit towards the target position. You will need to experiment with the interval to get the speed of movement that you require.

This technique could be extended easily to support multiple servos - just convert the variables involved to arrays and add code to apply the logic above to each element in the array.

If you were looking to make a very modular and reusable solution, you might go one step further and create a class that contains this logic (i.e. a speed-limited servo).
« Last Edit: January 30, 2013, 08:23:37 am by PeterH » Logged

I only provide help via the forum - please do not contact me for private consultancy.

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26637
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is a variable speed servo library somewhere.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

My apologies. My aim is not to upset or annoy. I tinkered some more and got it to stop waving about by removing the time interval bit off the 90 degree part of the sketch. But it still moves quickly to 45 degrees with it in on that part. Here is how it currently stands.
Code:
//Upper Quadrant servo sketch 1
#include <Servo.h>
 
Servo myservo;  // create servo object to control a servo
               
int yellowState;
int greenState;
int angle = 0;   
// constants won't change. They're used here to
// set pin numbers:

const int yellowPin = 3;
const int greenPin = 4;

void setup()
{
 
 // initialize the trigger pins as an input:
   
pinMode(yellowPin, INPUT);
pinMode(greenPin, INPUT);
myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}
 
void loop(){
 // read the state of the trigger value:
yellowState = digitalRead(yellowPin);
greenState = digitalRead(greenPin);

  // check if either of the triggers are HIGH
  // if it is, the relavant State is HIGH:
                     
if (yellowState == HIGH) 
                                   
    for (int angle = 1; angle < 45; angle += 1)
  myservo.write (angle);
  delay (100);
       //sends servo to 45 degrees         
   
if (greenState == HIGH)

 
  myservo.write (90);
 
        //sends servo to 90 degrees
   
if ((yellowState == LOW) && (greenState == LOW))
   
  myservo.write (0);
 



AWOL that sounds promising.

Thanks again for all the help,
Briggsy
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26637
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
if (yellowState == HIGH)  
                                  
    for (int angle = 1; angle < 45; angle += 1)
  myservo.write (angle);
  delay (100);
When I wrote the example in reply #3, I very carefully put in a set of  { } braces.
They're important, and they're missing from your code.
« Last Edit: January 30, 2013, 08:30:02 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

AWOL,
          My apologies. I must have left them out after my tinkering. I'll have another go after I put them back in. My mistake.

Thanks again,
Briggsy
Logged

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

AWOL,
          They are back in and it has slowed the servo down on the movement from 0 to 45 degrees but it now immediately returns to to zero degrees at full speed once it has reached 45 degrees. I'll include the updated code again.

Code:
//Upper Quadrant servo sketch 1
#include <Servo.h>
 
Servo myservo;  // create servo object to control a servo
               
int yellowState;
int greenState;
int angle = 0;   
// constants won't change. They're used here to
// set pin numbers:

const int yellowPin = 3;
const int greenPin = 4;

void setup()
{
 
 // initialize the trigger pins as an input:
   
pinMode(yellowPin, INPUT);
pinMode(greenPin, INPUT);
myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}
 
void loop(){
 // read the state of the trigger value:
yellowState = digitalRead(yellowPin);
greenState = digitalRead(greenPin);

  // check if either of the triggers are HIGH
  // if it is, the relavant State is HIGH:
                     
if (yellowState == HIGH) 
                                   
    for (int angle = 1; angle < 45; angle += 1){
  myservo.write (angle);
  delay (100);
    }
       //sends servo to 45 degrees         
   
if (greenState == HIGH)

 
  myservo.write (90);
 
        //sends servo to 90 degrees
   
if ((yellowState == LOW) && (greenState == LOW))
   
  myservo.write (0);
 



Thanks,
Briggsy
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26637
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but it now immediately returns to to zero degrees at full speed once it has reached 45 degrees
Presumably because after four-and-a-half seconds, you've let go of the buttons, and they're both low again?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 654
Posts: 50945
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It would really help you understand what your code is doing if you put every { on a new line, and used Tools + Auto Format.

Code that jerks
                all over the
    page is very
hard                     to read.
Logged

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Yes there is. It'd need some changes to your code, though. The approach I'd take is to add a variable holding the current position of the servo, and a variable that holds the target position. At the point in your code where you currently move the servo, just update the target position instead.

Add some code that runs at regular intervals - every 10 ms would be a reasonable starting point. Look at the 'blink without delay' example sketch to see how to do things at regular intervals. Every interval, compare the current and target position of the servo. If they're different then move the servo one unit towards the target position. You will need to experiment with the interval to get the speed of movement that you require.

This technique could be extended easily to support multiple servos - just convert the variables involved to arrays and add code to apply the logic above to each element in the array.

If you were looking to make a very modular and reusable solution, you might go one step further and create a class that contains this logic (i.e. a speed-limited servo).

PeterH,
           Thanks for that info. I'll do some more reading and have a go at it fresh next time. It's late and I've annoyed you gentleman enough for now. Sorry for it being everywhere. I'm still learning how to clean it up without stuffing it up.

Thanks again,
Briggsy
Logged

Pages: [1] 2   Go Up
Jump to: