Servo sweep works but the servos spin 360. code problem or bad servo's

Hi, this is my first post here so i apologize if this in the wrong section. I have enclosed my code below. What I am doing is using a sensor that outputs float numbers for x,y and z. I then convert them to an integer so that are whole numbers then convert them to their inverse by multiplying them by -1. I then send that integer to the servo. The problem is when i ground Pin 2 to end the servo sweep test the servo’s just spin in circles. Occasionally the servo’s will stop and try to move like they are supposed to, but then spin in circles. Do you think this is a code error or bad servo’s or is the loop refreshing to quickly? I am using external power to power the Arduino and the servos.

What this will is for is for a gimbal engine mount for a high powered rocket. It is mainly for bench design and will not go any further but I wanted to see if I can create the gimbal and have it correct the pitch and roll.

Thank you for any help that you can provide.

Guidence Code.txt (8.47 KB)

You haven't said what servos you are using which might be helpful information. And are you saying that the sweep test performs completely normally?

But one thing is that a standard servo will not ever spin continually in circles. Most will only travel through about 180 degrees total. So I'd say you either have the wrong type of servo or bad servos.

Steve

Yes they run the sweep correctly. After that they spin 360 degrees, they are not continuous servo’s they are Tower Pro SG90’s. I am thinking they are defective its odd that they both do the same thing though.

There are some SG90's that are sold pre-modified to be continuous rotation.
I suspect that you purchased that type instead of the standard servo.

Where did you get them?

Here is the link to the servo's I got. Any recommendation on servos that are not configured as continuous ? Thanks again for all the help!

https://www.amazon.com/gp/product/B01608II3Q/ref=oh_aui_detailpage_o04_s00?ie=UTF8&psc=1

I see nothing in that advertisement that indicates that the offered product is continuous or 360.

Either you were unlucky and got several broken servos, or you ordered from a different link.

I purchased a 20 pack of SG90 servos from AliExpress. I have been happy with them so far.

I must just be the unlucky one. I will order some new ones and test again. Thanks !

You’ll note that the first answer to a question on that Amazon page say they only travel 180 degrees which is normal for an SG90.

What I can’t understand is how the sweep test code seems to work.

Steve

I was thinking it was something to do with the 100 ms delay at the end of the loop, maybe the servo can not update that quickly. I will change it and try again.

Can you describe for us again how the servo behaves during the sweep execution?
Does it move back and forth in an arch of about 180 degrees, never more?

edit: Look at 4:00 on this tutorial video for how the sweep is expected to move the servo
[Arduino - Servo Motors - Sweep Actions - YouTube](http://edit: Look at 4:00 on this tutorial video for how the sweep is expected to move the servo Arduino - Servo Motors - Sweep Actions - YouTube)

Yes the servo's sweep 5 degrees at a time just like the code says, as soon as the last for statement is done then they just both spin 360. Occasionally they stop and twitch around but then start spinning again.

1 Like

That makes no sense to me at all.

Can you post the code that creates that behavior? And it would be cool to see a video.

With my understanding of the sweep code, there would be nothing to tell your continuous rotation servo to stop rotating. Well, except for the moment when it is at 90 degrees. I would expect it to stop there, right before it started rotating the other direction.

The code is attached to the 1st post. If I can not figure out this issue i will post a video of the servo's going bonkers for everyone's enjoyment :). Thanks !

Here is the code for just the sweep this is working correctly.

if (digitalRead(2) == HIGH) //when pin 2 goes HIGH then
{
for (pos = 0; pos <= 180; pos += 5) // goes from 0 degrees to 180 degrees
{ // in steps of 5 degree
pitchServo.write(pos); // tell servo to go to position in variable ‘pos’
lcd.clear();
lcd.setBacklight(HIGH);
lcd.print(“Pitch Servo Test”);
lcd.setCursor(0,1);
lcd.print("Pitch Servo @ ");lcd.print(pos);lcd.print(“Deg”);
delay(500);
// waits 15ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 5) // goes from 180 degrees to 0 degrees
{ // in steps of 5 degree
pitchServo.write(pos); // tell servo to go to position in variable ‘pos’
lcd.clear();
lcd.setBacklight(HIGH);
lcd.print(“Pitch Servo Test”);
lcd.setCursor(0,1);
lcd.print("Pitch Servo @ ");lcd.print(pos);lcd.print(“Deg”);
delay(500); // waits 15ms for the servo to reach the position
}
for (pos = 0; pos <= 180; pos += 5) // goes from 0 degrees to 180 degrees
{ // in steps of 5 degree
rollServo.write(pos); // tell servo to go to position in variable ‘pos’
lcd.clear();
lcd.setBacklight(HIGH);
lcd.print(“Roll Servo Test”);
lcd.setCursor(0,1);
lcd.print("Roll Servo @ ");lcd.print(pos);lcd.print(“Deg”);
delay(500); // waits 15ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 5) // goes from 180 degrees to 0 degrees
{ // in steps of 5 degree
rollServo.write(pos); // tell servo to go to position in variable ‘pos’
lcd.setBacklight(HIGH);
lcd.clear();
lcd.print(“Roll Servo Test”);
lcd.setCursor(0,1);
lcd.print("Roll Servo @ ");lcd.print(pos);lcd.print(“Deg”);
delay(500); // waits 500ms for the servo to reach the position
}
}

Sorry, here is the sweep code that is way easier to read. Thanks again for all the help that this forum provides.

if (digitalRead(2) == HIGH)  //when pin 2 goes HIGH then 
  {  
  for (pos = 0; pos <= 180; pos += 5)    // goes from 0 degrees to 180 degrees
  {                                      // in steps of 5 degree
    pitchServo.write(pos);               // tell servo to go to position in variable 'pos'
    lcd.clear();
    lcd.setBacklight(HIGH);
    lcd.print("Pitch Servo Test");
    lcd.setCursor(0,1);
    lcd.print("Pitch Servo @ ");lcd.print(pos);lcd.print("Deg");
    delay(500);
    // waits 15ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 5)   // goes from 180 degrees to 0 degrees
  {                                     // in steps of 5 degree
    pitchServo.write(pos);              // tell servo to go to position in variable 'pos'
    lcd.clear();
    lcd.setBacklight(HIGH); 
    lcd.print("Pitch Servo Test");
    lcd.setCursor(0,1);
    lcd.print("Pitch Servo @ ");lcd.print(pos);lcd.print("Deg");
    delay(500);                         // waits 15ms for the servo to reach the position
  }
  for (pos = 0; pos <= 180; pos += 5)   // goes from 0 degrees to 180 degrees
  {                                     // in steps of 5 degree
    rollServo.write(pos);               // tell servo to go to position in variable 'pos'
    lcd.clear();
    lcd.setBacklight(HIGH); 
    lcd.print("Roll Servo Test");
    lcd.setCursor(0,1);
    lcd.print("Roll Servo @ ");lcd.print(pos);lcd.print("Deg");
    delay(500);                         // waits 15ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 5)   // goes from 180 degrees to 0 degrees
  {                                     // in steps of 5 degree
    rollServo.write(pos);               // tell servo to go to position in variable 'pos'
    lcd.setBacklight(HIGH); 
    lcd.clear();
    lcd.print("Roll Servo Test");
    lcd.setCursor(0,1);
    lcd.print("Roll Servo @ ");lcd.print(pos);lcd.print("Deg");
    delay(500);                         // waits 500ms for the servo to reach the position
   }
  }

hmmm... That does not look like a complete program.
And it has a lot in it that has nothing to do with servos.

Can you run the servo sweep tutorial from the arduino tutorial?

Edit: of course, change the pin to whatever your servo pin is.

Here is the complete code. Thanks !

//---- Included Libraries ----//
#include <Wire.h>                           // I²C library
#include <math.h>                           // trig functions
#include <Adafruit_Sensor.h>                // Base library for sensors
#include <Adafruit_BNO055.h>                // BNO055 specific library
#include <utility/imumaths.h>               // Vector, Matrix, and IMUMath library
#include <Servo.h>                          // Standard Servo library
#include <XLR8Float.h>                      // XLR8 accelerated floating point math
#include <LiquidCrystal_I2C.h>

#define BNO055_SAMPLERATE_DELAY_MS (100)     // Set pause between samples

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7); // 0x27 is the I2C bus address for an unmodified backpack

//---- Variable Declaration ----//

boolean debug = true;                       // true/false

int rollPin  = 8;                           // Digital pin for roll
//int yawPin   = ;                          // Digital pin for yaw
int pitchPin = 9;                           // Digital pin for pitch
int iAbort = 0;                             // over bank and pitch counter

float roll, pitch, yaw;                     // Variable to hold roll, pitch, yaw information

Adafruit_BNO055 bno = Adafruit_BNO055();    // Use object bno to hold information

Servo rollServo;                            // Create servo rollServo
Servo pitchServo;                           // Create servo pitchServo

void setup(void) {

  rollServo.attach(rollPin);                // The rollServo is connected at rollPin
  pitchServo.attach(pitchPin);              // The pitchServo is connected at pitchPin

  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);

  pinMode(2,INPUT);                         // Pin for SELF TEST
  pinMode(3,INPUT);                         // Pin for LCD output
    
  lcd.begin (20, 4);                        // for 20 x 4 LCD module
  lcd.setBacklightPin(3, POSITIVE);         // set backlight pin
  lcd.setBacklight(HIGH);                   // turn on backlight
  lcd.print("LCD Initialized");
  lcd.setCursor(0,1);
  lcd.print("BNO055 Sensor Test");
  rollServo.write("0");
  pitchServo.write("90");
  delay(2000);

  if (!bno.begin())                         // Attempt communication with sensor
  {
    //Serial.print("BNO055 NOT detected ... Check your wiring or I2C ADDR!");
    lcd.print("BNO055 NOT DETECTED");
    lcd.setCursor(0,1);
    lcd.print("Check Bus Wiring");
  }

  delay(100);                               // Wait 0.1 seconds to allow it to initialize

  lcd.clear();
  lcd.setBacklight(LOW);

  bno.setExtCrystalUse(true);               // Tell sensor to use external crystal
}

//---- Main Program Loop ----//
void loop() {

digitalWrite(13,LOW);
  //---- Request Euler Angles from Sensor ----//
  imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER);
  
  /* Remap information from the sensor over the 0° - 180° range of the servo
     The Roll values are between -90° and +90°
     The Pitch values are between -180° and +180°
  */

  int iYaw = (int) (euler.x() + 0.5);       // convert float to integer and round correctly to whole number
  int iRoll =(int) (euler.y() + 0.5);       // convert float to integer and round correctly to whole number
  int iPitch = (int) (euler.z() + 0.5);     // convert float to integer and round correctly to whole number

  int ServoPitchCorrection; 
  int ServoRollCorrection; 
  
  int iPitchMaxPos = 140;     //Over Pitch Degisnator
  int iPitchMaxNeg = 40;      //Over Pitch Degisnator
  int iRollMaxPos = 40;       //Over Roll Degisnator
  int iRollMaxNeg = -40;      //Over Roll Degisnator
  
  int pos = 0;                // set sweep int to "0"
 
  ServoPitchCorrection = iPitch * -1;       // set the servo integer to the inverse of the current angle
  ServoRollCorrection = iRoll * -1;         // set the servo integer to the inverse of the current angle

  int servoRoll =  map(ServoRollCorrection, -90, 90, 0, 180);
  int servoPitch = map(ServoPitchCorrection, -180, 180, 0, 180);


  if (iPitch == 90)                         // if pitch is 90 then don't move the pitch servo
  {
    ServoPitchCorrection = 90;   // vehicle is staight up and verticle
  }

  //##### BUILD IN A FOR STATMENT TO TEST THE SERVOS RANGE OF MOTION need a pull down resistor to make this work between pin 2 and GND
  if (digitalRead(2) == HIGH)  //when pin 2 goes HIGH then 
  {  
  for (pos = 0; pos <= 180; pos += 5)    // goes from 0 degrees to 180 degrees
  {                                      // in steps of 5 degree
    pitchServo.write(pos);               // tell servo to go to position in variable 'pos'
    lcd.clear();
    lcd.setBacklight(HIGH);
    lcd.print("Pitch Servo Test");
    lcd.setCursor(0,1);
    lcd.print("Pitch Servo @ ");lcd.print(pos);lcd.print("Deg");
    delay(500);
    // waits 15ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 5)   // goes from 180 degrees to 0 degrees
  {                                     // in steps of 5 degree
    pitchServo.write(pos);              // tell servo to go to position in variable 'pos'
    lcd.clear();
    lcd.setBacklight(HIGH); 
    lcd.print("Pitch Servo Test");
    lcd.setCursor(0,1);
    lcd.print("Pitch Servo @ ");lcd.print(pos);lcd.print("Deg");
    delay(500);                         // waits 15ms for the servo to reach the position
  }
  for (pos = 0; pos <= 180; pos += 5)   // goes from 0 degrees to 180 degrees
  {                                     // in steps of 5 degree
    rollServo.write(pos);               // tell servo to go to position in variable 'pos'
    lcd.clear();
    lcd.setBacklight(HIGH); 
    lcd.print("Roll Servo Test");
    lcd.setCursor(0,1);
    lcd.print("Roll Servo @ ");lcd.print(pos);lcd.print("Deg");
    delay(500);                         // waits 15ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 5)   // goes from 180 degrees to 0 degrees
  {                                     // in steps of 5 degree
    rollServo.write(pos);               // tell servo to go to position in variable 'pos'
    lcd.setBacklight(HIGH); 
    lcd.clear();
    lcd.print("Roll Servo Test");
    lcd.setCursor(0,1);
    lcd.print("Roll Servo @ ");lcd.print(pos);lcd.print("Deg");
    delay(500);                         // waits 15ms for the servo to reach the position
  }
  }

  if (iPitch > iPitchMaxPos)
  {
    lcd.setCursor(0,3);
    pitchServo.write(iPitchMaxNeg); 
    iAbort = iAbort + 1;
    //lcd.print(iAbort);
    digitalWrite(13,HIGH);
  }
  
  else if (iPitch < iPitchMaxNeg)
  {
    lcd.setCursor(0,3);
    pitchServo.write(iPitchMaxPos); 
    iAbort = iAbort + 1;
    //lcd.print(iAbort);
    digitalWrite(13,HIGH);
  }

  else if (iRoll > iRollMaxPos)
  {
    lcd.setCursor(0,3);
    rollServo.write(iRollMaxNeg); 
    iAbort = iAbort + 1;
    //lcd.print(iAbort);
    digitalWrite(13,HIGH);
  }

  else if (iRoll < iRollMaxNeg)
  {
    lcd.setCursor(0,3);
    rollServo.write(iRollMaxPos); 
    iAbort = iAbort + 1;
    //lcd.print(iAbort);
    digitalWrite(13,HIGH);
  }

  else    
   {
    iAbort = 0;                                         // Reset the Abort counter
    pitchServo.write(ServoPitchCorrection);             // Send correction value to PitchServo
    rollServo.write(ServoRollCorrection);               // Send correction value rollServo
   }

  if (iAbort > 5)
  {
    lcd.clear();
    lcd.print("ABORT SEQUENCE");
    lcd.setCursor(0,1);
    lcd.print("INITIATED");
    pitchServo.write("90"); // send servo to home position
    rollServo.write("0");   // send servo to home position
    // ADD IN PIN GOING HIGH TO CLOSE A LATCHING RELAY, ENGINE OFF, RECOVERY START
    delay(100000); // PAUSE INDEFINTENLY
  }

  
  if (digitalRead(3) == HIGH)  //when pin 2 goes HIGH display information on LCD
    // DISPLAY INFORMATION FOR CALIBRATION
  {
    lcd.setBacklight(HIGH);
    lcd.clear();
    lcd.print("Yaw ");lcd.print(iYaw);lcd.setCursor(9,0);
    lcd.setCursor(0,1);
    lcd.print("Roll ");lcd.print(iRoll);lcd.setCursor(12,1);lcd.print("Ycr ");lcd.print(ServoRollCorrection);
    lcd.setCursor(0,2);
    lcd.print("Pitch ");lcd.print(iPitch);lcd.setCursor(12 ,2);lcd.print("Xcr ");lcd.print(ServoPitchCorrection );
    lcd.setCursor(0,3);
    lcd.print("Abort Sequence # ");lcd.print(iAbort);
    // DISPLAY INFORMATION FOR CALIBRATION
  }

  delay(BNO055_SAMPLERATE_DELAY_MS);       // Wait before rerunning loop
}

Here is the video of the sweep test. It is the Pitch servo, as soon as the pitch sweep is done the servo just spins. Totally bizarre.

Sweep Test

Very strange. Your video clearly shows that the servo still has the position pot in place and can function as a servo.

Also, it shows that at angles below about 10 or 15, it spins continuously.

That second part is not expected.
I would call this a broken servo.
If you can get away with keeping the servo angle above 15 or 20, you might still be able to use it.

I am going to order new servos, this is just a proof on concept before I build what it is going to be connected to. Before I go any further though I want this thing to work. Time to order new servo's. Thanks for all the help. I will post an update once I get the new servo's. Lets hope the new ones don't do the same thing :o