one full rotation of servo

I am having some trouble getting a servo to do a repeatable 360 rotations, no matter what value I give to “var” the servo never stops at the same point.

#include <Servo.h>
Servo myservoY;
Servo myservoX;

int potpinY = 612;
int potpinX = 512;
int Ytimer = 0;
int Xtimer = 0;
int valX = 0;
int valY = 0;
int var = 0;

void setup()
{
  myservoY.attach(5);
}
void loop()
/*Do one 360 degree rotation and stop*/
{
  if (var < 100) { 
    var++;
    Ytimer = potpinY;
    Ytimer = map(Ytimer, 0, 1023, 0, 180);
    myservoY.write(Ytimer);
    delay(18);
  }
  else 
/*Now stop rotation */
  {
    valY = 512;
    valY = map(valY, 0, 1023, 0, 180);
    myservoY.write(valY);
    delay(18);
  }
}

I am having some trouble getting a servo to do a repeatable 360 rotations

  • I guess you’re using a ‘continuous-rotation’ servo. There’s no way to set it to move any exact number of turns, or fraction thereof.
    Edit: And your comment and the thread title don’t say “360 rotations”:- “/Do one 360 degree rotation and stop/”

So your code maps 612 to a value between 0 and 180, then writes it to the servo 100 times, every 18mS.

Then, in an equally confusing way, it stops the servo.

There’s nothing to make the servo stop in exactly the same position each time. You’d need feedback from an external sensor for that. Timing isn’t enough.

a frequent error when servo do not achieve what's expected it's often due to being underpowered

but here I'm having a tough time understanding what you are trying to do...

the loop will go in the first part of the if 100 times (as you increase var) then because potpinY is a static number that never changes (612) you set Ytimer to 612, which you map to 107 and then you ask your servo to move to this 107° angle and wait 18ms.

as you do that 100 times, your code basically asks 100 times your servo to go to angle 107 and then var is larger than 100 so you enter the else statement at every loop and there you set the angle at 90° all the time.

so behavior you should see is: servo moving to 107° for 1,8seconds and then to 90° forever

How do you expect this to do any 360°?

J-M-L:
so behavior you should see is: servo moving to 107° for 1,8seconds and then to 90° forever

My assumption, which may be wrong, is that it's a continuous-rotation servo, in which case any value larger or smaller than 90 sets speed in one or the other direction, then 90 stops it.

OldSteve:
My assumption, which may be wrong, is that it’s a continuous-rotation servo, in which case any value larger or smaller than 90 sets speed in one or the other direction, then 90 stops it.

OK - if that’s the case then, on a continuous rotation servo, this will indeed set the speed of the servo. 0 being full-speed in one direction, 180 being full speed in the other, and a value near 90 being no movement - the 107 values means an ask to spin at ~60% of max speed in a given direction for roughly 1.8 seconds and then stop spinning.

@Gates - can you clarify which servo do you have?

the 107 values means an ask to spin at ~60% of max speed

How do you figure 60%?

J-M-L:
the 107 values means an ask to spin at ~60% of max speed in a given direction for roughly 1.8 seconds and then stop spinning.

Not 60%. About 19%. (17/90) (Which AWOL also just said as I was typing. :slight_smile: )

@Gates - can you clarify which servo do you have?

Yes, please. :slight_smile:

AWOL:
How do you figure 60%?

with quick and bad math :slight_smile:

I did 107/180 which of course is wrong because the should have done 17/90 instead so ~19% of the max speed

good eagle eyes catch (as always)

What I was pointing-out was that I don't think you can calculate any particular value to the speed - it'll depend on the individual ex-servo.
That's been my experience anyway.

AWOL:
What I was pointing-out was that I don’t think you can calculate any particular value to the speed - it’ll depend on the individual ex-servo.
That’s been my experience anyway.

That too. I should have said 19% of the max speed setting, not 19% of the max speed. Even my store-bought continuous rotation servos aren’t linear in speed from 90 to 180 or 0. And the speed for a given setting varies noticeably from servo to servo, even servos of the same type.

Hello again,
OldSteve, the servo has been modified to do continuous-rotation. valY = 512; stops the servo from moving. The program is meant for two continuous servo's which a value of 512 + or- 3 stops both of them.

Edit: And your comment and the thread title don't say "360 rotations":- "/Do one 360 degree rotation and stop/"

Sorry my mistake. At the moment I only want the servo to do a single 360 degree rotation and stop.

a frequent error when servo do not achieve what's expected it's often due to being underpowered

the servo is underpowered, and the results are slightly different at full power.

There's nothing to make the servo stop in exactly the same position each time. You'd need feedback from an external sensor for that. Timing isn't enough.

Yes I realize that now. Would using pinmode to set an active low on a digital pin increase the timing?

So you need to pick a sensor which can detect the position where you wish to stop. A simple switch is often good enough - look for a “microswitch” type. But a hall effect or optical sensor is usually better. There’s no moving parts to wear out.

Gates:
Would using pinmode to set an active low on a digital pin increase the timing?

I don't understand what you mean here:- "increase the timing?"

To stop the servo, writing 90, (adjusted for the particular servo), is all you need. Same goes for setting speed. Just write a value. A lthough you now know it's not possible to get it to stop in the same position each time without position feedback, if you did want it to run anticlockwise at a speed equivalent to 107 degrees for 1.8 seconds, all you needed was:-

myservoY.Write(107);
delay(1800);
myservoY.write(90);  // Adjusted slightly to actually stop the servo.

For higher speed resolution, or positioning resolution using a standard servo, you can also use writeMicroseconds(). (There's probably not much point in a C-R servo though. The speed control is pretty pissy even at the best of times as mentioned earlier.)

MorganS mentioned the usual method of stopping the servo in the same position each time.
~~Another method is to hack into the servo and connect a fourth wire to the internal pot's wiper, for position feedback. Either Adafruit or Sparkfun sell a servo with that modification already done. (I can't remember which.)~~Edit: Just a brain fart. Only useful with standard servos, not C-R servos, of course.

Hi OldSteve,

I just soldered a wire to the pots wiper.

method is to hack into the servo and connect a fourth wire to the internal pot's wiper, for position feedback.

I didn't think that I would see any changes on the wiper pin. The voltage with servo stopped was around 1.535. I noticed that the wiper pin changed in a range of about 1.625 (not sure about this result was not repeatable) the voltage was usually about 1.575 to 1.583.

Gates:
Hi OldSteve,

I just soldered a wire to the pots wiper. I didn't think that I would see any changes on the wiper pin. The voltage with servo stopped was around 1.535. I noticed that the wiper pin changed in a range of about 1.625 (not sure about this result was not repeatable) the voltage was usually about 1.575 to 1.583.

Oops, I was thinking of a standard servo, not a C-R type, for position feedback. My mistake. Sorry about that, I wasn't thinking. :frowning:
(An external sensor is needed. Again, sorry to waste your time.)

Hi OldSteve,

Servo/s I am using are standard servo type which have been modified to C-R (continuous rotation). The servo's are CEN 82108. I already cut off the post on the potentiometer before posting the question. I didn't think about feedback until now.

Oops, I was thinking of a standard servo, not a C-R type, for position feedback. My mistake. Sorry about that, I wasn't thinking. :frowning:
(An external sensor is needed. Again, sorry to waste your time.)

My mistake Steve. I didn't explain the problem completely to start with.

There's nothing to make the servo stop in exactly the same position each time. You'd need feedback from an external sensor for that. Timing isn't enough.

Thank you Steve

Gates:
My mistake Steve. I didn't explain the problem completely to start with.Thank you Steve

I don't like to argue, but it was my mistake, in saying you could get position feedback from a C-R servo by using the pot wiper for feedback. :smiley:
(I understood what you wanted, and made a silly blunder.)

Still, it's a good trick to remember for when using unmodified servos, to get position feedback without adding additional parts. :slight_smile:

Unfortunately, though, to do what you want you're stuck with having to add an external sensor of some sort, a mechanical switch, Hall-effect sensor or optical, (or something else I haven't listed). :frowning:

I was looking at this example to begin with as a switch to detected a full rotation of a servo. I believe that it is possible to move a servo by degrees, angle, or its position. In which case you are correct, I didn't explain in my first post about the reason I wanted to complete a single 360 degree rotation.

Badly coded to start with...as mentioned above.

Silly me. I am trying to get a 1000 of an inch measurement That's right 0.0254mm
Edit: before someone asks do you know what an inch is, Yes

/*
 Input Pullup Serial

 This example demonstrates the use of pinMode(INPUT_PULLUP). It reads a
 digital input on pin 2 and prints the results to the serial monitor.

 The circuit:
 * Momentary switch attached from pin 2 to ground
 * Built-in LED on pin 13

 Unlike pinMode(INPUT), there is no pull-down resistor necessary. An internal
 20K-ohm resistor is pulled to 5V. This configuration causes the input to
 read HIGH when the switch is open, and LOW when it is closed.

 created 14 March 2012
 by Scott Fitzgerald

 http://www.arduino.cc/en/Tutorial/InputPullupSerial

 This example code is in the public domain

 */

void setup() {
  //start serial connection
  Serial.begin(9600);
  //configure pin2 as an input and enable the internal pull-up resistor
  pinMode(2, INPUT_PULLUP);
  pinMode(13, OUTPUT);

}

void loop() {
  //read the pushbutton value into a variable
  int sensorVal = digitalRead(2);
  //print out the value of the pushbutton
  Serial.println(sensorVal);

  // Keep in mind the pullup means the pushbutton's
  // logic is inverted. It goes HIGH when it's open,
  // and LOW when it's pressed. Turn on pin 13 when the
  // button's pressed, and off when it's not:
  if (sensorVal == HIGH) {
    digitalWrite(13, LOW);
  } else {
    digitalWrite(13, HIGH);
  }
}

I have a MG996R motor and I need with a simple push of a button to make it rotate ONE full circle.
Is it possible to do it without an external sensor or switch but instead of that inside the code?

Is it possible to do it without an external sensor or switch but instead of that inside the code?

If it is a so called continuous rotation servo then no. You could rotate it for a fixed time but the angle that it turns through would not be accurate over time