3
$\begingroup$

I need to use continuously rotating servo for a camera stabilization system. My professor bought servos that have already been modified for continuous motion--there's no stop in the gears, and the potentiometer allows it to spin 360+ degrees.

I am currently using PWM with an Arduino Uno. The servo does spin continuously, but not in a stable way. I've also taken out the potentiometer in another one of the servo, and on a third servo I used a voltage divider in place of the potentiometer.

I've tried static values and a "sweep" from 0% duty cycle to 100% to get a feeling for how they work, but I just cannot figure it out. I greatly would appreciate any tips on this.

Here is my code:

 //PWM test for continious motion Servo

 int servoPin = 9; // connect servo to pin 10
 int pwmVal = 0; // declare pulse width modulation value

void setup(void) {
  pinMode(servoPin, OUTPUT); //set up the servoPin as an output pin
  Serial.begin(9600); // begin serial monitor
}

void loop(void) {

  //for loop that sweeps values from 0 to 255
  for (pwmVal = 0; pwmVal <= 253; pwmVal += 1) {
    analogWrite(servoPin, pwmVal);
    Serial.println(pwmVal);
    delay(100);
  }
  for (pwmVal = 253; pwmVal >= 0; pwmVal -= 1) {
    analogWrite(servoPin, pwmVal);
    Serial.println(pwmVal);
    delay(100);
  }


  //assign a static pwm value
  pwmVal = 0;
  analogWrite(servoPin, pwmVal);
}
$\endgroup$

5 Answers 5

2
$\begingroup$

I believe by continuous rotation servo you mean servos similar to TowerPro MG-995 or Winch Servo HS-785HB. For such servo, the normal Arduino code for servo motors won't work. You have to define

#define MAX_PWM 2150
#define MID_PWM 1500
#define MIN_PWM 850

...

void setup() 
{ 
  myservo.attach(9);
  myservo.writeMicroseconds(1500);  // set servo to mid-point  
}

...

Also you need to use .writeMicroseconds(pwm_in_us) API instead of .write(pwm) API. The difference between the mid value (i.e. 1500) and the user defined value will give you the desired rotation.

For values greater than 1500us, the servo will rotate in CCW direction (if I am not wrong) and for values less than 1500us it rotates in CW direction.

$\endgroup$
3
  • $\begingroup$ What is the difference between using .write() and .writeMicroseconds()? They both seem to work for me, but I want to understand. $\endgroup$
    – Mark Good
    Mar 4, 2020 at 7:49
  • $\begingroup$ @MarkGood The difference is in the argument you pass. Angle is passed with .write() for e.g. .write(180) will rotate the servo by 180 degrees and time in ms is passed with .writeMicroseconds(). For e.g. .writeMicroseconds(2000) will rotate for 2 seconds $\endgroup$
    – ron123456
    Apr 15, 2020 at 9:37
  • $\begingroup$ hmm... this isn't right. .writeMicrosoeconds(2000) makes the servo rotate continuously at a specific speed. Turns out that the microseconds is the speed at which the pwm pulses, which controls the direction and speed of the servo. $\endgroup$
    – Mark Good
    Apr 16, 2020 at 12:58
1
$\begingroup$

If your servos are just regular servos modified for continuous rotation, the way to control them is to send a 50Hz PWM signal (20ms period) with a high level time between 1ms (full left) and 2ms (full right). You can use the Servo arduino library, which is very easy to use.

Then, Lets assume the servo potentiometer is approximately set to what should be the middle position for the servo.

For continuous rotation to the left, just write myServo.write(0). The servo will rotate to the left, but since the potentiometer is disconnected from the servo's head, it will never reach the good value, so the servo will keep turning.

To go to the right, use myServo.write(180).

Stopping the servo might be harder, since you have to find exactly the current position of the potentiometer, but you should manage to do it by several trials.

 #include "Servo.h"
 int servoPin = 9; // connect servo to pin 10
 myServo = Servo();

void setup(void) {
  myServo.attach(servoPin);
  Serial.begin(9600); // begin serial monitor
}

void loop(void) {
    myServo.write(0);
    Serial.println("going to the left!");
    delay(2000);

    myServo.write(180);
    Serial.println("going to the right!");
    delay(2000);
}
$\endgroup$
1
  • $\begingroup$ How I can use this code for servo motor contusions rotation This code for servo motor 180 degrees. As same purposes? $\endgroup$
    – Abuwesam
    Sep 16, 2019 at 10:38
0
$\begingroup$

Doing a sweep across a range of PWM value will not results in a continous motion, since the delay times between the different vales are not correlated with the time required for the servo to arrive to the given position.

Depending on how the motor functions:

I suggest you only give 2 commands, the minimum PWM value and the maximum PWM value. This should do a complete rotations continously, if the duty cylcle of your PWM is proportional to the position of the motor.

If your motor has been modified and the pwm duty cycle is not proportional to the position of the motor, but to its velocity, then a constant PWM duty cylce should rotate the motor with a constant velocity.

Also please increase delay times to a few seconds in both cases to make sure that the motor has enough time to execute the commands.

$\endgroup$
0
$\begingroup$

I have a gut-feeling that the question cannot be answered without the details of the motors. I see that analogWrite() is being used along with a delay of 0.1s . In Arduino, analogWrite() is a PWM itself running at about 490Hz/980Hz and additional delays may not be necessary. Servos generally use 1 milli-second to 2 milli-second 50 Hz PWM as mentioned in this description https://learn.sparkfun.com/tutorials/pulse-width-modulation . Servo motors use feedback and internal softwares most of the times - http://www.electronicshub.org/servo-motors/ . So, it is better to use Arduino Servo Library and program using 'servo angles' like this: https://learn.adafruit.com/adafruit-arduino-lesson-14-servo-motors/arduino-code-for-sweep .

$\endgroup$
0
$\begingroup$

I can control a normal servo by the esp8266 module. Where I can rotate servo continuously and stop any time by Blynk application. As you mentioned Arduino board to control the servo you may modify my code to run by Arduino. Here I am giving my code below.

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Servo.h>
int pwmVal;

Servo servo;

char auth[] = "UjMplBC1-vDSgd79iL53O_p5f-3YngaA";
char ssid[] = "...";
char pass[] = ".......";

void setup()
{
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);
  servo.attach(15); // NodeMCU D8 pin
 }

void loop()
{
  Blynk.run();
}

 void cradle() {

  //for loop that sweeps values from 0 to 255
    pwmVal=8;
    analogWrite(15, pwmVal);
    Serial.println(pwmVal);
    delay(100);
  
  pwmVal = 0;
  analogWrite(15, pwmVal);
 }


BLYNK_WRITE(V1) 
{
  int Value = param.asInt();
  if (Value == 1) {    // if Button sends 1
    cradle();             // start the function cradle
    int Value = 0;  // Set V1 status to 0 to quit, unless button is still pushed (as per below)
    
    Blynk.syncVirtual(V1); // ...Then force BLYNK_WRITE(V1) function check of button status to determine if repeating or done.
  }
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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