SERVO Misbehave

Hi all,
the Servo is misbehaving,
I have tried powering it up from external source, yet it continues to move (in a sweep motion) between 80-110 deg !
Could you advice on what is going on ?

#include <SoftwareSerial.h>  
#include <TinyGPS++.h>  
#include <Wire.h> 

#include <Adafruit_Sensor.h>  
#include <Adafruit_LSM303_U.h> 
#include <Adafruit_BMP085_U.h> 
#include <Adafruit_L3GD20_U.h>  
#include <Adafruit_10DOF.h>

#include <Servo.h>  

#define RXPin 10
#define TXPin 11
#define GPSBaud 9600
#define ConsoleBaud 115200
#define PI 3.1415926535897932384626433832795
 
SoftwareSerial ss(RXPin, TXPin); 
TinyGPSPlus gps; 
Servo myservo;  
unsigned long lastUpdateTime = 0;
 int servoPin = 22;
 
#define EIFFEL_LAT 14.770775
#define EIFFEL_LNG 57.056785


/* Assign a unique ID to the sensors */
Adafruit_10DOF                  dof   = Adafruit_10DOF();
//Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(30301);
Adafruit_LSM303_Mag_Unified     mag   = Adafruit_LSM303_Mag_Unified(30302);
//Adafruit_BMP085_Unified       bmp   = Adafruit_BMP085_Unified(18001);


////////////////////////////////////////////////////////////////////////////////////////
void initSensors()
{
 /* if(!accel.begin())
  {
    // There was a problem detecting the LSM303 ... check your connections 
    Serial.println(F("Ooops, no LSM303 detected ... Check your wiring!"));
    while(1);
  } */
  if(!mag.begin())
  {
    // There was a problem detecting the LSM303 ... check your connections 
    Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
    while(1);
  }
 /* if(!bmp.begin())
  {
    // There was a problem detecting the BMP180 ... check your connections  
    Serial.println("Ooops, no BMP180 detected ... Check your wiring!");
    while(1);
  }*/
}

////////////////////////////////////////////////////////////////

 
void setup()
{
 
   myservo.attach(servoPin);
   myservo.write(90);  
   Serial.begin(ConsoleBaud);
   ss.begin(GPSBaud);
  
  //Serial.println("Starting the I2C interface.");
   Wire.begin(); // Start the I2C interface.

   initSensors();

  
 
}

///////////////////////////////////////////////////////////////////
void loop()
{

  
  
  // If any characters have arrived from the GPS,
  // send them to the TinyGPS++ object
  while (ss.available() > 0)
    gps.encode(ss.read());

  // Every 5 seconds, do an update.
  if (millis() - lastUpdateTime >= 5000)
  {
    lastUpdateTime = millis();
    Serial.println();

sensors_vec_t   orientation;
sensors_event_t mag_event;

   /* Calculate the heading using the magnetometer */
  mag.getEvent(&mag_event);
  if (dof.magGetOrientation(SENSOR_AXIS_Z, &mag_event, &orientation))
  {
    /* 'orientation' should have valid .heading data now */
    Serial.print(F("Heading: "));
    Serial.print(orientation.heading);
    Serial.print(F("; "));
  }

    // Establish our current status
      // Find distance from current location, to Target
    double distanceToDestination = TinyGPSPlus::distanceBetween(
      gps.location.lat(), gps.location.lng(),EIFFEL_LAT, EIFFEL_LNG);

      // Find heading in degrees, from current location, to target
    double courseToDestination = TinyGPSPlus::courseTo(
      gps.location.lat(), gps.location.lng(), EIFFEL_LAT, EIFFEL_LNG);

      
    const char *directionToDestination = TinyGPSPlus::cardinal(courseToDestination);
    int courseChangeNeeded = (int)(360 + courseToDestination - gps.course.deg()) % 360;

    // debug
    Serial.print("DISTANCE: ");
    Serial.print(distanceToDestination);
 
    Serial.print(" , Angle Course2Dest: ");
    Serial.print(courseToDestination);
    
   // Serial.print("  CurCourse: ");
   // Serial.print(gps.course.deg());   

   // bearing by GPS , need to check true bearing by compas. 
   // Bearing set (which will actually be compass heading)
    Serial.print(" , Cardinal Dir2Dest: ");
    Serial.print(directionToDestination);
    Serial.println();
       
   // Serial.print("  RelCourse: ");
   // Serial.print(courseChangeNeeded);
    
   // Serial.print("  CurSpd: ");
   // Serial.println(gps.speed.kmph());

    // Within 20 meters of destination?  We're here!
    if (distanceToDestination <= 20.0)
    {
      Serial.println("CONGRATULATIONS: You've arrived!  ");
      exit(1);
    } 
 
 
      
  }
}

Moderator edit: CODE TAGS, ALWAYS CODE TAGS

d20237:
Hi all,
the Servo is misbehaving,
I have tried powering it up from external source, yet it continues to move (in a sweep motion) between 80-110 deg !
Could you advice on what is going on ?

Start from the bare minimum set-up. What kind of servo is it? What inputs does it accept?

Is it the kind that requires a PWM frequency of 50 Hertz and has a 1500 microsecond pulse width for mid-position? If it is..... then does it work normally if you apply 1500 microsecond pulse widths for a 20000 microsecond PWM period?

Its a Hitec 32645S HS-645MG High Torque 2BB Metal Gear Servo.

Maybe use a 5 to 10 Amp power supply to power the servo. Use an arduino to generate the control pwm signal. Make sure to connect the arduino ground and the negative terminal of the motor power supply together.

The pwm signal needs to have a 50 Hertz frequency.... aka 20000 microsecond period. Set the high time pulse widths of the pwm signal to 1500 microseconds. This means low time of 18500 microseconds.

Use a separate power supply to power the arduino.

When you have a problem with an Arduino program it is important to go back to basics.

Try the servo sweep example that comes with the Arduino IDE.

...R

Robin2:
When you have a problem with an Arduino program it is important to go back to basics.

Try the servo sweep example that comes with the Arduino IDE.

...R

Sweep is working perfect.

Southpark:
Maybe use a 5 to 10 Amp power supply to power the servo. Use an arduino to generate the control pwm signal. Make sure to connect the arduino ground and the negative terminal of the motor power supply together.

The pwm signal needs to have a 50 Hertz frequency.... aka 20000 microsecond period. Set the high time pulse widths of the pwm signal to 1500 microseconds. This means low time of 18500 microseconds.

Use a separate power supply to power the arduino.

Ground is common.
Servo and Arduino have different power supply.

I have commented most of the codes related to the servo.
I've left attach in setup only, Still servo is sweeping between two small angles !!
I have changed the servo, Still the problem is present.

d20237:
I have commented most of the codes related to the servo.
I've left attach in setup only, Still servo is sweeping between two small angles !!
I have changed the servo, Still the problem is present.

Your DC power supply for the motor..... what power output can it handle?

If you used a second servo, and you're still seeing the same thing, then chances are that you either haven't got something connected properly, or your code is not doing the right thing.

I just use a simple code like this...

/*
 * Simple Arduino sketch to find the full pulsewidth range of a servo
 *
 * INSTRUCTIONS
 *
 * Watch the serial port, and press a key each time the servo starts/stops moving regularly.
 * 
 * If you're using the Arduino IDE "Serial Monitor", you'll need to type something into the 
 * text field and then press "Send"
 *
 * When you're done, the sketch will output the low and high pulse widths, a sample attach() line, and then
 * start sweeping from top to bottom so you can check it works and/or measure the total angle.
 *
 * Ignore any massive jumping movements when searching, servos often seem to move to a random angle when
 * you send a really out-of-range signal to them.
 *
 *
 * This sketch is released under the GNU General Public License v2, (C) 2009 Angus Gratton 
 */

// Kenny - Assuming the angle position servo motor is already powered, and digital pin 10 arduino is connected to the servo's PWM control signal INPUT line.
// Use the serial communications monitor. The software starts with pulse width modulation using short pulse-width duration, eg 100 microsecond width to start with.
// No motor response expected due to widths being outside the active range. Iteratively increase the pulse width (increments of +64 microseconds)...eg 164, 228 microseconds etc.
// Eventually the servo will move. This is when we need to press a key (or type a letter in the serial monitor, and press ENTER). This stores the minimum duration required to make the servo respond.
// The ramping continues until we get to a width level where the motor stops responding. At this point, press a key again. This stores the maximum pulse width.

#include <Servo.h>
#include <stdio.h>

char buffer[128]; // This wastes a bunch of RAM, but we don't need it for this sketch
#define printfLn(format, args... ) \
  snprintf(buffer, sizeof(buffer), format, ## args); \
  Serial.println(buffer);


/*
 * Set this to the pin your servo is hooked to (9 or 10.)
 */
const int servopin = 10;

Servo myservo;

void setup() 
{ 
  int del = 64;
  Serial.begin(9600);
  
  myservo.attach(servopin);
} 



void loop() 
{ 
   // Just loop through a few working values

     myservo.writeMicroseconds(1500);
     delay(4000);

}

d20237:
Sweep is working perfect.

Then, what is the key difference between the SWEEP program and your own program that is giving rise to the problem?

...R

Southpark:
Your DC power supply for the motor..... what power output can it handle?

If you used a second servo, and you're still seeing the same thing, then chances are that you either haven't got something connected properly, or your code is not doing the right thing.

I just use a simple code like this...

/*
  • Simple Arduino sketch to find the full pulsewidth range of a servo
  • INSTRUCTIONS
  • Watch the serial port, and press a key each time the servo starts/stops moving regularly.
  • If you're using the Arduino IDE "Serial Monitor", you'll need to type something into the
  • text field and then press "Send"
  • When you're done, the sketch will output the low and high pulse widths, a sample attach() line, and then
  • start sweeping from top to bottom so you can check it works and/or measure the total angle.
  • Ignore any massive jumping movements when searching, servos often seem to move to a random angle when
  • you send a really out-of-range signal to them.
  • This sketch is released under the GNU General Public License v2, (C) 2009 Angus Gratton
    */

// Kenny - Assuming the angle position servo motor is already powered, and digital pin 10 arduino is connected to the servo's PWM control signal INPUT line.
// Use the serial communications monitor. The software starts with pulse width modulation using short pulse-width duration, eg 100 microsecond width to start with.
// No motor response expected due to widths being outside the active range. Iteratively increase the pulse width (increments of +64 microseconds)...eg 164, 228 microseconds etc.
// Eventually the servo will move. This is when we need to press a key (or type a letter in the serial monitor, and press ENTER). This stores the minimum duration required to make the servo respond.
// The ramping continues until we get to a width level where the motor stops responding. At this point, press a key again. This stores the maximum pulse width.

#include <Servo.h>
#include <stdio.h>

char buffer[128]; // This wastes a bunch of RAM, but we don't need it for this sketch
#define printfLn(format, args... )
  snprintf(buffer, sizeof(buffer), format, ## args);
  Serial.println(buffer);

/*

  • Set this to the pin your servo is hooked to (9 or 10.)
    */
    const int servopin = 10;

Servo myservo;

void setup()
{
  int del = 64;
  Serial.begin(9600);
 
  myservo.attach(servopin);
}

void loop()
{
  // Just loop through a few working values

myservo.writeMicroseconds(1500);
    delay(4000);

}

Thanks for reply.
i have changed the pin to 2

const int servopin = 2;

and

added another line

void loop() 
{ 
   // Just loop through a few working values

     myservo.writeMicroseconds(1500);
     delay(4000);
  myservo.writeMicroseconds(2000);
  delay(4000);
}

It is doing well, as it should.
Servo centers, wait, swings ,waits, centers, wait, ...

Regarding power, I am using a 9 volt batter, while my Mega is connected to my PC via USB.

d20237:
Regarding power, I am using a 9 volt batter, while my Mega is connected to my PC via USB.

In a previous post, I recommended to use a 5 Amp or 10 Amp power supply.

So does your 9 Volt battery supply 5 Amp or 10 Amp on a continual/continuous basis? If not, then that could be a problem. Just need to find out if your 9 Volt battery is capable of supplying the required power for long periods of time.

The small rectangular 9V batteries don't work for servos or other motors.

jremington:
The small rectangular 9V batteries don't work for servos or other motors.

It is running fine with other codes/sketches, including the sample code. hence, I do believe it is a code problem rather than, power problem.

Southpark:
In a previous post, I recommended to use a 5 Amp or 10 Amp power supply.

So does your 9 Volt battery supply 5 Amp or 10 Amp on a continual/continuous basis? If not, then that could be a problem. Just need to find out if your 9 Volt battery is capable of supplying the required power for long periods of time.

9v has 0.5Amp rating.
Hobby servo doesn't need 5 amp.
Here is the servo spec, Hitec Super Torque Servo - 3204_0 - Phidgets

Robin2:
Then, what is the key difference between the SWEEP program and your own program that is giving rise to the problem?

...R

Robin2,
Thanks for steering the thoughts.
I am unable to see, that's why I have posted the entire code from the start.
could it be conflict between the SoftwareSerial and Servo libraries

9v has 0.5Amp rating.
Hobby servo doesn't need 5 amp.

According to: Hitec Super Torque Servo - 3204_0 - Phidgets
the servo stall current is 1.8 amperes on a 1061 controller, and the servo draws that every time it starts up. Experienced robotics enthusiasts always budget at least 1 ampere per servo.

For proper operation, your servo power supply must be able to supply at least 1.8 amperes.

jremington:
According to: Hitec Super Torque Servo - 3204_0 - Phidgets
the servo stall current is 1.8 amperes on a 1061 controller, and the servo draws that every time it starts up. Experienced robotics enthusiasts always budget at least 1 ampere per servo.

For proper operation, your servo power supply must be able to supply at least 1.8 amperes.

Yes, But I am applying zero load. Hence, I only need to see rated current.

I have modified the code, and servo behaved.
It was conflict between the SoftwareSerial and Servo libraries , and hence,
I have removed SoftwareSerial library, and used the hardware serial instead. (i am using Mega, so i have plenty)

http://blog.startingelectronics.com/how-to-use-arduino-serial-ports/

d20237:
Yes, But I am applying zero load. Hence, I only need to see rated current.

Even though the average current may be low the motor will probably draw the full stall current briefly whenever it starts to move. Having too much available current is better than too little - or as somebody rather picturesquely said when I was considering whether to buy 20 screws or 30 screws "better to be looking at it than looking for it"

...R

Yes, But I am applying zero load. Hence, I only need to see rated current.

A common beginner misunderstanding, leading to trouble down the road.