Making Servo go back and forth without delay

I'm working on a project where I have to make 2 servos rotate in the opposite direction, stop for a few seconds and go in reverse for both servos. All of this without the delay function. I've attempted to solve this puzzle, but the code ends up not working and gets very messy. My current code is below:

#include <Servo.h>

//MOTOR
const int servoPin = 9; // the pin number for the servo signal
const int servoMinDegrees = 20; // the limits to servo movement
const int servoMaxDegrees = 190; //Increase to increase servo time on
Servo Motor;  // create servo object to control a servo 
int servoPosition = 90;     // the current angle of the servo - starting at 90.
int servoSlowInterval = 80; // millisecs between servo moves
int servoFastInterval = 10;
int servoInterval = servoSlowInterval; // initial millisecs between servo moves
int servoDegrees = 4;       // amount servo moves at each step 
unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousServoMillis = 0; // the time when the servo was last moved

//MOTOR2
const int servoPin2 = 10; // the pin number for the servo signal
const int servoMinDegrees2 = -10; // the limits to servo movement
const int servoMaxDegrees2 = 190; //Increase to increase servo time on
Servo Motor2;  // create servo object to control a servo 
int servoPosition2 = 90;     // the current angle of the servo - starting at 90.
int servoSlowInterval2 = 80; // millisecs between servo moves
int servoFastInterval2 = 10;
int servoInterval2 = servoSlowInterval2; // initial millisecs between servo moves
int servoDegrees2 = -4;       // amount servo moves at each step 
unsigned long currentMillis2 = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousServoMillis2 = 0; // the time when the servo was last moved

void setup() {
 Serial.begin(9600);
 Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino");  // so we know what sketch is running
 Motor.write(servoPosition); // sets the initial position
 Motor.attach(servoPin);
 Motor2.write(servoPosition); // sets the initial position
 Motor2.attach(servoPin2);
}

//=======

void loop() {
 currentMillis = millis();   // capture the latest value of millis()
 servoSweep();
 currentMillis2 = millis();
 servoSweep2();
}
void servoSweep() {
    // this is similar to the servo sweep example except that it uses millis() rather than delay()
     // nothing happens unless the interval has expired
     // the value of currentMillis was set in loop()
 if (currentMillis - previousServoMillis >= servoInterval) {
       // its time for another move
   previousServoMillis += servoInterval;
   servoPosition = servoPosition + servoDegrees; // servoDegrees might be negative
   if (servoPosition <= servoMinDegrees) {
         // when the servo gets to its minimum position change the interval to change the speed
      if (servoInterval == servoSlowInterval) {
        servoInterval = servoFastInterval;
      }
      else {
       servoInterval = servoSlowInterval;
      }
   }
   if ((servoPosition >= servoMaxDegrees) || (servoPosition <= servoMinDegrees))  {
   Motor.detach();
   }
       // make the servo move to the next position
   Motor.write(servoPosition);
       // and record the time when the move happened
 }
}

void servoSweep2() {
    // this is similar to the servo sweep example except that it uses millis() rather than delay()
     // nothing happens unless the interval has expired
     // the value of currentMillis was set in loop()
 if (currentMillis2 - previousServoMillis2 >= servoInterval2) {
       // its time for another move
   previousServoMillis2 += servoInterval2;
   servoPosition2 = servoPosition2 + servoDegrees2; // servoDegrees might be negative
   if (servoPosition2 <= servoMinDegrees2) {
         // when the servo gets to its minimum position change the interval to change the speed
      if (servoInterval2 == servoSlowInterval2) {
        servoInterval2 = servoFastInterval2;
      }
      else {
       servoInterval2 = servoSlowInterval2;
      }
   }
   if ((servoPosition2 >= servoMaxDegrees2) || (servoPosition2 <= servoMinDegrees2))  {
   Motor2.detach();
   
   }
       // make the servo move to the next position
   Motor2.write(servoPosition2);
       // and record the time when the move happened
 }
}

I've also tried using the boolean function, but I feel as if I'm lacking some vital understanding on it and yes I have already researched.

Why would you detach() the servo at all?

I've also tried using the boolean function

Boolean is a variable type. It is NOT a function.

       // make the servo move to the next position
   Motor2.write(servoPosition2);
       // and record the time when the move happened

Well, what happened to the next line of code?

This is what I have so far. I'm digressing my attempt at making it reverse.

#include <Servo.h>
boolean reverse = false;

//MOTOR
const int servoPin = 9; // the pin number for the servo signal
const int servoMinDegrees = -10; // the limits to servo movement
const int servoMaxDegrees = 190; //Increase to increase servo time on
Servo Motor;  // create servo object to control a servo 
int servoPosition = 90;     // the current angle of the servo - starting at 90.
int servoSlowInterval = 80; // millisecs between servo moves
int servoFastInterval = 10;
int servoInterval = servoSlowInterval; // initial millisecs between servo moves
int servoDegrees = 4;       // amount servo moves at each step 
unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousServoMillis = 0; // the time when the servo was last moved

//MOTOR2
const int servoPin2 = 10; // the pin number for the servo signal
const int servoMinDegrees2 = -10; // the limits to servo movement
const int servoMaxDegrees2 = 190; //Increase to increase servo time on
Servo Motor2;  // create servo object to control a servo 
int servoPosition2 = 90;     // the current angle of the servo - starting at 90.
int servoSlowInterval2 = 80; // millisecs between servo moves
int servoFastInterval2 = 10;
int servoInterval2 = servoSlowInterval2; // initial millisecs between servo moves
int servoDegrees2 = -4;       // amount servo moves at each step 
unsigned long currentMillis2 = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousServoMillis2 = 0; // the time when the servo was last moved

void setup() {
 Serial.begin(9600);
 Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino");  // so we know what sketch is running
 Motor.write(servoPosition); // sets the initial position
 Motor.attach(servoPin);
 Motor2.write(servoPosition); // sets the initial position
 Motor2.attach(servoPin2);
}

//=======

void loop() {
 currentMillis = millis();   // capture the latest value of millis()
 servoSweep();
 currentMillis2 = millis();
 servoSweep2();
}
void servoSweep() {
    // this is similar to the servo sweep example except that it uses millis() rather than delay()
     // nothing happens unless the interval has expired
     // the value of currentMillis was set in loop()
 if (currentMillis - previousServoMillis >= servoInterval) {
       // its time for another move
   previousServoMillis += servoInterval;
   servoPosition = servoPosition + servoDegrees; // servoDegrees might be negative
   if (servoPosition <= servoMinDegrees) {
         // when the servo gets to its minimum position change the interval to change the speed
      if (servoInterval == servoSlowInterval) {
        servoInterval = servoFastInterval;
      }
      else {
       servoInterval = servoSlowInterval;
      }
   }
   
   if ((servoPosition >= servoMaxDegrees) || (servoPosition <= servoMinDegrees))  {
   Motor.detach();
   }
       // make the servo move to the next position
   Motor.write(servoPosition);
       // and record the time when the move happened
 }
}

void servoSweep2() {
    // this is similar to the servo sweep example except that it uses millis() rather than delay()
     // nothing happens unless the interval has expired
     // the value of currentMillis was set in loop()
 if (currentMillis2 - previousServoMillis2 >= servoInterval2) {
       // its time for another move
   previousServoMillis2 += servoInterval2;
   servoPosition2 = servoPosition2 + servoDegrees2; // servoDegrees might be negative
   if (reverse == false) {
   if (servoPosition2 <= servoMinDegrees2) {
         // when the servo gets to its minimum position change the interval to change the speed
      if (servoInterval2 == servoSlowInterval2) {
        servoInterval2 = servoFastInterval2;
      }
      else {
       servoInterval2 = servoSlowInterval2;
      }
   }
   }
   if ((servoPosition2 >= servoMaxDegrees2) || (servoPosition2 <= servoMinDegrees2))  {
   Motor2.detach();
   reverse = true;
   }
       // make the servo move to the next position
   Motor2.write(servoPosition2);
       // and record the time when the move happened
 }

if (reverse == true){
if (currentMillis - previousServoMillis >= servoInterval) {
       // its time for another move
   previousServoMillis += servoInterval;
   servoPosition = servoPosition + servoDegrees; // servoDegrees might be negative
   if (servoPosition <= servoMinDegrees) {
         // when the servo gets to its minimum position change the interval to change the speed
      if (servoInterval == servoSlowInterval) {
        servoInterval = servoFastInterval;
      }
      else {
       servoInterval = servoSlowInterval;
      }
   }
   
   if ((servoPosition >= servoMaxDegrees) || (servoPosition <= servoMinDegrees))  {
   Motor2.detach();
   reverse = false;
   }
       // make the servo move to the next position
   Motor2.write(servoPosition);
       // and record the time when the move happened
 }
 
}
}

This is one of my attempts at making Motor2 reverse (it doesn't work). :frowning:

Have a look at the servo code in Several Things at a Time

...R

I have looked at it, but after I detach the servo, how do I make it pause for a few seconds (without using delay) and then turn on again, but going in reverse?

You never answered the question earlier - why are you detaching the servo?

Its part of the project guidelines.

nafi04:
Its part of the project guidelines.

I would be interested to see them. Is any reason given for detaching the servo ?

The 2 servo control a panel. When the servo's rotate the panel covers what's underneath (solar panel), protecting it from any "dangers", such as dust to a solar panel. That detach is there to stop the panel and protect the solar panels from the dust (this is only the beginning of the project). When the flow of dust stops, the panel goes back, uncovering the solar panel and allowing more energy to be collected.

That detach is there to stop the panel

That is exactly what it won't do. Detaching the servo allows it to turn if the output shaft is turned by an external force. To stop the servo turning all that needs to happen is to write a constant value to it.

UKHeliBob:
To stop the servo turning all that needs to happen is to write a constant value to it.

So do I attach a value to detach?

nafi04:
So do I attach a value to detach?

No

Motor.write(holdPosition);

Will move the servo to the position given and hold it there.

Incidentally, how are you powering the servos ?

I'm using a breadboard to extend the reach of the servos and right now I'm using a laptop. Thanks for the advice. :slight_smile:

nafi04:
I'm using a breadboard to extend the reach of the servos. Thanks for the advice. :slight_smile:

OK, but how are they powered ? Direct from the Arduino 5V and GND pins or from another power source ?

What value would I give holdPosition and would I replace it with the position Motor.detach(); took? And by the way I edited that post for clarity before I knew you already posted (5V and GND)

The value you use for what I named holdPosition is up to you. What angle do you want to stop the servo at ?

In your PM to me you said

I've tries making hold position = servoMinDegrees and servoMaxDegrees, but it doesn't work.

but you didn't say what you meant by that.

Please post the code that you tried.

So, the servos are powered directly from the Arduino 5V and GND pins. This is generally regarded as bad practice due to the current that can be taken by servos. Can you please provide a link to the servos being used.

Here is the servo link (https://www.pololu.com/product/2820).

#include <Servo.h>

//MOTOR
const int servoPin = 9; // the pin number for the servo signal
const int servoMinDegrees = -10; // the limits to servo movement
const int servoMaxDegrees = 190; //Increase to increase servo time on
Servo Motor;  // create servo object to control a servo 
int servoPosition = 90;     // the current angle of the servo - starting at 90.
int servoSlowInterval = 80; // millisecs between servo moves
int servoFastInterval = 10;
int servoInterval = servoSlowInterval; // initial millisecs between servo moves
int servoDegrees = 4;       // amount servo moves at each step 
unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousServoMillis = 0; // the time when the servo was last moved

//MOTOR2
const int servoPin2 = 10; // the pin number for the servo signal
const int servoMinDegrees2 = -10; // the limits to servo movement
const int servoMaxDegrees2 = 190; //Increase to increase servo time on
Servo Motor2;  // create servo object to control a servo 
int servoPosition2 = 90;     // the current angle of the servo - starting at 90.
int servoSlowInterval2 = 80; // millisecs between servo moves
int servoFastInterval2 = 10;
int servoInterval2 = servoSlowInterval2; // initial millisecs between servo moves
int servoDegrees2 = -4;       // amount servo moves at each step 
unsigned long currentMillis2 = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousServoMillis2 = 0; // the time when the servo was last moved

void setup() {
 Serial.begin(9600);
 Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino");  // so we know what sketch is running
 Motor.write(servoPosition); // sets the initial position
 Motor.attach(servoPin);
 Motor2.write(servoPosition); // sets the initial position
 Motor2.attach(servoPin2);
}

//=======

void loop() {
 currentMillis = millis();   // capture the latest value of millis()
 servoSweep();
 currentMillis2 = millis();
 servoSweep2();
}

void servoSweep() {
    // this is similar to the servo sweep example except that it uses millis() rather than delay()
     // nothing happens unless the interval has expired
     // the value of currentMillis was set in loop()
 if (currentMillis - previousServoMillis >= servoInterval) {
       // its time for another move
   previousServoMillis += servoInterval;
   servoPosition = servoPosition + servoDegrees; // servoDegrees might be negative
   if (servoPosition <= servoMinDegrees) {
         // when the servo gets to its minimum position change the interval to change the speed
      if (servoInterval == servoSlowInterval) {
        servoInterval = servoFastInterval;
      }
      else {
       servoInterval = servoSlowInterval;
      }
   }
   
   if ((servoPosition >= servoMaxDegrees) || (servoPosition <= servoMinDegrees))  {
   Motor.write(servoMaxDegrees);
   }
       // make the servo move to the next position
   Motor.write(holdPosition);
       // and record the time when the move happened
 }
}

void servoSweep2() {
    // this is similar to the servo sweep example except that it uses millis() rather than delay()
     // nothing happens unless the interval has expired
     // the value of currentMillis was set in loop()
 if (currentMillis2 - previousServoMillis2 >= servoInterval2) {
       // its time for another move
   previousServoMillis2 += servoInterval2;
   servoPosition2 = servoPosition2 + servoDegrees2; // servoDegrees might be negative
   if (servoPosition2 <= servoMinDegrees2) {
         // when the servo gets to its minimum position change the interval to change the speed
      if (servoInterval2 == servoSlowInterval2) {
        servoInterval2 = servoFastInterval2;
      }
      else {
       servoInterval2 = servoSlowInterval2;
      }
   }
   
   if ((servoPosition2 >= servoMaxDegrees2) || (servoPosition2 <= servoMinDegrees2))  {
  Motor2.write(servoMinDegrees2);
   }
       // make the servo move to the next position
   Motor2.write(servoPosition2);
       // and record the time when the move happened
 }
}

The servo should stop at that position, the minimum or maximum. The degrees are even specified, but the servos continue to rotate. I replaced Motor.detach(); with the corresponding servoMin/MaxDegrees.

Oh dear, Oh dear, Oh dear.

What you have are not servos, despite their name. They are electronically controlled motors. The value written to them controls their speed and direction and not their position as would be the case for real servos.

You cannot, therefore, stop them at a particular position. My advice would be to buy some real servos.

Can you give me a link to where I can buy a real servo?