Not getting consistent servo movement with Arduino UNO

I need a spray bottle to spray twice a day at set intervals for a crested gecko habitat. I put my code together to turn a servo from the 0 degree position back to the 150 degree position, and then back to the 0 degree position in order to pull the spray bottle trigger back and then release it; but the code only works about once or twice at best before it fails. It rarely sprays the correct number of times and its timing is all wrong quite often. It has worked properly on its own a few times; but the vast majority of the time it fails.

It is just inputting servo movements with delays in between. I looked into millis() instead; but it was way over complicated and the code should be compatible with blocking. Also, this should be running for far longer than 50 days; so millis() won’t work for my application. The code can be viewed below:

/*
Arduino Servo Test sketch
*/
#include <Servo.h>
Servo servoMain; // Define our Servo

void setup()
{
   servoMain.attach(10); // servo on digital pin 10

}

void loop()
{
   /*
   // Start night time spray of 12 sprays at ~8pm
   */
   /* Start servo position at 0 degrees */
   servoMain.write(0); // Turn Servo back to center position (0 degrees)
    /* Spray 1 */
   delay(2000);          // Wait 2 seconds
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);   // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 2 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0); // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 3 */
   servoMain.write(150); // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);  // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds 
    /* Spray 4 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);   // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 5 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0); // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 6 */
   servoMain.write(150); // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);  // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 7 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);   // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 8 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0); // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 9 */
   servoMain.write(150); // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);  // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds 
    /* Spray 10 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);   // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 11 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0); // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 12 */
   servoMain.write(150); // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);  // Turn Servo back to center position (0 degrees)
   delay(50374400);          // Wait 14 hours (minus 25.6 seconds of spray time) OVERNIGHT to ~10am
   /*
   //Start day time spray of 6 sprays
   */
    /* Spray 1 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);   // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 2 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);   // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 3 */
    servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);   // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 4 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);   // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 5 */
    servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);   // Turn Servo back to center position (0 degrees)
   delay(2000);          // Wait 2 seconds
    /* Spray 6 */
   servoMain.write(150);  // Turn Servo Left to 150 degrees
   delay(2000);          // Wait 2 seconds
   servoMain.write(0);   // Turn Servo back to center position (0 degrees)
   delay(35974400);          // Wait 10 hours (minus 12.8 seconds of spray time) to ~8pm 
}

this should be running for far longer than 50 days; so millis() won't work for my application.

It will if you write it correctly
See Using millis() for timing. A beginners guide, Several things at the same time and look at the BlinkWithoutDelay example in the IDE.

Please post your code here, using code tags when you do.

How is the servo powered? Powering a loaded (working) servo from the Arduino 5V regulator can cause dips in the 5V power resulting in odd behavior. Power the servo from an external supply like a 5V phone charger or 4 AA battey pack.

groundFungus:
How is the servo powered? Powering a loaded (working) servo from the Arduino 5V regulator can cause dips in the 5V power resulting in odd behavior. Power the servo from an external supply like a 5V phone charger or 4 AA battey pack.

That would make a lot of sense. So, in my case do I only want the signal wire coming from the servo to the Arduino; and then have the power and ground going to a 5v phone charger?

Thanks for your reply!

UKHeliBob:
It will if you write it correctly
See Using millis() for timing. A beginners guide, Several things at the same time and look at the BlinkWithoutDelay example in the IDE.

Please post your code here, using code tags when you do.

My code is now posted. Thanks for your reply. If I can make it work with delays I would prefer it only because I don't need to multitask and this is my first Arduino project. I'm very new and millis went over my head when I tried to use it. I don't have a lot of time available to devote to this now and I'd like to get it working asap; but I will take a look at the section you referenced so I can possibly implement this method in future projects as I get more Arduinos. Thanks for your reply!

The external supply positive goes to the servo positive supply, servo signal to an Arduino output and the negative side of the external supply to the servo negative supply (servo ground) and also to the Arduino ground.

delay(35974400);          // Wait 10 hours (minus 12.8 seconds of spray time) to ~8pm

You came up with that number by yourself? Why not let the compiler calculate it for you?

const unsigned long usualSprayTime = 12800; //milliseconds
const unsigned long waitTime2 = 10; //hours
delay(waitTime2 * 60 *60 * 1000 - usualSprayTime);

You could extend this by making those constants calculate from the other delays you used elsewhere.

If it is important that this event occurs at exactly 8pm and does not slip by more than a few minutes per year then you must use another time source, such as an RTC (real time clock) chip. The Arduino's clock which sits behind millis() and delay() will slip by minutes per day and will be completely wrong in a month or two. But the spray events will still occurr 14 hours and 10 hours apart.

MorganS:
You came up with that number by yourself? Why not let the compiler calculate it for you?

const unsigned long usualSprayTime = 12800; //milliseconds

const unsigned long waitTime2 = 10; //hours
delay(waitTime2 * 60 *60 * 1000 - usualSprayTime);




You could extend this by making those constants calculate from the other delays you used elsewhere.

If it is important that this event occurs at exactly 8pm and does not slip by more than a few minutes per year then you must use another time source, such as an RTC (real time clock) chip. The Arduino's clock which sits behind millis() and delay() will slip by minutes per day and will be completely wrong in a month or two. But the spray events will still occurr 14 hours and 10 hours apart.

Thanks so much, that's great info! I did not know I could have that auto calculated. This is ok to slip in time as long as the time between stays constant. I appreciate your reply :slight_smile:

groundFungus:
The external supply positive goes to the servo positive supply, servo signal to an Arduino output and the negative side of the external supply to the servo negative supply (servo ground) and also to the Arduino ground.

I did this according to your recommendation and I tried it with a 5V phone charger first and then with a 8V wall charger. Both power supplies appeared far too weak to move the servo the full 150 degrees of movement that the code instructs it to. It moved more freely when it was wired directly into the Arduino; but it does appear to follow the code instructions now more accurately in terms of the number of sprays it attempts. So, there appear to be improvements. Any idea why a 5V & 8V power supply would both fail to power it as strong as the Arduino direct connection did? I am using this servo: TowerPro MG995 Digital Servo

Thanks again for your help!

What is the current rating on those two power supplies?

8V is higher than the servo is rated for. It is probably OK but I would worry that it might burn itself out with that kind of power.

MG995s are quite power-hungry but they need plenty of current not excessive voltages. Try powering the servo with something like 4 or 5 x AA NiMH rechargeable batteries or a 6V power supply that provides at least 2A.

Steve

MorganS:
What is the current rating on those two power supplies?

8V is higher than the servo is rated for. It is probably OK but I would worry that it might burn itself out with that kind of power.

Thanks, I was iffy about the 8V power supply and i only tried it once. The other power supplies I tried were all 5V and the 3 I tried had amp ratings of 100 mA, 500 mA, and I even tried a dash charger that was rated at 4 amps.

100mA and 500mA are both far too low. As I said previously you need at least 2A from a solid 5V supply like 4 NiMH AA cells.

Unfortunately the "dash charger" isn't right because it produces a undefined higher voltage and relies on additional circuitry in the phone/device being charged to sort it out so you may have already done some damage.

Steve

slipstick:
100mA and 500mA are both far too low. As I said previously you need at least 2A from a solid 5V supply like 4 NiMH AA cells.

Unfortunately the "dash charger" isn't right because it produces a undefined higher voltage and relies on additional circuitry in the phone/device being charged to sort it out so you may have already done some damage.

Steve

:frowning: well that sucks. Guess I'm learning the hard way here. I suppose that's to be expected when I jump in blind with both feet into an unknown territory. Do you think this one is a good power supply?

smile.amazon.com/ICV-USB-Wall-Charger-Lightweight/dp/B0119BUJDQ/ref=sr_1_5?keywords=5+volt+2+amp&qid=1560814134&s=gateway&sr=8-5

I was thinking about trying this one out and if it still doesn't work then purchase a replacement servo. If I accidentally ran the positive power from the 2nd power supply to the arduino along with it being plugged in, do you think the arduino may be damaged as well? ...Man I feel like a blithering idiot over here.

slipstick:
100mA and 500mA are both far too low. As I said previously you need at least 2A from a solid 5V supply like 4 NiMH AA cells.

Unfortunately the "dash charger" isn't right because it produces a undefined higher voltage and relies on additional circuitry in the phone/device being charged to sort it out so you may have already done some damage.

Steve

I think you are probably right about the damage done unless the 5V 2A plug I got still isn't powerful enough. I got the one from the link above and it isn't rotating the servo with nearly enough force. It tried to move it a bit and then there is a high pitched whine while it is trying to move the servo. I'm ordering a replacement servo and will see if that fixes it. I sure hope this thread helps someone from going through what I am dealing with here! :slight_smile: Thanks to everyone for your help and feedback and guidance.

I received the 5v 2A power supply above and it still didn't work. I tested the output and it is only outputting 1 amp :frowning:

I am returning it and looking for another power supply. What is the max I can use on this servo? Does anyone know of a reputable seller for these who isn't going to sell me one that doesn't meet its spec?

For a servo the voltage is important. If powered with the right voltage the servo will pull only the current that it needs (if the supply is capable of supplying the current).

It would be a good idea to buy something marketed as a POWER SUPPLY not as a CHARGER. They're not the same thing.

Provided is it 5V you can get one that is able to supply any amount of current (2A or more). Even if it COULD supply 100A the servo will still only take what it needs.

Steve

Thank you slipstick & groundFungus! I purchased an actual power supply as recommended that is rated for 6V 3A DC. When I check it with the multimeter I'm not getting any readings for V or A. I can check other power supplies and get readings like I would expect. So, I'm thinking this might be DOA; but can't try it out to be sure because I'll have to destroy it to check in my application.

My question is a point of clarification (thank you both for your patience and help with this!). Let's pretend this 6V 3A power supply isn't DOA. Would you guys expect this to have enough voltage and amperage to power the servo in question? Also, why do many of my power supplies on hand read a lower amp setting on my multimeter than they sticker on the unit says they output? Is this because there isn't a source pulling the max amps through?

After getting the replacement 6V 3A power supply, everything is now working; so it definitely was a lack of power. Thanks so much guys for your help! Although, with the 1st power supply being DOA and this replacement one getting super hot within a minute of being plugged in I'm now skeptical about this power supply's safety. Any recommendations on a quality power supply that outputs 6V 3A?