8

When I started Arduino, I did not expect that everything must be contained in an infinite loop. I thought I could just write something like: motor start -> motor stop. But in actuality, what I get is motor start -> motor stop -> motor start -> ... forever and ever.

What is commonly done to stop a servo after it is in a desired position? Do I use servo.write(desired position) to keep it from turning? Do I detach the output wire?

What are some of the risks involved?

1
  • Could also be that you've got a continuous rotation servo, where 0 is full speed in one direction, 90 is stop, and 180 full speed in the other direction.
    – Blee
    Oct 28 at 18:38

7 Answers 7

15

You do not "stop" a servo.

A servo is always running. In a general sense, the servo is a control loop that takes as input a position target and applies force to hold at the requested target. If you want the target to be maintained, then the servo must be running.

A servo motor contains electronics that are internally turning a DC motor on and off as necessary to hold the target position. If the target does not match the current position, it turns on the motor to turn until the two match. Once the output shaft reaches what you requested, the electronics inside the servo motor turn the motor "off". Off meaning the DC motor is drawing little or no current. The servo control loop is always running comparing the shaft position to a target.

If you powered off the entire servo motor, the position is not under control and could move. For many applications if you unplugged the wires, the gears and motors apply enough friction that it would not turn. But in general, you do not count on friction to make things work.

Do I use...Servo.Write(desired position) to keep it from turning?

Yes. To tell a servo to stay at one position, you can just keep sending it the same target.

But you do not have to Write() again and again. If you want, you can keep track of what the last setting was and apply only when you have a change. For example, you can code like this:

if(position_target != position_last_set) {
  Servo.Write(position_target);
  position_last_set = position_target;
}  

Regardless of your code, under the hood, Servo is constantly transmitting the position target to the servo motor.

1
  • A servo can use a considerable amount of current trying to hold position when a rotational load is applied to the output shaft.
    – linhartr22
    Sep 9, 2016 at 0:31
9

A normal servo doesn't have a "go" function, it only has positional control. That is, whether you run servo.write(90) forever or once, the servo will go to 90 and continue to actively keep that position until you write another position. The only way to turn a servo off is:

servo.detach();

For a normal DC motor, you will need to turn it on then off and then have kind of state tracking in the loop to never turn it on again, using a variable or millis() etc.

Of course, if you want something to only run once, put it in setup() (maybe within a loop in setup for simple tasks).

Also, you can simulate ending the program by entering an infinite loop with while(true){} or for(;;){}.

2
  • Yes, the problem seems to be with the misfit of the arduino loop paradigm with the application rather than anything specific to do with the servo - and the solution could indeed be preventing the arduino main loop from looping by putting another infinite loop to trap execution before the end of it. Or, in a more complicated system, by watching for some external condition and performing a sequence of operations only once in response to that. Sep 8, 2014 at 19:30
  • 2
    Feh, I don't see what's misfit about it. If you want it to stop you have options as above. And why bother with a microcontroller if you're just going to do one simple thing and stop? What does it do then? Run down the battery?
    – sdcharle
    Dec 17, 2015 at 2:35
6

myservo.detach(); is what you are looking for. Moving it to a location than detaching. This is good when you want to use it to control a servo and not have it continue to take power like when using a battery. Here is a example.

#include <Servo.h>
Servo myservo;  // create servo object to control a servo

void setup() {
  myservo.attach(9);
  // attaches the servo on pin 9 to the servo object
}

void loop() {
  myservo.attach(9);
  // attaches the servo on pin 9 to the servo object
  delay(15);
  myservo.write(1);
  // sets the servo position according to the scaled value
  delay(1000);
  // waits for it to get to the position
  myservo.detach();
  delay(1000);
  myservo.attach(9);
  // attaches the servo on pin 9 to the servo object
  delay(15);
  myservo.write(179);
  // sets the servo position according to the scaled value
  delay(1000); // waits for it to get to the position
  myservo.detach();
  delay(1000);
1
  • do you have to delay before detach? i haven't done that and never have problems with the servo reaching the position. thus im guessing once the servo pwm signal is sent it is sent and you can move on.
    – Alex
    May 14, 2017 at 5:11
3

The word servo has a vague definition and can encompass many types of subcomponents. If you want no-power position holding using an electromagnetic motor, then there are four options:

  • High viscosity grease
  • Dash pot
  • Very high gear ratio
  • magnetic brake shoe / brake band

EDIT: There are some additional possibilities, but it's sort of an effect of some motor designs:

  • Permanent magnet pole holding torque, or detent torque
  • Permanent magnet drag torque

 

The high viscosity grease and dash pot have similar functions; providing a high static friction to resist motion, which then breaks away into movement. (A dash pot is essentially a toothed gear inside a toothed wall container, and which is permanently filled with a high viscosity fluid.)

However both of these will add to the motor load, and when they get hot they tend to become thin and runny and lose holding ability.

 

A high gear ratio increases the torque required to back-spin the motor. Though note, if any gearbox could have a perfectly frictionless lubricant, no amount of gear reduction could stop back-spinning.

So really this is similar to the thick grease and dash pot, but gear reduction allows just the normal thin lubrication to have enough static breakaway friction, to stop back-spinning.

 

A magnetic brake gives you active control over the static breakaway friction, and can allow for very high holding ability vs intermittent load spikes on the output shaft. Typically with the power off, a spring engages the brake to hold position with no power.

Note, there are two different kinds of braking: static position holding, and deceleration of a moving mechanism.

The second type both dumps heat into the brake pads and friction plate, and wears down the pads and friction plate. If the brake overheats, the pads usually disintegrate, and the brake now won't hold position.

Unless we're talking about large machinery, usually servo brakes are simple designs without replaceable parts. When the brake fails, you pull the whole thing off and replace it ... including possibly the entire servomotor and gearbox too.

For long service life with magnetic braking, you need to actively decelerate the load using the servo, and then once it has stopped moving, then engage the brake to just do the job of holding position.

 

Using a magnetic brake for no-power static load holding only, will look like this:

  • Power up motor, get current position, and begin actively holding position.
  • Energize brake to release it
  • Accelerate and move to new position
  • Decelerate motor and hold end position
  • Remove power from brake to engage it
  • Turn off power to motor

The motor is powered up and goes into position holding first, so that the load doesn't suddenly slip in either direction, in the instant between the brake being released and the servomotor then becoming active.

 

EDIT #1: For some permanent magnet motors, even with the power off there is a resistance to rotation because in certain positions, the magnets and the pole pieces more closely attract to each other, known as detent torque.

This pole positioning is like a low-energy valley and it takes a bit of force to overcome the magnetic attraction and move the rotor in either direction using an external torque.

You can feel this in some brushless fans and stepper motors, where if you rotate the shaft unpowered, it resists continuous motion, and there seem to be high resistance points that the rotor does not want to cross. When spun, the rotor rapidly slows, and may fall into a back-forth oscillation as it settles into one of the magnetic attractive wells.

This can be used to resist external torques without a brake, but making use if it requires stopping the rotor in one of the magnetic wells rather than a specific position you may want. But if combined with a gearbox, the exact specific stopping position may not matter too critically, and there may be a number of wells next to each other where the rotor can stop that provide an acceptable end-effector alignment.

 

EDIT #2: Permanent magnet drag torque is an effect of shorting all the power wires together. When this is done it takes considerably more force to rotate the shaft than with the stepper coil wires disconnected from each other.

This is because with the coil wires all connected together, when the rotor turns it acts as a generator and current flows through the coils. This current flow creates what is known as counter electromotive force (CEMF), which counters the magnetic field of the permanent magnet.

This CEMF can provide additional resistance against rotation when the servo is unpowered. Although CEMF won't prevent motion, it can help resist continued motion and provide instant deceleration when intermittent load spikes are applied that try to move the unpowered servo.

 

All of the above is also generally true for linear motor servos. Those don't have gear reduction, but the motion carriage can be lubed with thick grease, be equipped with a dash pot, and have position holding magnetic brakes.

2

I had the same problem.

I figured out that simply adding myservo.write(90); delay(4000); helps to stop motor.

#include <Servo.h> 

Servo myservo;  // create servo object to control a servo 
                // twelve servo objects can be created on most boards

int pos =0;    // variable to store the servo position 

void setup() 
{ 

  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
} 

void loop() 

{ 
  myservo.write(180);             
    delay(8000); ////stops motor for 8 seconds 
  for(pos = 180; pos>=90; pos-=1)// goes from 180 degrees to 0 degrees
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15); // waits 15ms for the servo to reach the position 

  } 

    myservo.write(90);              
    delay(4000); //stops motor for 4 seconds   
  for(pos = 90; pos <= 180; pos +=1) // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15);      // waits 15ms for the servo to reach the position

  } 

} 
1
  • i had the same problem i figure out that simply adding myservo.write(90); delay(4000); //stops motor for 4 seconds this helps to stops motor
    – kale
    Dec 23, 2014 at 4:50
2

This is a very brief explanation regarding servos.

The type of servo system that you are proposing is a none positional open loop system and is generaly used for accurate movement rate (controlled speed) . The loop in this case is usually a tachogenerator which sends a voltage (which is proportional to the motor speed) to a comparator which compares the tachogenerator voltage to the required adjustable voltage , the output of the comparator then regulates the motor speed, hence the required speed . this type of servo system will continue to run at the constant speed until A the comparator signal is set to zero or B the motive power is reremoved from the moter ( switched off) ----Point to point servo control , on the other hand ,, generally uses a position command which is verified with a signal from an encoder at which point the servo will stop until another command is issued from the stack ( EG. another position location or a dwell command (wait) or other ) the most common way to do this is to use gcode which has the ability to give full control of your servo system . If there is no encoding device then accurate servo position control is very difficult if not impossible.

1

A servo, by nature, is used to hold a position in the presence of disturbances trying to disturb that position. If you just need to move a mechanism that won't try to (or can't) back-drive the motor, your application ay be better served by a geared motor with a shaft encoder or position switches.

3
  • Hobby servos are mostly used because they are cheap and abstract out the problem and are not disturbed by typical loads. Applications with forces that can backdrive the normal variety may be approaching overloading them anyway (some of the high performance servos have internals wguch are more easily backdriven when off - even by the weight of control surfaces on large models). Dec 23, 2014 at 14:39
  • @ChrisStratton: I know that the hobby servo can offer a block-box solution in a lot of cases, but my point is that a servo is always active, and if that is undesirable, as implied in the question, another technique may have an advantage.
    – JRobert
    Dec 23, 2014 at 16:46
  • No, a hobby servo is not always active - if it is not passively sitting in its deadband (comparator satisfied so motor off) or moving to a distinct new position, it has probably been misapplied. Continued audible action means that either the servo is faulty (common in the $3 class), the linkage binding, or the load excessive. Dec 24, 2014 at 10:28

Not the answer you're looking for? Browse other questions tagged or ask your own question.