New Servo Question

So I have two quick questions.

  1. Is there any way to SEARCH these forums? I'm sure my question has been asked before, but I"m not having any luck finding an answer. :slight_smile:

  2. I'm new to Arduino and just starting to play with builds involving a single servo. Before I play with the "sweep" and "knob" programs, is there anything I need to do to calibrate or initialize the servo? If it can move from angles 0 - 180, and I command it to go to 180, what if the shaft is not at 0? E.g., can the shaft be at 90, and I send it to 180; can it only move 90 more and "break"?

Thanks!

Found the forum search. (Can't believe I missed it.)

This thread looks like it answers some of my questions:

http://forum.arduino.cc/index.php?topic=164829.0

but I still don't know if you can break a servo by commanding it to move more than it "can" move...

gar0u:
but I still don't know if you can break a servo by commanding it to move more than it "can" move...

You can but if you just barely reach the endpoint, it's not likely to damage the servo.

You should use the knob example and monitor where the endpoints are so you can use these values in other programs.

So how do you determine where "center" (90) is? Especially for a new servo?

I don't see any code in the examples that calibrates or centers the servo. Is this something you have to worry about, or do you just plug in the servo and command it to 180 to find the upper bound, regardless of it's current position? Won't that break it?

gar0u:
So how do you determine where "center" (90) is? Especially for a new servo?

I don't see any code in the examples that calibrates or centers the servo. Is this something you have to worry about, or do you just plug in the servo and command it to 180 to find the upper bound, regardless of it's current position? Won't that break it?

Do you have a pot to use with the knob example? If so, I'll let you know which program to try in a few minutes.

When writing demo code, there's always a trade off between writing simple code and writing good code.

I don't fault the authors of the knob demo for keeping the code simple but in my extremely biased opinion, this demo is better.

/* 
 Controlling a servo position using a potentiometer (variable resistor) 
 by Michal Rinott <http://people.interaction-ivrea.it/m.rinott> 

 modified on 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Knob

 modified on 16 Dec 2015
 by Duane Degn
*/

#include <Servo.h>

const int CENTER = 1500;
const int ENDPOINT_MIN = 540; // default value Modify these values after observing your servo in use.
const int ENDPOINT_MAX = 2400; // default value


Servo myservo;  // create servo object to control a servo

const int POT_PIN = 0;  // analog pin used to connect the potentiometer
const int SERVO_PIN = 9;
const int BAUD = 9600;
const int LOOP_DELAY_MS = 10;
int knobPosition;    
int servoPosition; 

void setup()
{
  Serial.begin(BAUD);
  myservo.writeMicroseconds(CENTER); // It's a good idea to write a position before you attach the servo.
  myservo.attach(SERVO_PIN);  // attaches the servo on pin 9 to the servo object
  Serial.println(F(" Modified Knob Demo"));
}

void loop() 
{ 
  knobPosition = analogRead(POT_PIN);            // reads the value of the potentiometer (value between 0 and 1023) 
  servoPosition = map(knobPosition, 0, 1023, ENDPOINT_MIN, ENDPOINT_MAX);     // scale it to use it with the servo
  myservo.writeMicroseconds(servoPosition);     // sets the servo position according to the scaled value 
  Serial.print(F("knobPosition = "));
  Serial.print(knobPosition);
  Serial.print(F(", servoPosition = "));
  Serial.println(servoPosition);
  delay(LOOP_DELAY_MS);                         // waits for the servo to get there 
}

I got rid of most of the "magic numbers" (constants without names such as "1023" which I left in the code).
I used a couple tricks I barely learned myself like writing a position to the servo before attaching it and using the "F" micro (I think that's what it's called) to keep the strings written to the terminal in flash instead of RAM.

I had the code output both the knob position and the servo position. This should let you find the endpoints of the servo you're using.

A couple of things bug me about this example. The use of "delay" blocks the code so if you wanted to do something else in the program, you'd be out of luck.

The other thing I don't like is the use of "map". I've read this doesn't do a very good job of mapping the values used.

I've posted several other servo examples (such as using a joystick to control a servo) and these other examples don't use "delay". I'll likely add some links to these programs in the near future. (I'll edit this post to do so.)

I should warn you, I haven't tested this code. Let me know if it behave unexpectedly. (Come to think of it let me know if it works too.)

Thank you very much for the code.

I'm going to try to pick up a POT from Radio Shack this evening.

I've written plenty of software, but never to control hardware; so this is all very new to me. :slight_smile:

Will let you know how it goes...

So at first I couldn't get anything to work. Then I realized Arduino did not "save" my USB port from the last time I programmed it. After setting the port, I was able to upload a sketch.

The "knob" one did not work, so I decided to try the simpler "sweep" example--and it worked!

My little servo was spinning!

I turned it off, then swapped the horn from the circular pattern to the vertical so I could see its direction easier.

Then I changed the sketch to set the horn position to 90, put the horn on straight up and down, and screwed it down. When I turned it back on, it was moving in a nice 180 degrees.

Next I tried the knob example again. Still nothing.

The only POT at Radio Shack was a 10k w/ a SPDT switch. I wasn't sure I had +5V and GND hooked up on the POT right, so I powered everything off, switched them, then powered it back up...

Now nothing works.

I reloaded the "sweep" program, and took off the POT wiring, and even wired my servo directly into the Arduino; just pin 9, +5V, and GND.

Did I break my servo already? :frowning:

Just tried the other GND on the Arduino board, and the "sweep" sketch is working.

So I swapped back to the previous GND and it worked again.

The lead wires looked like they were all connected, but since both ports work, It must have been the lead...

This is pretty hard when you don't have any previous experience! :slight_smile:

I guess I'll try the "knob" example again...

Still no luck on the "knob" example. I did some Google-fu and learned about the Serial Monitor, so I added a few lines of code to dump out the value of pin 0 coming in from the POT, and it's random garbage. Maybe that's correct, but I was expecting a steady value, and to see the value change when I twisted the knob on the POT.

Lots to learn... :slight_smile:

The sockets on the Arduino board work with solid-core hookup wire, perhaps you are
using multi-strand wires from the pot? It would explain unreliable connection.

Do you have a multimeter to measure voltages? If so, check the output from the wiper of the pot. What sort of voltages do you see from the wiper at the various knob settings?

is there anything I need to do to calibrate or initialize the servo?

Simple servo test code you can use to carefully use to determine the servo rotation mechanical end points.

// zoomkat 3-28-14 serial servo incremental test code
// using serial monitor type a character (s to increase or a 
// to decrease) and enter to change servo position 
// (two hands required, one for letter entry and one for enter key)
// use strings like 90x or 1500x for new servo position 
// for IDE 1.0.5 and later
// Powering a servo from the arduino usually *DOES NOT WORK*.

#include<Servo.h>
String readString;
Servo myservo;
int pos=1500; //~neutral value for continous rotation servo
//int pos=90;

void setup()
{
  myservo.attach(7, 400, 2600); //servo control pin, and range if desired
  Serial.begin(9600);
  Serial.println("serial servo incremental test code");
  Serial.println("type a character (s to increase or a to decrease)");
  Serial.println("and enter to change servo position");
  Serial.println("use strings like 90x or 1500x for new servo position");
  Serial.println();
}

void loop()
{
  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }
  if (readString.length() >0) {
    if(readString.indexOf('x') >0) { 
      pos = readString.toInt();
    }

    if(readString =="a"){
      (pos=pos-1); //use larger numbers for larger increments
      if(pos<0) (pos=0); //prevent negative number
    }
    if (readString =="s"){
      (pos=pos+1);
    }

    if(pos >= 400) //determine servo write method
    {
      Serial.println(pos);
      myservo.writeMicroseconds(pos);
    }
    else
    {   
      Serial.println(pos);
      myservo.write(pos); 
    }
  }
  readString=""; //empty for next input
}

I am using solid-core hookup wire.

I do have a multimeter and will check the POT voltage output soon and report back.

Thanks for the code, zoomkat. I will try that, too. :slight_smile: