Servo works intermittently, can't figure out why.

So, I have a simple project. I basically hooked a standard size servo (Link) to a bicycle derailleur to shift it electronically. My setup is pretty simple. I have one servo, two buttons, and one LED, all controlled by an Uno. Circuit diagram on Tinkercad Circuits here. The code will tell the servo to upshift or downshift to the next gear when a button is pressed. (One for up, one for down.)

// Electromechanical derailleur project v.1.0
// Assumes you know the servo positions for each gear (determined using v.0.0 software)

#include <Servo.h> 
#include <EEPROM.h>            //Need this because we'll be saving the gear selection in EEPROM (to avoid shifts on startup)

#define db_time 20             //Button debounce time in mS
#define servo_pin 3            //HW pin to which servo signal line is attached
#define servoDelta 1           //Amt servo moves with each button push (degress)
#define upButtonPin 6          //Up button push grounds it
#define dnButtonPin 7         //Dn button push grounds it
#define led_pin 5             //LED Turn ON when button is pressed
#define highestGear 6          //Number of sprockets on rear hub
#define threshold 2000       // Long press button time threshold in mS
#define rearGear1 105         //Servo position values for the various rear sprockets (numbered low to high gears, not by size)
#define rearGear2 95          //These were determined empirically using the diyshift0 sketch while hooked up to a laptop
#define rearGear3 85
#define rearGear4 75
#define rearGear5 65
#define rearGear6 55
//#define rearGear7 90
//#define rearGear8 85
//#define rearGear9 80
#define rearGearAddr 0            //EEPROM address for saving the gear selected

Servo rearServo;                  // Create servo object to control a servo 
int   lastUpButtonState = 1;
int   lastDnButtonState = 1;
int   rearPos = 90;               // variable to store the servo position
int   rearGear;                   //Numbered sprocket (1 is lowest gear; 9 is highest)
 
void setup() 
{ 
  
  rearGear = EEPROM.read(rearGearAddr);
  rearServo.attach(servo_pin);                          //Attach the rear servo to the servo object
  
  if ((rearGear > 0) && (rearGear < 7))
  {
    shiftToRearGear(rearGear);                          //And immediately set it to whatever gear was last saved in EEPROM
  }
  else
  {
    shiftToRearGear(3);                                 //If not valid, goto gear 3
  }
  
  pinMode(upButtonPin, INPUT);
  pinMode(dnButtonPin, INPUT);
  pinMode(led_pin, OUTPUT);

  digitalWrite(upButtonPin, HIGH);                      //Enable internal pullup resistors
  digitalWrite(dnButtonPin, HIGH);
  digitalWrite(led_pin, LOW);
  
  Serial.begin(9600);    //USED ONLY FOR DEBUG
} 
 
 
void loop() 
{ 
  int upButtonState = digitalRead(upButtonPin);          //Poll the up/dn buttons
  int dnButtonState = digitalRead(dnButtonPin);
  int count;                                             //variables to count the time button is held

  
  if (upButtonState == 0){                               //Button was pushed
    delay(db_time);                                      //Wait a bit to debounce the button
    upButtonState = digitalRead(upButtonPin);            //Test again
    if (upButtonState == 0 && lastUpButtonState == 1){   //If still down AND was up before
      upOneGear();                                       //Shift up one gear
      lastUpButtonState = 0;                             //Save state
      digitalWrite(led_pin, HIGH);                       // Turn On LED when button is pressed
    }
  }
  else {                                                  //upButton must be open (button state = 1)
    delay (db_time);                                      //Wait a bit to debounce the button
    upButtonState = digitalRead(upButtonPin);             //Test again
    if (upButtonState == 1){                              //Still open, save state
      lastUpButtonState = 1;
      digitalWrite(led_pin, LOW);
    }
  }
  //
  //Now same for dowm
  //
  if (dnButtonState == 0){                               //Button was pushed
    delay(db_time);                                      //Wait a bit to debounce the button
    dnButtonState = digitalRead(dnButtonPin);            //Test again
  
    if (dnButtonState == 0 && lastDnButtonState == 1){   //If still down AND was up before
      dnOneGear();                                       //Shift down one gear
      lastDnButtonState = 0;                             //Save state
      digitalWrite(led_pin, HIGH);                       // Turn On LED when button is pressed
    }
  else if(dnButtonState == 0 && lastDnButtonState == 0)
  {
    unsigned long last_time=millis(); 
    
    do
    {
     dnButtonState = digitalRead(dnButtonPin);
     if(dnButtonState == 1)
      {
       break;
      }
     else if((millis()-last_time)>threshold)  
      {
       dnRearGear1();
      }
     
    }
   while(1);  
    
  
  }
  }
  else {                                                  //dnButton must be open (button state = 1)
    delay (db_time);                                      //Wait a bit to debounce the button
    dnButtonState = digitalRead(dnButtonPin);             //Test again
    if (dnButtonState == 1){                              //Still open, save stated
      lastDnButtonState = 1;
      digitalWrite(led_pin, LOW);
    }
  }
}
//
//Functions called
//
  void upOneGear(){
    if (rearGear < highestGear){
      rearGear = rearGear + 1;
    }
    shiftToRearGear(rearGear);
  }
  
    void dnOneGear(){
    if (rearGear > 1){
      rearGear = rearGear - 1;
    }
    shiftToRearGear(rearGear);
  }
  
  void dnRearGear1(){
    if (rearGear > 1){
      rearGear = 1;
    }
    shiftToRearGear(rearGear);
  }
  
  void shiftToRearGear(int gear){
      EEPROM.write(rearGearAddr, gear);
      switch (gear) {
    case 1:
      rearServo.write(rearGear1);
      break;
    case 2:
      rearServo.write(rearGear2);
      break;
    case 3:
      rearServo.write(rearGear3);
      break;
    case 4:
      rearServo.write(rearGear4);
      break;
    case 5:
      rearServo.write(rearGear5);
      break;
    case 6:
      rearServo.write(rearGear6);
      break;
   // case 7:
     // rearServo.write(rearGear7);
      //break;
    //case 8:
     // rearServo.write(rearGear8);
      //break;
    //case 9:
      //rearServo.write(rearGear9);
      //break;
    }
  }

I copied this code from this website: DIY Derailleur e-Shifter with Arduino Nano... need help with programming... - Endless Sphere. All I have changed is I commented out the extra gears, the person on this website had nine and I have six. I also changed the variables that correspond to that (highest gear is now 6, not 9, etc.).

I have the servo power soldered to a USB cable. Both the servo USB cable and the Arduino are powered from a portable battery bank intended for charging phones. It is capable of 2.4A per USB port (it has 2), 3.4A total. The only data I have found on this servo’s current draw is from an Amazon answered question, where they claim a 1.8A maximum current draw at 5v when it is stalled.

However, the servo in the derailleur will only “power up” intermittently- I can hear it hum or move when it does.

Here is what I know:
-The battery is charged.
-The wiring to the servo is intact and works. I know the wires didn’t come unsoldered.
-The power wires to the servo are receiving power. I measured 5.05v with my multimeter, right where it should be.
-The code works. I tested it in Tinkercad Circuits, with the servo out of the bike, and with a different servo. They all work.
-The problem isn’t caused by a bad connection on the buttons, either. The LED lights up whenever I push them, just as it should. Thus, the Arduino is receiving and interpreting the signals.

Continued:
Here is what I have tried:
-Unplugging the servo and Arduino USB cables from the battery and plugging them back in. I have switched ports, the problem still remains.
-Hooked up another servo to the Arduino- powered and signaled by it. It works.
-Mechanically disconnected the servo from the derailleur so that it can spin freely. The problem remains.
-Connected a wire between the servo USB cable ground and Arduino ground in case the battery doesn't have them connected. Didn't work.

Here is what I think:
-I don't think that the servo has burned out. It still works occasionally- maybe once every 20 times I plug everything back in. Both when it does and doesn't work, I can't feel any heat coming from the servo or battery pack, so I don't think it is any thermal protection circuit either.
-I don't think it is an issue of not enough power. The battery pack was giving off 5v, and the servo isn't making any noise when it isn't working. As I said above, the battery pack can provide enough current.

Do any of you know what is going on or what I can try?
Any help will be greatly appreciated. I am pretty lost.

(deleted)

Proper use of code tags on your first post. Yay! Karma++

If I were troubleshooting this, I would try a different power source for the servos. An appropriate number of AA batteries for example. Make sure it has a common ground to the arduino.

Here’s an image of the circuit diagram. Sorry about that.
Edit: For some reason that image isn’t showing up, here is the URL: Electronic Derailleur Circuit Diagram - Album on Imgur
I tried a different power source, one of these breadboard power supplies set to 5v (Here), powered by a 9v battery through that barrel connector and connected a common ground to the Arduino.The servo still didn’t move or make any sound, not even the I-don’t-have-enough-power clicking noise. (I would use AAs as you suggested but I don’t currently have a holder for them.)

I also tried connecting a common ground to the Arduino earlier with the servo powered by the USB battery bank, still didn’t work.

As for those buttons, I am using the internal pullup resistors of the Uno as detailed in Arduino’s article about constants (Here!).

Because it didn’t work with another power source, that would make me think that the servo is bad, but then why did it still work once or twice?

I did open up the servo. I measured 5v coming in right where it should. I tried applying 5v to the motor and it did turn, so that hasn’t burned out. None of the components on the board appear damaged in any way.

I still have no idea what is happening. Unless anyone has a better idea I will probably just take out that servo and replace it with another.

(deleted)

bobdathud:
Here's an image of the circuit diagram.

Please make your image visible in your Post. See this Simple Image Posting Guide

...R

Here is that image again, I tried to embed it in the post but it didn't work for some reason last time.

Also, this is called a circuit diagram, right? I might be using the wrong term for that, if so, sorry. :slight_smile:

(deleted)

701511 with ground.PNG