Multiple lines of code running simultaneously?

Robin2:
"and then you should have a separate copy of the function servoSweep() (each with a different name) for each servo."

When you say this, do you mean I establish servoSweep() multiple times in the loop or the void servoSweep function? And how exactly do I establish it?

Also yes I have three servos - one in pin 3, one in 4, and one in 5. I tried to modify the code to fit this situation. My goal is to get all three servos doing a back and forth motion simultaneously, and if possible make it so that I can run a line of code that doesn't loop a back and forth motion. This way, I can accurately run the servo that will operate the mouth to fit a speech we prerecorded. I also want the servos operating the arms to run on lines of code rather than a loop, since, for example, I want one of the arms to wave (move up and back down), but I do not want this action to loop.

Currently when I run the code, the only thing that happens is that the servo operating the mouth flinches a little bit.

I really appreciate the help and I hope I can figure this out as a noob with no clue how to code outside of Robot C.

Edit: Sorry, quote fail, coding is even involved in asking how to code

eguirguis2005:
When you say this, do you mean I establish servoSweep() multiple times in the loop or the void servoSweep function? And how exactly do I establish it?

What I am suggesting is that you make two copies of the function so you have three functions with different names and ALSO with different names for the variables for the different servos.

AND, in loop() you need a line to call each of the functions, one after the other.

If you are still having difficulties please post the program that represents your best attempt.

...R

Alright, I have established three servosweep functions in the loop and have made three separate void servosweep functions, but all the code does is move the mouth servo (the servo in pin 5) back and forth slowly once and then back and forth once at normal speed. Here is my code:
CODE:
// SeveralThingsAtTheSameTimeRev1.ino

// An expansion of the BlinkWithoutDelay concept to illustrate how a script
// can appear to do several things at the same time

// it sweeps a servo (connected to pin 5) back and forth at different speeds

// The Arduino is not capable of supplying enough 5v power to operate a servo
// The servo should have it’s own power supply and the power supply Ground should
// be connected to the Arduino Ground.

// The sketch is written to illustrate a few different programming features.
// The use of many functions with short pieces of code.
// Short pieces of code are much easier to follow and debug
// The use of variables to record the state of something (e.g. onBoardLedState) as a means to
// enable the different functions to determine what to do.
// The use of millis() to manage the timing of activities
// The definition of all numbers used by the program at the top of the sketch where
// they can easily be found if they need to be changed

//=======

// -----LIBRARIES

#include <Servo.h>

// ----CONSTANTS (won’t change)

const int servoPin3 = 3; // the pin number for the servo signal
const int servoPin4 = 4;
const int servoPin5 = 5;
const int servoMinDegrees = 20; // the limits to servo movement
const int servoMaxDegrees = 150;

Servo myservo; // 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 = 2; // amount servo moves at each step
// will be changed to negative value for movement in the other direction

unsigned long currentMillis = 0; // stores the value of millis() in each iteration of loop()
unsigned long previousOnBoardLedMillis = 0; // will store last time the LED was updated
unsigned long previousLed_A_Millis = 0;
unsigned long previousLed_B_Millis = 0;

unsigned long previousButtonMillis = 0; // time when button press last checked

unsigned long previousServoMillis = 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

// set the Led pins as output:

myservo.write(servoPosition); // sets the initial position
myservo.attach(servoPin3);
myservo.attach(servoPin4);
myservo.attach(servoPin5);

}

//=======

void loop() {

// Notice that none of the action happens in loop() apart from reading millis()
// it just calls the functions that have the action code

currentMillis = millis(); // capture the latest value of millis()
// this is equivalent to noting the time from a clock
// use the same time for all LED flashes to keep them synchronized
servoSweep1();
servoSweep2();
servoSweep3();

}

//========

void servoSweep1() {

// 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)) {
// if the servo is at either extreme change the sign of the degrees to make it move the other way
servoDegrees = - servoDegrees; // reverse direction
// and update the position to ensure it is within range
servoPosition = servoPosition + servoDegrees;
}
// make the servo move to the next position
myservo.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 (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)) {
// if the servo is at either extreme change the sign of the degrees to make it move the other way
servoDegrees = - servoDegrees; // reverse direction
// and update the position to ensure it is within range
servoPosition = servoPosition + servoDegrees;
}
// make the servo move to the next position
myservo.write(servoPosition);
// and record the time when the move happened
}
}

void servoSweep3() {

// 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)) {
// if the servo is at either extreme change the sign of the degrees to make it move the other way
servoDegrees = - servoDegrees; // reverse direction
// and update the position to ensure it is within range
servoPosition = servoPosition + servoDegrees;
}
// make the servo move to the next position
myservo.write(servoPosition);
// and record the time when the move happened
}
}
//=====END
</>

Edit: I can’t get this code button thing to work, I apologize

To make it easy for people to help you please modify your post and use the code button </>
codeButton.png

so your code looks like this and is easy to copy to a text editor. See How to use the Forum

I already mentioned this in Reply #15!

Your code is too long for me to study quickly without copying to my text editor. The text editor shows line numbers, identifies matching brackets and allows me to search for things like all instances of a particular variable or function.

Also, if you have not done so, please use the AutoFormat tool to indent your code for easier reading.

...R

You're only declaring one servo object:

Servo myservo;  // create servo object to control a servo

and then assigning 3 pins in succession to it:

myservo.attach(servoPin3);
myservo.attach(servoPin4);
myservo.attach(servoPin5);

It's not surprising that the last pin you assigned -- 5 -- is the one that is controlled.

Consider making your servo and pin names more descriptive than "myservo" and, more importantly, instantiate objects for each servo.

const int pinServoLArm = 3; // the pin number for the servo signal
const int pinServoRARM = 4;
const int pinServoMouth = 5;  

.
.
.

Servo servoMouth;
Servo servoLeftArm;
Servo servoRightArm;

.
.
.

    servoMouth.attach(pinServoMouth);
    servoLeftArm.attach(pinServoLArm);
    servoRightArm.attach(pinServoRARM);

    servoMouth.write(servoMouthPosition);
.
.
.

Note that this also means your variable manipulation will need serious tweaking to control 3 individual servo instances instead of just one.

@Blackfin

Thank you for the fix. I’ve added it into the code, however it had an error with the servoMouth.write(servoMouthPosition) function and I didn’t know how to fix it so I removed it. Here is my current code.

@Robin

I see now, the problem was I was using quick reply so there was no code option. Maybe now you could review the code?

// SeveralThingsAtTheSameTimeRev1.ino

// An expansion of the BlinkWithoutDelay concept to illustrate how a script
//  can appear to do several things at the same time

//    it sweeps a servo (connected to pin 5) back and forth at different speeds

//  The Arduino is not capable of supplying enough 5v power to operate a servo
//    The servo should have it's own power supply and the power supply Ground should
//      be connected to the Arduino Ground.

// The sketch is written to illustrate a few different programming features.
//    The use of many functions with short pieces of code. 
//       Short pieces of code are much easier to follow and debug
//    The use of variables to record the state of something (e.g. onBoardLedState) as a means to
//       enable the different functions to determine what to do.
//    The use of millis() to manage the timing of activities
//    The definition of all numbers used by the program at the top of the sketch where 
//       they can easily be found if they need to be changed

//=======

// -----LIBRARIES

#include <Servo.h>

// ----CONSTANTS (won't change)

const int pinServoLArm = 3; // the pin number for the servo signal
const int pinServoRARM = 4;
const int pinServoMouth = 5;
const int servoMinDegrees = 20; // the limits to servo movement
const int servoMaxDegrees = 150;

Servo myservo;  // 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 = 2;       // amount servo moves at each step 
                           //    will be changed to negative value for movement in the other direction

unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousOnBoardLedMillis = 0;   // will store last time the LED was updated
unsigned long previousLed_A_Millis = 0;
unsigned long previousLed_B_Millis = 0;

unsigned long previousButtonMillis = 0; // time when button press last checked

unsigned long previousServoMillis = 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
 
     // set the Led pins as output:

Servo servoMouth;
Servo servoLeftArm;
Servo servoRightArm;
     

servoMouth.attach(pinServoMouth);
servoLeftArm.attach(pinServoLArm);
servoRightArm.attach(pinServoRARM);

}

//=======

void loop() {

     // Notice that none of the action happens in loop() apart from reading millis()
     //   it just calls the functions that have the action code

 currentMillis = millis();   // capture the latest value of millis()
                             //   this is equivalent to noting the time from a clock
                             //   use the same time for all LED flashes to keep them synchronized
 servoSweep1();
 servoSweep2();
 servoSweep3();

}

//========

void servoSweep1() {

     // 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))  {
         // if the servo is at either extreme change the sign of the degrees to make it move the other way
     servoDegrees = - servoDegrees; // reverse direction
         // and update the position to ensure it is within range
     servoPosition = servoPosition + servoDegrees; 
   }
       // make the servo move to the next position
   myservo.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 (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))  {
         // if the servo is at either extreme change the sign of the degrees to make it move the other way
     servoDegrees = - servoDegrees; // reverse direction
         // and update the position to ensure it is within range
     servoPosition = servoPosition + servoDegrees; 
   }
       // make the servo move to the next position
   myservo.write(servoPosition);
       // and record the time when the move happened
 }
}

void servoSweep3() {

     // 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))  {
         // if the servo is at either extreme change the sign of the degrees to make it move the other way
     servoDegrees = - servoDegrees; // reverse direction
         // and update the position to ensure it is within range
     servoPosition = servoPosition + servoDegrees; 
   }
       // make the servo move to the next position
   myservo.write(servoPosition);
       // and record the time when the move happened
 }
}
//=====END

When the time comes - and it will be pretty soon, you should explore structs and arrays.
It's a modest sized step forward from using millis()

Using them will shrink the existing code by 50% or more

e.g. a struct{} for 'a' servo with the pin and other parameters as variables
an array of those structs - with unique param values for each

A single function to manipulate any servo.

eguirguis2005:
Maybe now you could review the code?

You now have three functions which is what I had in mind. But they are all using the same variables - like the Monty Python sketch in which everyone was named Bruce.

This is from your servoSweep2() function

if (currentMillis - previousServoMillis >= servoInterval) {
       // its time for another move
   previousServoMillis += servoInterval;
   
   servoPosition = servoPosition + servoDegrees;

I strongly suspect that the variables previousServoMillis, servoInterval, servoPosition and servoDegrees will need to be different for each servo.

And I agree with @lastchancename that it would be well worth the trouble to learn how to use a struct and an array of structs. But it is not essential.

...R

@OP, have a look at this and give it a try. It looks to work on my oscilloscope on a 2560. It should give activity on all three servos, sweeping back and forth. It utilizes the notion of a structure and array to hold servo information.

Sorry I don’t have a lot of time to comment the code more than it is. Have a look and ask any questions.

#include <Servo.h>

// ----CONSTANTS (won't change)
const int pinServoLArm = 3; // the pin number for the servo signal
const int pinServoRArm = 4;
const int pinServoMouth = 5;
const int servoMinDegrees = 20; // the limits to servo movement
const int servoMaxDegrees = 150;
const unsigned long servoSlowInterval = 80; // millisecs between servo moves
const unsigned long servoFastInterval = 10;

//servo instantiatons
Servo servoMouth;
Servo servoLeftArm;
Servo servoRightArm;

//structure to hold relevant servo information
typedef struct
{
    Servo       *ServoAxis;             //mouth, left- or right-arm
    uint16_t    ServoPosition;          //servo's position
    bool        bServoDirection;        //direction of travel (true = angle increasing)
    uint32_t    timeServo;              //used for timing servo motion
    uint32_t    timeServoDelay;         //used for timing servo motion
    
}struct_ServoControl;

//create an array of the above structures, each element corresponding to each servo axis
struct_ServoControl ServoControl[] = 
{
    {
        //mouth
        .ServoAxis = (Servo *)&servoMouth,
        .ServoPosition = servoMinDegrees,       //different start positions for each 
        .bServoDirection = true,
        .timeServo = 0,
        .timeServoDelay = servoSlowInterval
            
    },
    {
        //left arm
        .ServoAxis = (Servo *)&servoLeftArm,
        .ServoPosition = servoMaxDegrees,
        .bServoDirection = false,
        .timeServo = 0,
        .timeServoDelay = servoFastInterval
            
    },
    {
        //right arm
        .ServoAxis = (Servo *)&servoRightArm,
        .ServoPosition = 90,
        .bServoDirection = true,
        .timeServo = 0,
        .timeServoDelay = servoSlowInterval
            
    }
};

//========
//not really needed but helps identify element members in array
#define MOUTH       0
#define LEFTARM     1   
#define RIGHTARM    2
void setup() 
{
    Serial.begin(9600);
    Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino");  // so we know what sketch is running

    //attach each pin
    ServoControl[MOUTH].ServoAxis->attach(pinServoMouth);
    ServoControl[LEFTARM].ServoAxis->attach(pinServoLArm);
    ServoControl[RIGHTARM].ServoAxis->attach(pinServoRArm);

    //set each axis initial position
    ServoControl[MOUTH].ServoAxis->write( ServoControl[MOUTH].ServoPosition );
    ServoControl[LEFTARM].ServoAxis->write( ServoControl[LEFTARM].ServoPosition );
    ServoControl[RIGHTARM].ServoAxis->write( ServoControl[RIGHTARM].ServoPosition );

}//setup

//=======

void SimpleServoControl( void )
{
    static byte
        axis = MOUTH;
    unsigned long
        timeNow;

    //get the "time" now
    timeNow = millis();

    //for the current element (pointed to by axis); is it time to move the servo?
    if( timeNow - ServoControl[axis].timeServo >= ServoControl[axis].timeServoDelay )
    {
        //yes, record the time this occured for timing the next movement
        ServoControl[axis].timeServo = timeNow;

        //check the current direction of movement
        if( ServoControl[axis].bServoDirection )
        {
            //true; we're increasing the angle
            ServoControl[axis].ServoPosition++;
            //if we get to the upper limit...
            if( ServoControl[axis].ServoPosition >= servoMaxDegrees )
            {
                //change direction and set the "slow" interval time
                ServoControl[axis].bServoDirection = false;
                ServoControl[axis].timeServoDelay = servoSlowInterval;
                
            }//if
                
        }
        else
        {
            //we're decreasing the angle
            ServoControl[axis].ServoPosition--;
            //if we get to the lower limit...
            if( ServoControl[axis].ServoPosition <= servoMinDegrees )
            {
                //check the direction again
                ServoControl[axis].bServoDirection = true;
                //and set the "fast" interval time
                ServoControl[axis].timeServoDelay = servoFastInterval;
                
            }//if
            
        }//else

        //set the new servo position
        ServoControl[axis].ServoAxis->write( ServoControl[axis].ServoPosition );        
        
    }//if

    //next time through we'll look a the next element of the array (so after MOUTH, do LEFTARM then RIGHTARM...
    axis++;
    //if we move past RIGHTARM, it's time to reset to the MOUTH again
    if( axis > RIGHTARM )
        axis = MOUTH;
        
}//SimpleServoControl

void loop() 
{
    //just call servo control; it handles the movement of all three servos
    SimpleServoControl();
    
}//loop

Edit: Updated to use pointers to the servo objects…

Nice example @BlackFin, but perhaps throwing OP in the deep end!

@Blackfin

Thank you so much for this code. I tried it out and messed with the const unsigned long functions and it finally allowed all three servos to move at the same time! I just have two problems now:

  1. I need the arm servos to take larger strokes than the mouth
  2. I need to modify the movements (pauses, etc)

Here is a video of what it does now: Arduino Animatronic - YouTube

I would appreciate your input on how to do this. Thanks in advance

eguirguis2005:
@Blackfin

Thank you so much for this code. I tried it out and messed with the const unsigned long functions and it finally allowed all three servos to move at the same time! I just have two problems now:

  1. I need the arm servos to take larger strokes than the mouth
  2. I need to modify the movements (pauses, etc)

Here is a video of what it does now: https://youtu.be/lPePleOobLw

I would appreciate your input on how to do this. Thanks in advance

Is that running the code I provided? If so, it looks like its cycling more quickly than I anticipated.

I modified your existing code which means all servos are limited by the two constants:

const int servoMinDegrees = 20; // the limits to servo movement
const int servoMaxDegrees = 150;

You could add a couple more members to the struct to define each element’s max and min, assign values to them during init and then compare against those instead of global constants as above:

typedef struct
{
    Servo       *ServoAxis;             //mouth, left- or right-arm
    uint16_t    ServoPosition;          //servo's position
    uint16_t    ServoMaxAngle;          //maximum angle  <-- add
    uint16_t    ServoMinAngle;          //minimum angle  <-- add
    bool        bServoDirection;        //direction of travel (true = angle increasing)
    uint32_t    timeServo;              //used for timing servo motion
    uint32_t    timeServoDelay;         //used for timing servo motion
    
}struct_ServoControl;


struct_ServoControl ServoControl[] = 
{
    {
        //mouth
        .ServoAxis = (Servo *)&servoMouth,
        .ServoPosition = servoMinDegrees,       //different start positions for each 
        .ServoMaxAngle = MAX_MOUTH_ANGLE,
        .ServoMinAngle = MIN_MOUTH_ANGLE,
        .bServoDirection = true,
        .timeServo = 0,
        .timeServoDelay = servoSlowInterval
            
    },
.
.
.

            if( ServoControl[axis].ServoPosition >= ServoControl[axis].ServoMaxAngle )
.
.
.

etc

that comes together in something like:

#include <Servo.h>

#define MIN_MOUTH_ANGLE     40
#define MAX_MOUTH_ANGLE     170
#define MIN_LARM_ANGLE      50
#define MAX_LARM_ANGLE      150
#define MIN_RARM_ANGLE      50
#define MAX_RARM_ANGLE      150

// ----CONSTANTS (won't change)
const int pinServoLArm = 3; // the pin number for the servo signal
const int pinServoRArm = 4;
const int pinServoMouth = 5;
const unsigned long servoSlowInterval = 80; // millisecs between servo moves
const unsigned long servoFastInterval = 10;

//servo instantiatons
Servo servoMouth;
Servo servoLeftArm;
Servo servoRightArm;

//structure to hold relevant servo information
typedef struct
{
    Servo       *ServoAxis;             //mouth, left- or right-arm
    uint16_t    ServoPosition;          //servo's position
    uint16_t    ServoMaxAngle;          //maximum angle
    uint16_t    ServoMinAngle;          //minimum angle
    bool        bServoDirection;        //direction of travel (true = angle increasing)
    uint32_t    timeServo;              //used for timing servo motion
    uint32_t    timeServoDelay;         //used for timing servo motion
    
}struct_ServoControl;

//create an array of the above structures, each element corresponding to each servo axis
struct_ServoControl ServoControl[] = 
{
    {
        //mouth
        .ServoAxis = (Servo *)&servoMouth,
        .ServoPosition = MIN_MOUTH_ANGLE,       //different start positions for each 
        .ServoMaxAngle = MAX_MOUTH_ANGLE,
        .ServoMinAngle = MIN_MOUTH_ANGLE,
        .bServoDirection = true,
        .timeServo = 0,
        .timeServoDelay = servoSlowInterval
            
    },
    {
        //left arm
        .ServoAxis = (Servo *)&servoLeftArm,
        .ServoPosition = MAX_LARM_ANGLE,
        .ServoMaxAngle = MAX_LARM_ANGLE,
        .ServoMinAngle = MIN_LARM_ANGLE,
        .bServoDirection = false,
        .timeServo = 0,
        .timeServoDelay = servoFastInterval
            
    },
    {
        //right arm
        .ServoAxis = (Servo *)&servoRightArm,
        .ServoPosition = MIN_RARM_ANGLE,
        .ServoMaxAngle = MAX_RARM_ANGLE,
        .ServoMinAngle = MIN_RARM_ANGLE,
        .bServoDirection = true,
        .timeServo = 0,
        .timeServoDelay = servoSlowInterval
            
    }
};

//========
//not really needed but helps identify element members in array
#define MOUTH       0
#define LEFTARM     1   
#define RIGHTARM    2
void setup() 
{
    Serial.begin(9600);
    Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino");  // so we know what sketch is running

    //attach each pin
    ServoControl[MOUTH].ServoAxis->attach(pinServoMouth);
    ServoControl[LEFTARM].ServoAxis->attach(pinServoLArm);
    ServoControl[RIGHTARM].ServoAxis->attach(pinServoRArm);

    //set each axis initial position
    ServoControl[MOUTH].ServoAxis->write( ServoControl[MOUTH].ServoPosition );
    ServoControl[LEFTARM].ServoAxis->write( ServoControl[LEFTARM].ServoPosition );
    ServoControl[RIGHTARM].ServoAxis->write( ServoControl[RIGHTARM].ServoPosition );

}//setup

//=======

void SimpleServoControl( void )
{
    static byte
        axis = MOUTH;
    unsigned long
        timeNow;

    //get the "time" now
    timeNow = millis();

    //for the current element (pointed to by axis); is it time to move the servo?
    if( timeNow - ServoControl[axis].timeServo >= ServoControl[axis].timeServoDelay )
    {
        //yes, record the time this occured for timing the next movement
        ServoControl[axis].timeServo = timeNow;

        //check the current direction of movement
        if( ServoControl[axis].bServoDirection )
        {
            //true; we're increasing the angle
            ServoControl[axis].ServoPosition++;
            //if we get to the upper limit...
            if( ServoControl[axis].ServoPosition >= ServoControl[axis].ServoMaxAngle )
            {
                //change direction and set the "slow" interval time
                ServoControl[axis].bServoDirection = false;
                ServoControl[axis].timeServoDelay = servoSlowInterval;
                
            }//if
                
        }
        else
        {
            //we're decreasing the angle
            ServoControl[axis].ServoPosition--;
            //if we get to the lower limit...
            if( ServoControl[axis].ServoPosition <= ServoControl[axis].ServoMinAngle )
            {
                //check the direction again
                ServoControl[axis].bServoDirection = true;
                //and set the "fast" interval time
                ServoControl[axis].timeServoDelay = servoFastInterval;
                
            }//if
            
        }//else

        //set the new servo position
        ServoControl[axis].ServoAxis->write( ServoControl[axis].ServoPosition );        
        
    }//if

    //next time through we'll look a the next element of the array (so after MOUTH, do LEFTARM then RIGHTARM...
    axis++;
    //if we move past RIGHTARM, it's time to reset to the MOUTH again
    if( axis > RIGHTARM )
        axis = MOUTH;
        
}//SimpleServoControl

void loop() 
{
    //just call servo control; it handles the movement of all three servos
    SimpleServoControl();
    
}//loop

@Blackfin

Thank you for the code suggestion. The reason I changed the servoslowintervals is because I was messing around with the values and realized that when I decreased this value, it made the servos move faster and also have shorter movements (though I don’t know why there are two). I modified this to cater the purpose of the mouth servo moving back and forth at full speed from angle 40 to angle 100, and this works properly. Additionally, I changed the arm min and max angles to 0 and 100, since I want the arm servos (one of the plastic knob things on it) to go from facing down to facing forwards in a repeated motion while the gorilla animatronic talks. However, for some reason the continuous servo (being the left arm) moves faster than the normal servo for the right arm, and moves one direction more than the other, so it goes from 0 to 100 degrees and back to about 30 and keeps looping around inconsistently. I don’t know how to make each servo move at the same speed and consistently from 0 to 100 degrees, but this is what I need. Here is my current code:

#include <Servo.h>

#define MIN_MOUTH_ANGLE     40
#define MAX_MOUTH_ANGLE     100
#define MIN_LARM_ANGLE      0
#define MAX_LARM_ANGLE      180
#define MIN_RARM_ANGLE      0
#define MAX_RARM_ANGLE      180

// ----CONSTANTS (won't change)
const int pinServoLArm = 3; // the pin number for the servo signal
const int pinServoRArm = 4;
const int pinServoMouth = 5;
const unsigned long servoSlowInterval = 5; // millisecs between servo moves
const unsigned long servoFastInterval = 5;

//servo instantiatons
Servo servoMouth;
Servo servoLeftArm;
Servo servoRightArm;

//structure to hold relevant servo information
typedef struct
{
    Servo       *ServoAxis;             //mouth, left- or right-arm
    uint16_t    ServoPosition;          //servo's position
    uint16_t    ServoMaxAngle;          //maximum angle
    uint16_t    ServoMinAngle;          //minimum angle
    bool        bServoDirection;        //direction of travel (true = angle increasing)
    uint32_t    timeServo;              //used for timing servo motion
    uint32_t    timeServoDelay;         //used for timing servo motion
    
}struct_ServoControl;

//create an array of the above structures, each element corresponding to each servo axis
struct_ServoControl ServoControl[] = 
{
    {
        //mouth
        .ServoAxis = (Servo *)&servoMouth,
        .ServoPosition = MIN_MOUTH_ANGLE,       //different start positions for each 
        .ServoMaxAngle = MAX_MOUTH_ANGLE,
        .ServoMinAngle = MIN_MOUTH_ANGLE,
        .bServoDirection = true,
        .timeServo = 0,
        .timeServoDelay = servoSlowInterval
            
    },
    {
        //left arm
        .ServoAxis = (Servo *)&servoLeftArm,
        .ServoPosition = MAX_LARM_ANGLE,
        .ServoMaxAngle = MAX_LARM_ANGLE,
        .ServoMinAngle = MIN_LARM_ANGLE,
        .bServoDirection = false,
        .timeServo = 0,
        .timeServoDelay = servoFastInterval
            
    },
    {
        //right arm
        .ServoAxis = (Servo *)&servoRightArm,
        .ServoPosition = MIN_RARM_ANGLE,
        .ServoMaxAngle = MAX_RARM_ANGLE,
        .ServoMinAngle = MIN_RARM_ANGLE,
        .bServoDirection = true,
        .timeServo = 0,
        .timeServoDelay = servoSlowInterval
            
    }
};

//========
//not really needed but helps identify element members in array
#define MOUTH       0
#define LEFTARM     1   
#define RIGHTARM    2
void setup() 
{
    Serial.begin(9600);
    Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino");  // so we know what sketch is running

    //attach each pin
    ServoControl[MOUTH].ServoAxis->attach(pinServoMouth);
    ServoControl[LEFTARM].ServoAxis->attach(pinServoLArm);
    ServoControl[RIGHTARM].ServoAxis->attach(pinServoRArm);

    //set each axis initial position
    ServoControl[MOUTH].ServoAxis->write( ServoControl[MOUTH].ServoPosition );
    ServoControl[LEFTARM].ServoAxis->write( ServoControl[LEFTARM].ServoPosition );
    ServoControl[RIGHTARM].ServoAxis->write( ServoControl[RIGHTARM].ServoPosition );

}//setup

//=======

void SimpleServoControl( void )
{
    static byte
        axis = MOUTH;
    unsigned long
        timeNow;

    //get the "time" now
    timeNow = millis();

    //for the current element (pointed to by axis); is it time to move the servo?
    if( timeNow - ServoControl[axis].timeServo >= ServoControl[axis].timeServoDelay )
    {
        //yes, record the time this occured for timing the next movement
        ServoControl[axis].timeServo = timeNow;

        //check the current direction of movement
        if( ServoControl[axis].bServoDirection )
        {
            //true; we're increasing the angle
            ServoControl[axis].ServoPosition++;
            //if we get to the upper limit...
            if( ServoControl[axis].ServoPosition >= ServoControl[axis].ServoMaxAngle )
            {
                //change direction and set the "slow" interval time
                ServoControl[axis].bServoDirection = false;
                ServoControl[axis].timeServoDelay = servoSlowInterval;
                
            }//if
                
        }
        else
        {
            //we're decreasing the angle
            ServoControl[axis].ServoPosition--;
            //if we get to the lower limit...
            if( ServoControl[axis].ServoPosition <= ServoControl[axis].ServoMinAngle )
            {
                //check the direction again
                ServoControl[axis].bServoDirection = true;
                //and set the "fast" interval time
                ServoControl[axis].timeServoDelay = servoFastInterval;
                
            }//if
            
        }//else

        //set the new servo position
        ServoControl[axis].ServoAxis->write( ServoControl[axis].ServoPosition );        
        
    }//if

    //next time through we'll look a the next element of the array (so after MOUTH, do LEFTARM then RIGHTARM...
    axis++;
    //if we move past RIGHTARM, it's time to reset to the MOUTH again
    if( axis > RIGHTARM )
        axis = MOUTH;
        
}//SimpleServoControl

void loop() 
{
    //just call servo control; it handles the movement of all three servos
    SimpleServoControl();
    
}//loop