Search code examples
arduinoservo

My Servo is Not Moving, Only When Trying Write 180 degrees


My servo only starts to "change" (that is what the code tells me anyway) when it is set for 180 degrees.

I've tried searching the website as well as Google, but this seems to be something that has to do very specifically with writing to Servo in an advanced non-repeatable kind of way.

The code that changes the servo is:

#include <SoftwareSerial.h>
#include <Servo.h>

const int rxPin = 12;
const int txPin = 13;
SoftwareSerial bluetooth (rxPin, txPin);

Servo myServo;
boolean canMove = true;

int rotation = 0;
int currentRotation = 0;

void setup() {
  Serial.begin(9600); // Begins Serial communication
  bluetooth.begin(9600);
  myServo.attach(11); // Sets a servo on pin 11  
}

void loop() {
  // put your main code here, to run repeatedly:

  // Checks if Serial has something to read
  if (bluetooth.available() > 0) {
    rotation = bluetooth.read(); // Reads it and sets it to an integer
  }

  currentRotation = myServo.read();

  if (currentRotation != rotation) {
    Serial.println("Current Rotation:");
    Serial.println(currentRotation);
    Serial.println("Set to:");
    Serial.println(rotation);
    for (int i = currentRotation; i < rotation; i++) {
      Serial.println("Writing to servo");
      myServo.write(i);
    }  
  }

}

There is a Processing program that sends the data to the Arduino, but I can perfectly see that the numbers are coming in in the Arduino's Serial Monitor (they vary from 0 to 180)

After doing this the only thing that shows up in the Serial Monitor is:

Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0
Current Rotation:
93
Set to:
0

over and over. The servo just twitches back and forth. The only time it changes (the number to set to comes from the Processing program) is when the number it is set to be 180. Then it moves even more back and forth and says:

Current Rotation:
179
Set to:
180
Writing to servo
Current Rotation:
179
Set to:
180
Writing to servo

over and over. What is going on and how can I fix it? Cheers, and thanks for the help!


Solution

  • There are some problems with your code:

    1. You don't need to read current servo value, just save the last gave value.

    2. Moving a servo step by step is not a good option as it may have some error for movement. You need to find a dynamic delay based on a threshold of movement. For example, suppose that your max delay time for the servo to fully move from 0 to 180 is 2 seconds, so if you need to move the servo for 90 degrees you need 1 second delay.

    3. You just need to move your servo when a new data came so set servo when new data comes.

    Remember to set max_delay based on your servo.

    #include <SoftwareSerial.h>
    #include <Servo.h>
    
    const int rxPin = 12;
    const int txPin = 13;
    SoftwareSerial bluetooth(rxPin, txPin);
    
    Servo myServo;
    boolean canMove = true;
    
    int rotation = 0;
    int currentRotation = 0;
    
    // how much time takes servo to move
    int move_delay = 0;
    // maximum time for changing servo state from lowest to highest value
    const int max_delay = 2;
    
    void setup()
    {
        Serial.begin(9600); // Begins Serial communication
        bluetooth.begin(9600);
        myServo.attach(11); // Sets a servo on pin 11
    }
    
    void loop()
    {
        // put your main code here, to run repeatedly:
    
        // Checks if Serial has something to read
        if (bluetooth.available() > 0)
        {
            rotation = bluetooth.read(); // Reads it and sets it to an integer
    
            Serial.print("New value: ");
            Serial.println(rotation);
            Serial.print("Current Rotation: ");
            Serial.println(rotation);
            if (currentRotation != rotation)
            {
                Serial.println("Setting new value");
                // find a proper delay
                move_delay = (max_delay / 180) * (abs(rotation - currentRotation)) * 1000;
                myServo.write(rotation);
                delay(move_delay);
                currentRotation = rotation;
            }
        }
    }