Servo Direction Confusion

Can anyone give me a hand changing the direction of of a micro servo using servo.h ?

Currently 3 of my servos operate in the same direction. I needed to flip one of them 180 degrees for space reasons.

I tried flipping the values in the sketch for servoC but that didn’t work. Included is a rough drawing showing 3 of the 4 servos for reference.

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Servo.h>

#define ssid      "itwifi"
#define password  "mis5436133"

ESP8266WebServer server(84);

Servo myservoA;
int posA = 0;
int stateA = 0;
int prevstateA = 0;
int dircA = 0;
int servoPinA = D4;

Servo myservoB;
int posB = 0;
int stateB = 0;
int prevstateB = 0;
int dircB = 0;
int servoPinB = D5;

Servo myservoC;
int posC = 0;
int stateC = 0;
int prevstateC = 0;
int dircC = 0;
int servoPinC = D6;

Servo myservoD;
int posD = 0;
int stateD = 0;
int prevstateD = 0;
int dircD = 0;
int servoPinD = D1;


String webPage = "";

void setup() {
  Serial.begin(115200);
  delay(100);


  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  // Set a static IP (optional)
  IPAddress ip(192, 168, 1, 72);
  IPAddress gateway(192, 168, 1, 1);
  IPAddress subnet(255, 255, 255, 0);
  WiFi.config(ip, gateway, subnet);
  // End of set a static IP (optional)

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());


  webPage += "<BODY style='background-color:#0a88c2'>";
  webPage += "<h1 style=\"color:#FBFCFC; text-align:center\">Treats for Lincoln</h1>";
  webPage += "<hr/>";
  webPage += "<h3 style=\"color:#FBFCFC; text-align:center\">Quiet Time (AM)<p><a href=\"deliverA\"><button>Deliver</button></a>&nbsp;<a href=\"resetA\"><button>Reset</button></a></p>";
  webPage += "<h3 style=\"color:#FBFCFC; text-align:center\">Quiet Time (PM)<p><a href=\"deliverB\"><button>Deliver</button></a>&nbsp;<a href=\"resetB\"><button>Reset</button></a></p>";
  webPage += "<h3 style=\"color:#FBFCFC; text-align:center\">Cup Of Treats<p><a href=\"deliverC\"><button>Deliver</button></a>&nbsp;<a href=\"resetC\"><button>Reset</button></a></p>";
  webPage += "<h3 style=\"color:#FBFCFC; text-align:center\">Kong<p><a href=\"deliverD\"><button>Deliver</button></a>&nbsp;<a href=\"resetD\"><button>Reset</button></a></p>";
  webPage += "<hr/>";
server.on("/", []() {
  server.send(200, "text/html", webPage);
  });

  server.on("/deliverA", []() {
    server.send(200, "text/html", webPage);
    Serial.println("HTTP OPEN COMMAND RECEIVED");
    dircA = 0;  // direction for servo to run
    stateA = 2; // sets current state
  });

  server.on("/resetA", []() {
    server.send(200, "text/html", webPage);
    Serial.println("HTTP CLOSE COMMAND RECEIVED");
    dircA = 180; // direction for servo to run
    stateA = 1;  // sets current state
  });

  server.on("/deliverB", []() {
    server.send(200, "text/html", webPage);
    Serial.println("HTTP OPEN COMMAND RECEIVED");
    dircB = 0;  // direction for servo to run
    stateB = 2; // sets current state
  });

  server.on("/resetB", []() {
    server.send(200, "text/html", webPage);
    Serial.println("HTTP CLOSE COMMAND RECEIVED");
    dircB = 180; // direction for servo to run
    stateB = 1;  // sets current state
  });

  server.on("/deliverC", []() {
    server.send(200, "text/html", webPage);
    Serial.println("HTTP OPEN COMMAND RECEIVED");
    dircC = 0;  // direction for servo to run
    stateC = 2; // sets current state
  });

  server.on("/resetC", []() {
    server.send(200, "text/html", webPage);
    Serial.println("HTTP CLOSE COMMAND RECEIVED");
    dircC = 180; // direction for servo to run
    stateC = 1;  // sets current state
  });

  server.on("/deliverD", []() {
    server.send(200, "text/html", webPage);
    Serial.println("HTTP OPEN COMMAND RECEIVED");
    dircD = 0;  // direction for servo to run
    stateD = 2; // sets current state
  });

  server.on("/resetD", []() {
    server.send(200, "text/html", webPage);
    Serial.println("HTTP CLOSE COMMAND RECEIVED");
    dircD = 180; // direction for servo to run
    stateD = 1;  // sets current state
  });

  server.begin();
  Serial.println("Server started");
}


void servo_moveA() {
  Serial.println("State Change. Rotating Servo");
  if ( dircA == 180) {
    myservoA.attach(servoPinA);               // energize servo
    delay(50);
    for (posA = 0; posA <= 180; posA += 1) {    // goes from 0 degrees to 90 degrees in steps of 1 degree CHANGE 90 TO MATCH ANGLE OF TILT DESIRED
      myservoA.write(posA);                   // tell servo to go to position in variable 'pos'
      delay(5);                              // waits 30ms between each degree to slow rotation speed
    }
    delay(50);
    myservoA.detach();                        // movement finished so detach servo to conserve power
  }
  else if (dircA == 0) {
    myservoA.attach(servoPinA);                // energize servo
    delay(50);
    for (posA = 180; posA >= 0; posA -= 1) {     // goes from 90 degrees to 0 degrees in steps of 1 degree CHANGE 90 TO MIRROR ANGLE OF TILT DESIRED ABOVE
      myservoA.write(posA);                    // tell servo to go to position in variable 'pos'
      delay(5);                             // waits 30ms between each degree to slow rotation speed
    }
    delay(50);
    myservoA.detach();                          // movement finished so detach servo to conserve power
  }// end if dirA
}// end servoA

void servo_moveB() {
  Serial.println("State Change. Rotating Servo");
  if ( dircB == 180) {
    myservoB.attach(servoPinB);               // energize servo
    delay(50);
    for (posB = 0; posB <= 180; posB += 1) {    // goes from 0 degrees to 90 degrees in steps of 1 degree CHANGE 90 TO MATCH ANGLE OF TILT DESIRED
      myservoB.write(posB);                   // tell servo to go to position in variable 'pos'
      delay(5);                              // waits 30ms between each degree to slow rotation speed
    }
    delay(50);
    myservoB.detach();                        // movement finished so detach servo to conserve power
  }
  else if (dircB == 0) {
    myservoB.attach(servoPinB);                // energize servo
    delay(50);
    for (posB = 180; posB >= 0; posB -= 1) {     // goes from 90 degrees to 0 degrees in steps of 1 degree CHANGE 90 TO MIRROR ANGLE OF TILT DESIRED ABOVE
      myservoB.write(posB);                    // tell servo to go to position in variable 'pos'
      delay(5);                             // waits 30ms between each degree to slow rotation speed
    }
    delay(50);
    myservoB.detach();                          // movement finished so detach servo to conserve power
  }// end if dirB
}// end servoB

void servo_moveC() {
  Serial.println("State Change. Rotating Servo");
  if ( dircC == 180) {
    myservoC.attach(servoPinC);               
    delay(50);
    for (posC = 0; posC <= 180; posC += 1) {    
      myservoC.write(posC);                   
      delay(5);                              
    }
    delay(50);
    myservoC.detach();                        
  }
  else if (dircC == 0) {
    myservoC.attach(servoPinC);                
    delay(50);
    for (posC = 90; posC >= 0; posC -= 1) {     
      myservoC.write(posC);                    
      delay(5);                             
    }
    delay(50);
    myservoC.detach();                          
  }// end if dirC
}// end servoC

void servo_moveD() {
  Serial.println("State Change. Rotating Servo");
  if ( dircD == 180) {
    myservoD.attach(servoPinD);
    delay(50);
    for (posD = 0; posD <= 180; posD += 1) {
      myservoD.write(posD);
      delay(5);
    }
    delay(50);
    myservoD.detach();
  }
  else if (dircD == 0) {
    myservoD.attach(servoPinD);
    delay(50);
    for (posD = 90; posD >= 0; posD -= 1) {
      myservoD.write(posD);
      delay(5);
    }
    delay(50);
    myservoD.detach();
  }// end if dircD
}// end servoD


void loop() {
  if (stateA != prevstateA) {
    servo_moveA();
    prevstateA = stateA;
  }

  if (stateB != prevstateB) {
    servo_moveB();
    prevstateB = stateB;
  }

  if (stateC != prevstateC) {
    servo_moveC();
    prevstateC = stateC;
  }

  if (stateD != prevstateD) {
    servo_moveD();
    prevstateD = stateD;
  }


  server.handleClient();
}

Thanks for taking a look.
Johnny

Where do you initialize it at the other end of movement for its starting location? I'm not seeing that.

CrossRoads,

I thought the "0" values indicated the servo starting position.

Servo myservoC;
int posC = 0;
int stateC = 0;
int prevstateC = 0;
int dircC = 0;
int servoPinC = D6;

The original code is found here: Simplest-SmartThings-ESP8266-Blinds/ESP8266-Sketch.ino at master · hobbzey/Simplest-SmartThings-ESP8266-Blinds · GitHub

I modified it to suit my needs with the help and guidance of other arduino.cc forum members.

What I was saying was that I didn't see where you commanded the servo to go and stay there until the following command told to move again.

CrossRoads,

I believe those commands are here

void servo_moveA() {
  Serial.println("State Change. Rotating Servo");
  if ( dircA == 180) {
    myservoA.attach(servoPinA);               // energize servo
    delay(50);
    for (posA = 0; posA <= 180; posA += 1) {    // goes from 0 degrees to 90 degrees in steps of 1 degree CHANGE 90 TO MATCH ANGLE OF TILT DESIRED
      myservoA.write(posA);                   // tell servo to go to position in variable 'pos'
      delay(5);                              // waits 30ms between each degree to slow rotation speed
    }
    delay(50);
    myservoA.detach();                        // movement finished so detach servo to conserve power
  }
  else if (dircA == 0) {
    myservoA.attach(servoPinA);                // energize servo
    delay(50);
    for (posA = 180; posA >= 0; posA -= 1) {     // goes from 90 degrees to 0 degrees in steps of 1 degree CHANGE 90 TO MIRROR ANGLE OF TILT DESIRED ABOVE
      myservoA.write(posA);                    // tell servo to go to position in variable 'pos'
      delay(5);                             // waits 30ms between each degree to slow rotation speed
    }
    delay(50);
    myservoA.detach();                          // movement finished so detach servo to conserve power
  }// end if dirA
}// end servoA

Changing the posA 180 values to 0 and the 0’s to 180 didn’t work.

I also tried swapping the dircA values from 180 to 0 and that also didn’t work.

Anyone else have any ideas?

I recently made an extensive class to do just what you are trying to do.

This excerpt should work for you… use normalizedWrite() instead of write().

(untested)

#include <Servo.h>

enum Spin{
  NORMAL_ROTATION,
  REVERSE_ROTATION,
}spin;
  
class MyServo : public Servo {
  public:
    MyServo(Spin _direction){spinDirection = _direction;};
    void normalizedWrite(int val){write(spinDirection == REVERSE_ROTATION? 180 - val : val);};
  private:
   Spin spinDirection;
};

MyServo right(NORMAL_ROTATION);
MyServo left(REVERSE_ROTATION);

void setup() 
{
  right.attach(9);
  left.attach(10);
}

void loop() 
{
  static bool toggle = true;
  right.normalizedWrite(toggle? 180:0);
  left.normalizedWrite(toggle? 180:0);
  delay(2000);
  toggle = !toggle;
}

I needed to flip one of them 180 degrees for space reasons.

For the servo you need to be flipped, if you've got thisServo.write (angle); use thisServo.write(180 - angle);

Or have I misunderstood?

BulldogLowell and Groove,

I appreciate the info.

Unfortunately I don't fully understand how to modify my code with these changes to make it all work.

Johnny