Servos and timing (delay()).

Hi, I've got a 'hobby' servo that I'm trying to control with the ServoTimeTimer1 library (very similar to the Servo library) but it doesn't seem to work well with the delay() function. Here's the code:

#include <inttypes.h>
#include <avr/io.h>
#include "WProgram.h" 

#include <ServoTimeTimer1.h>

#define servoPin1 9

ServoTimeTimer1 servo1;

 int ledPin = 13;                // LED connected to digital pin 13

void setup()
{
  servo1.attach(servoPin1);
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  digitalWrite(ledPin, HIGH);   // sets the LED on
    servo1.write(1600);
    delay(3000);
  digitalWrite(ledPin, LOW);    // sets the LED off
    servo1.write(1500);
    delay(3000);
}

What happens is that it often moves to the second position and then goes straight back. I guess it's because the servo library uses the same timer as the delay function. Anyone know of a way around this?

Two other small questions:

  1. Should the servo vibrate when it is use? Even when it isn't moving? Seems like bad feedback circuitry if it should...
  2. Where can I find a reference to all the registers and stuff needed to write things like the Servo library? Is it GCC stuff or is this info provided by Atmel somewhere?

Thanks.

Actually I tried it without the servo attached and it worked. I think the problem was that I was using the regulated 5V on the arduino to drive the servo. I guess the regulator can't supply that much current and the voltage dropped too low for the arduino.

Is there any way to bypass the regulator? E.g. if I'm running off an already regulated 5V supply (or 5V of batteries)?

I have had similar problems with a servo not working because it took more power than the board could provide.

You can wire the servo so the power lead (generally a red wire in the middle of the three wires going to the servo) is connected to an external 5v power supply (or battery). You must also connect the Arduino ground to the ground of this external supply.

Yeah but how do you connect the arduino itself to the 5V supply (assuming it is already regulated)? I don't want to have to use two power supplies...

Hmm perhaps the easiest way is to make a USB<->power connector. I think USB provides regulated 5V so that must bypass arduino's regulator...

There is a pin marked 5v on the Arduino, you can provide 5 volts to that pin to power the board.

OK I'm getting really confused! I connected a regulated 5V power supply that says it can supply 2.5A to the 5V socket on the arduino. So now the 2.5A power supply directly powers the servo and the arduino, but it still doesn't work! If I disconnect either the PWM servo controller wire, or its power wires then the code works (i.e. the LED flashes on and off every three seconds).

Any idea what is going on? Basic servos don't use more than 2.5A do they?

Also, if I try using USB to power the arduino and a power adapter to power the servo will that cause issues with the different grounds, or is the control lead of servos isolated from the power leads?

I tried your code but I could not compile it (I'm using Arduino 0011 Alpha) without some changes. I had to remove all #includes except the one that includes the ServoTimer1 library.

You call it "ServoTimeTimer1" - is this a different library or a typo? Also, I see you set the servo angle to 1500 and 1600. With ServoTimer1 (atleast the one I'm using) angle is between 0 and 359 (I think - I don't have any 360 degrees servos!) so I had to change this to a more reasonable value to get stuff working.

This code compiles and runs properly on my Freeduino:

#include <ServoTimer1.h>

#define servoPin1 9

ServoTimer1 servo1;

 int ledPin = 13;                // LED connected to digital pin 13

void setup()
{
  servo1.attach(servoPin1);
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  digitalWrite(ledPin, HIGH);   // sets the LED on
    servo1.write(25);
    delay(3000);
  digitalWrite(ledPin, LOW);    // sets the LED off
    servo1.write(165);
    delay(3000);
}

I forgot to say that I also power the Arduino (Freeduino) with an external regulated PSU (actually an ATX PSU) connected to the 5V-pin. I actually power the Arduino with VSB and the servo (and some other stuff) with VCC.

This gets weirder and weirder... I tried your code (but with Servo.h instead - using arduino 0012) and it worked! Why do you do stuff with pin 2 btw?

And this code also works:

void loop() 
{ 
  for(pos = 40; pos < 140; pos += 20)  // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    for (int i = 0; i < 1000; ++i)
      delay(1);                       // This works by delay(1000) doesn't. Must b
  } 
}

But if I replace the inner loop with delay(1000); it goes all random again. Very odd.

If I replace the loop in your working code with this then it also doesn't work:

  for (int i = 25; i <= 165; i += 21)
   {
    digitalWrite(ledPin, (i % 2) ? HIGH : LOW);
    servo1.write(i);
    delay(3000);
   }

This gets weirder and weirder... I tried your code (but with Servo.h instead - using arduino 0012) and it worked!

Perhaps the servo library you're using doesn't work with 0012? Servo.h is included with 0012, so why are you using ServoTimeTimer1?

Why do you do stuff with pin 2 btw?

I thought I edited that out :slight_smile: I'm using pin 2 to switch on the ATW PSU. I power the servo by Vcc, so I have to switch the PSU on first.

If I replace the loop in your working code with this then it also doesn't work

In what way doesn't it work? It works fine here.

It seems to randomly cut some of the timing short... It doesn't seem to be deterministic. You probably get a similar effect by replacing the

delay(3000)'s with

delay(rand() % 8 ? 3000 : 200); // Assuming rand() works like libc's.

I'm going to try manually making the PWM signal to see if that works. I'll hook it up to a scope too to see if that provides any more insight.

Oh and I've switched to using the Servo library that comes with the arduino IDE. Doesn't seem to have changed anything though.

Try 0011 and check if the problem persists. If it goes away, there is probably a bug in the new Servo-lib or in delay() in 0012.

Aha! It works with version 0011! :slight_smile: Is there a bug tracker somewhere?