Servo Rotation Speed

I am thinking of building a servo pan/tilt head and have a question about servo speed. This will be my first Arduino project.

I want to use Servo.write.Microseconds() to be able to move the servo in finer increments than the 1-degree increments of Servo.write() and thus achieve smoother movement.

If my (pseudo)code is as follows:

for i = 0 to 1500
Servo.write.Microseconds(i)
Delay(1900)
next

This will turn the servo through 90 degrees in approximately 5.1 seconds.

Do I have this correct?

Thank you.

Hello there!

Im assuming that the 1900 in the delay is milliseconds, which would translate to 1.9 seconds. This 1.9 milliseconds * the 1501 iterations of the delay would be about 47.5 minutes.

Good catch.

Let's try:

for i = 0 to 1500
Servo.write.Microseconds(i)
DelayMicroseconds(1900)
next

That's much better.

Going from milliseconds to microseconds is dividing by 1000. So the new total time would be about 2.85 seconds.

Here is what I get, but I could be doing it wrong:

0.0015 = 1500 / 1000000 (convert to seconds)

2.25 seconds = 1500 * 0.0015 — total travel time

1900 = delay() statement in microseconds

2.85 = 1900 * 1500 / 1000000 — cumulative delay in seconds

5.1 seconds = 2.25 s travel + 2.85 s = total travel time + total delay time

= 5.1 seconds from full CCW to midpoint

Does that look like a valid result?

Thank you.

That looks fine. Do you know for certain that each travel takes 1.5 milliseconds?

Servo pulses are updated roughly every 20ms. It makes no sense to update faster than this.

And most servos work in a range of something like 800 to 2200 microseconds. If you try writing 0 then the servo library will change it for you to its minimum pulse length. A 90 degree movement is likely to be something like 800 to 1500.

Steve

bos1714:
That looks fine. Do you know for certain that each travel takes 1.5 milliseconds?

No.

I’m a little confused here.

The function name of Servo.write.Microseconds() implies time, but apparently it sets the position, with 1500 being mid-range, correct? I have set up the “for” loop to increment the argument with each iteration.

How long should I assume it takes for the servo to travel from i to i + 1? I can then adjust the delay accordingly.

The idea is to get the servo to make a smooth 90-degree turn in approximately 5 seconds.

The function name of Servo.write.Microseconds() implies time,

Yes, it sets the pulse width of the Servo library's PWM control pulse.

How long should I assume it takes for the servo to travel from i to i + 1?

You may get a rough idea from the servo's specified slew rate, but the simplest way is good ol' trial-and-error.

If you want slow controlled movement of a servo have you tried the VarSpeedServo library https://github.com/netlabtoolkit/VarSpeedServo instead of the basic Servo library. That has a speed parameter to the write(angle) command which effectively manages the incrementing loop for you and may make life somewhat simpler.

But in either case the actual time taken for the servo to move one increment will depend on the particular servo. Servos exist with a vast range of different slew rates.

Steve

I'll look at that library, thank you.

To complicate things, I'm thinking of setting the speed according to the deflection of a joystick. This will provide inertia to the acceleration and deceleration of the servo shaft, at least I hope it will. The idea is to emulate an expensive camera fluid head or a crank-operated geared head.

Does this code look like it will work? I might have to fuss around with the speed.

/*
Servo.write.Microseconds(i)
DelayMicroseconds(1900)

Analog range = 0 - 1023

Description
Writes a value in microseconds (uS) to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft. On standard servos a parameter value of 1000 is fully counter-clockwise, 2000 is fully clockwise, and 1500 is in the middle.*/

//In this implementation, 0 is full CCW, 1000 is full CW and 500 is center. 1000 is added to all calls to Servo.write.Microseconds.

#include <Servo.h>

Servo panServo;
Servo tiltServo;

int joystickPanPin = A0;
int joystickTiltPin = A1;
int joystickpanSpeed = 0;
int joysticktiltSpeed = 0;
int servoPanPin = 9;
int servoTiltPin = 10;
int panPosition;
int tiltPosition;

void setup()
{
pinMode(servoPanPin, OUTPUT);
pinMode(servoTiltPin, OUTPUT);
panServo.attach(servoPanPin);
tiltServo.attach(servoTiltPin);

//0 = Full CCW; 500 = Center; 1000 = Full CW

panPosition = 500;
Servo.write.Microseconds(panPosition + 1000)

tiltPosition = 500;
Servo.write.Microseconds(tiltPosition + 1000)
}

while (1) //loop
{
// joystick at 512 when in home position

joystickpanSpeed = (analogRead(joystickPanPin);
joysticktiltSpeed = (analogRead(joystickTiltPin);

if (joystickPanSpeed > 512) // user has pushed joystick to the right
{PanPosition += 1; // will move servo clockwise
joystickPanSpeed = 1023 - joystickPanSpeed;
}

else if (joystickPanSpeed < 512) // user has pushed joystick to the left
{panPosition -= 1;} // move servo counterclockwise
//No change to speed

if (joystickPanSpeed != 512 //&& panPosition > 0 && panPosition < 1000)
{
Servo.write.Microseconds(PanPosition + 1000)
delayMicroseconds(panSpeed);
}

// TILT
if (joystickTiltSpeed > 512) // user has pushed joystick up
{TiltPosition += 1; // will move servo clockwise
joystickTiltSpeed = 1023 - joystickTiltSpeed;
}

else if (joystickTiltSpeed < 512) // user has pushed joystick down
{TiltPosition -= 1;} // move servo counterclockwise
//No change to speed

if (joystickTiltSpeed != 512 //&& TiltPosition > 0 && TiltPosition < 1000)
{
Servo.write.Microseconds(TiltPosition + 1000)
delayMicroseconds(TiltSpeed);
}
}

// do nothing if joystick at home

c319chris: Does this code look like it will work?

As you have by now found out, that code doesn't compile, so no, it won't work.

I'm not that far along and don't even have any Arduino hardware as yet. I was just wondering if the logic of my pseudocode looks sound.

I see there is an Arduino simulator here:

https://www.sites.google.com/site/unoardusim/in-the-news/unoardusimv22released

You don't need Arduino hardware to do test compilations. Just download the IDE and use the Verify function. You'll have to get used to the IDE sometime so might as well start now.

But note that just because something compiles it doesn't mean that it will do anything, let alone do what you actually want it to do.

Steve

Now that I've installed the IDE, do I still need the "Arduino Create Agent"? Or the simulator?

slipstick: just because something compiles it doesn't mean that it will do anything, let alone do what you actually want it to do.

Steve

That's why I wanted someone to check the logic of the pseudocode before compiling.

Here is what I’ve come up with so far:

/*
Servo.write.Microseconds(i)
DelayMicroseconds(1900)

Analog range = 0 - 1023

Description
Writes a value in microseconds (uS) to the servo,
controlling the shaft accordingly. On a standard servo,
this will set the angle of the shaft.
On standard servos a parameter value of 1000 is fully counter-clockwise, 2000 is fully clockwise, and 1500 is in the middle.*/

/*In this implementation, 0 is full CCW, 1000 is full CW and 500 is center. 1000 is added to all calls to Servo.write.Microseconds.*/

#include <Servo.h>

int main (void)
{
Servo panServo;
Servo tiltServo;

int joystickPanPin = A0;
int joystickTiltPin = A1;
int joystickPanSpeed = 0;
int joystickTiltSpeed = 0;
int servoPanPin = 9;
int servoTiltPin = 10;
int panPosition;
int tiltPosition;

	pinMode(servoPanPin, OUTPUT);
	pinMode(servoTiltPin, OUTPUT);
	panServo.attach(servoPanPin);
	tiltServo.attach(servoTiltPin);
	
	//0 = Full CCW; 500 = Center; 1000 = Full CW
	
	panPosition = 500;
	panServo.writeMicroseconds(panPosition + 1000);
	
	tiltPosition = 500;
	tiltServo.writeMicroseconds(tiltPosition + 1000);

while (1)
{
	// joystick at 512 when in home position
	
	joystickPanSpeed = analogRead(joystickPanPin);
	joystickTiltSpeed = analogRead(joystickTiltPin);
	
	if (joystickPanSpeed > 512) // user has pushed joystick to the right
	{	panPosition += 1; // will move servo clockwise
		joystickPanSpeed = 1023 - joystickPanSpeed;
	}
	
	else if (joystickPanSpeed < 512) // user has pushed joystick to the left
	{
		panPosition -= 1;
	} // move servo counterclockwise
	//No change to speed
	
	if (joystickPanSpeed != 512 && panPosition > 0 && panPosition < 1000)
	{
		panServo.writeMicroseconds(panPosition + 1000);
		delayMicroseconds(joystickPanSpeed);
	}
	
	// TILT
	if (joystickTiltSpeed > 512) // user has pushed joystick up
	{	tiltPosition += 1; // will move servo clockwise
		joystickTiltSpeed = 1023 - joystickTiltSpeed;
	}
	
	else if (joystickTiltSpeed < 512)
	// user has pushed joystick down
	{
	  tiltPosition -= 1;
	} // move servo counterclockwise
	//No change to speed
	
	if (joystickTiltSpeed != 512 && tiltPosition > 0 && tiltPosition < 1000)
	{
		tiltServo.writeMicroseconds(tiltPosition + 1000);
		delayMicroseconds(joystickTiltSpeed);
	}
// do nothing if joystick at home
} //end of while(1)

} // end of main()

Now that I've installed the IDE, do I still need the "Arduino Create Agent"? Or the simulator?

Not necessarily. As long as you can write the code in there you will be able to upload it to your board. They each serve their own purpose but are unnecessary.

-- DH