I'm having trouble getting a servo to respond

I'm starting a project to build a walker, and the servo I bought to test the waters isn't responding.

To start off with I'm using the "Sweep example in the sketchbook. I have everything connected correctly and the darn thing still wont budge.

This is the servo I bought. http://www.servocity.com/html/hs-55_sub-micro.html

Is it a problem that the servo is an analog one. I'm seeing digital ones and I'm wondering if I bought one that the arduino cant control.

First thing to d, of course, is to make sure your connections are correct. If possible, have someone else check it. If you check it yourself, don't approach it thinking "it's all correct", start by thinking "there's a mix-up somewhere; I must find it".

I ran the "Sweep" example myself yesterday, and then the "Melody" one. I connected the piezo speaker to the Arduino was still running "Sweep", and I could hear the "Sweep" pulses. If you have a piezo speaker (or similar), try that just to make sure the Arduino code is running OK.

I don't have any piezios lying around. An LED didn't do squat and my multimeter didn't move at all. I tried these tests on two different PWM pins.

Oh, I'm using an Arduino Diecimila.

OK, So I wanted to try some different code, so I headed back to the Playground. I found this page

I added the new header and .c files to my hardware/libraries/servo folder and when I execute the following code, it kicks it back saying that it can't understand the refresh command.

#include <Servo.h>

Servo servo1; Servo servo2;

void setup() {

pinMode(1,OUTPUT);
servo1.attach(14); //analog pin 0
//servo1.setMaximumPulse(2000);
//servo1.setMinimumPulse(700);

servo2.attach(15); //analog pin 1
Serial.begin(19200);
Serial.println("Ready");

}

void loop() {

static int v = 0;

if ( Serial.available()) {
char ch = Serial.read();

switch(ch) {
case '0'...'9':
v = v * 10 + ch - '0';
break;
case 's':
servo1.write(v);
v = 0;
break;
case 'w':
servo2.write(v);
v = 0;
break;
case 'd':
servo2.detach();
break;
case 'a':
servo2.attach(15);
break;
}
}

Servo::refresh();

}

This is my error Message:

In function 'void loop()':
error: 'refresh' is not a member of 'Servo'Couldn't determine program size: C:\Users\John\Documents\duino\arduino-0012-win\arduino-0012\hardware/tools/avr/bin/avr-size: 'C:\Users\John\AppData\Local\Temp\build4363.tmp\Sweep.hex': No such file

Are you sure this is what you want? Servo::refresh();

This is my first time ever using a servo, so I'm not exactly sure what I'm looking for. I've got the servo attached to a PWM pin. I just tried modifying the classic Blink sketch to manually send out timing signals, but that didn't work either. I managed to make it twitch, but it maved only in short increments in one direction, even though I was only sending it the signals for it's 0 and 180 locations. It's minimum pulse is 600 and it's maximum is 2400

here's the code.

/*

  • Blink
  • The basic Arduino example. Turns on an LED on for one second,
  • then off for one second, and so on... We use pin 13 because,
  • depending on your Arduino board, it has either a built-in LED
  • or a built-in resistor so that you need only an LED.
  • http://www.arduino.cc/en/Tutorial/Blink
    */

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

void setup() // run once, when the sketch starts
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}

void loop() // run over and over again
{
digitalWrite(ledPin, HIGH); // sets the LED on
delay(.06); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
digitalWrite(ledPin, HIGH); // sets the LED on
delay(.24); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
}

(ignore the comments)

Delay is in milliseconds, you need to set a delay in microseconds.

Try this:

int servoPin = 8;                // servo connected to digital pin 8

void setup()                    // run once, when the sketch starts
{
  pinMode(servoPin, OUTPUT);      // sets the digital pin as output
}

void loop()                     // run over and over again
{
  for(int i=0; i < 50; i++){ // 900 us pulse for 1 second
    digitalWrite(servoPin, HIGH);  
    delayMicroseconds(900);    
    digitalWrite(servoPin, LOW);   
    delay(20); // delay 20 milliseconds 
  } 

  for(int i=0; i < 50; i++){ // 2000 us pulse for 1 second
    digitalWrite(servoPin, HIGH);  
    delayMicroseconds(2000);    
    digitalWrite(servoPin, LOW);   
    delay(20); // delay 20 milliseconds 
  } 
}

My servo seems to struggle when it reaches either end of it's swath. Is this standard for servos or is mine faulty?

Also, It's nuetral position is about 10-15 degrees off of true, and the ends of rotation are off by the same difference. Is this something I can correct myself? I do need 180 degrees of (clean, non-strugling) rotation for the walker.

Third (and lastly) When I use the following code, if the potentiometer is moved away from a similar state as the servo, it twitches around five or ten times in the direction it needs to go, then doesn't move at all (falling vastly short of it's intended destination). Other time's it vibrates gently and makes an angry, bad sounding noise. I unplug the signal line sa soon as than happens for fear of ruining the pricey bugger.

int servoPin = 8;
int potPin = 2;
int pos = 600;

void setup()
{
pinMode(servoPin, OUTPUT);
pinMode(potPin, INPUT);
}

void loop()
{
pos = analogRead(potPin);
pos = map(pos, 0, 1023, 600, 2400);
for(int i=0; i < 50; i++){
digitalWrite(servoPin, HIGH);
delayMicroseconds(pos);
digitalWrite(servoPin, LOW);
delay(5);
}

}

You are driving the servos to 600 and 2400 microseconds at the extremes and some servos may not cope with these values. Hobby servos are typically used within the range of 1000 to 2000 microseconds and although they can cope with more, there is no guarantee that the ones you have are ok at the values you are using. Use trial and error to see find out what range your servos are comfortable with and don't exceed that range. If the servo is buzzing or chattering then you have exceeded its working range. If your servos don't give you 180 degrees then you may need to find different servos.

Your code is delaying 5 milliseconds between pulses. This is not enough – use 20 milliseconds as in the example code in the previous post.

Even with 20 miliseconds (which I tried both before and after the reduced delay, it begins to chatter.

The motor shield should do a better job Motor Shield - Arduino motor/stepper/servo control :slight_smile:

I don't have any cash on hand, and the final product will require 12 servos, and compared with the 2 ports on the motor shield, comes up a bit shy. I'll be moving the final project off of the arduino and onto either my Sanguino or something a bit bigger I've got in the works.

Also, when I run the following code, my servo takes breaks traveling to it's intended angle. - YouTube

int servoPin = 8;
int potPin = 2;
int pos = 600;

void setup()
{
pinMode(servoPin, OUTPUT);
pinMode(potPin, INPUT);
}

void loop()
{
pos = analogRead(potPin);
pos = map(pos, 309, 450, 700, 2300);
for(int i=0; i < 50; i++){
digitalWrite(servoPin, HIGH);
delayMicroseconds(pos);
digitalWrite(servoPin, LOW);
delay(20);
}

}

Your youtube link doesn't seem to work

Youtube is saying: "This video is unavailable."

You will need something with a lot of IO pins and a good external power supply to drive all those servos

:slight_smile:

I'm working on a board built around a monster. I'll be able to drive them and then some.

The video was unavailable, now it is. Youtube just hadn't processed it yet, now you can take a look at my problem, in all it's youtubishly grainy quality.

That code is only reading the pot once every second, try it without the for loop.

Also, how did you choose those map values? If the analogRead values go from 0 to 1024 why not map those to the pulse range.

For the reasons I posted earlier, I suggest you try to use a pulse range from 1000 to 2000 to get things going. When you can smoothly control the servo, you can experiment to see how big a range your servo will support.

I can see it now in all its grainy youtube greatness :slight_smile:

What are you building with 12+ IO pins?

What kind of power are you going to use?

You may need a precision timer

:slight_smile:

ATTN: mem-

I chose those values because when I tested the pot, those are it's limits. At one end it stays at aou 311, and at the other it stays around 445. I retested a few times, and it's ends fluctuate everytime I upload new code. Is there a way that I can stop this from happening, or write in some code to manually set it's limits once the program is already running? Also, the data coming from the pot has a bit of jitter on it. Can I smooth this out somehow?

I Checked the highest spikes from the pot and accounted accordingly for them. I'll take that line out, limit the servo range even further to it's inner 90deg (I'm already about 10% in an each end) and see how it works. also, does map work as I think it does? Here's what I think happens.
var = map(var, A1, B1, A2, B2);
Where A1 and B1 are the initial endpoints, and A2 and B2 are the finl points the data is stretched to.

ATTN: Gnu-

In the first post I explain that I'm building a quadruped, and for purposes of agility and other uses (a walking cnc machine if I can get the math right). I'll be building my own power management circuit with the help of a friend (this is becoming a team build at the dorm). What is this precision timer of which you speak, and why would we need one?

Latest code:

int servoPin = 8; //Naming the pin for the servo
int potPin = 2; //Naming the pin for the potentiometer
int pos = 600; //Decloring an initial value for "pos",
// "pos" will be rewritten before 600 can be used
void setup() //Declaring the usage of each pin
{
pinMode(servoPin, OUTPUT); //Set the Servo's pin as an output
pinMode(potPin, INPUT); //Set the Potentiometer's pin as an input
Serial.begin(9600); //Set the data rate for serial communications at 9600

}

void loop() //The actual running loop
{
pos = analogRead(potPin); //Reading the position of the pot and saving it as "pos"
Serial.println(pos); //Tell me where the servo is
pos = map(pos, 310, 370, 1050, 1950); //Changing the pot's data into the impulse length
//Serial.println(pos); //Tell me where the servo is
digitalWrite(servoPin, HIGH); //Start the servo's impulse
delayMicroseconds(pos); //The impulse length as determined by the value of "pos"
digitalWrite(servoPin, LOW); //End the servo's impulse
pos = map(pos, 600, 2400, 0, 180); //Turn the impulse length into degrees
//Serial.println(pos); //Tell me where the servo is
delay(15); //Allow the servo to get to it's desired position

}

Aha! I know your problem!
Your servo has different minimum/maximum pulses than what you have in the code:

"This servo can operate 180° when given a pulse signal ranging from 600usec to 2400usec."

I think that all you need to do is change that and you're golden!

Well Mark, it doesn't like going to it's limits, and right now I'm working on getting a nice, smooth, proportional transition in it's happy-zone. To be simple for now, I'm sticking with 1050 and 1950 us impulses.