Easier way to make routines?

hello, I am making a robot face type thing and I'm trying to make it sing along to some songs. (by singing I mean the song playing through speakers while the mouth moves) Is there an easier way to code the routines for singing??
Code Below, I only have a couple of movements set up right now.

#include <Servo.h>

Servo jaw;

Servo righteye;

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

int pos = 0;    // variable to store the servo position

void setup() 
{
  jaw.attach(9);

  lefteye.attach(8);

  righteye.attach(10); 
}
void loop()
{
  for (pos = 90; pos <= 145; pos += 1) { 
    jaw.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for (pos = 145; pos >= 90; pos -= 1) { 
    jaw.write(pos);              
    delay(15);                       
  }
  for (pos = 0; pos <= 45; pos += 1) {
    righteye.write(pos);
    lefteye.write(pos);
    delay(15);
  }
  for (pos = 90; pos <= 145; pos += 1) {
    jaw.write(pos);
    delay (15); 
  }
  for (pos = 45; pos <= 0; pos -= 1) {
    righteye.write(pos);
    lefteye.write(pos);
    delay (15);
  }
}

The easiest is something like below; it's not the perfect solution.

/*
move the jaw
In:
  start position
  end position
*/
void moveJaw(int start, int end)
{
  int step = 0;
  if(start < end)
  {
    step = 1;
  }
  else if (start > end)
  {
    step = -1;
  }

  if (step == 0)
  {
    // nothing to do
    return;
  }


  int pos = start;
  do
  {
    jaw.write(pos);
    pos += step;
    delay(15);

  } while (pos != end);
}

It does not use a for loop but a do/while loop; the condition checks for equal and will might not work reliably if step is not 1 or -1. step is calculated on the two positions and determines the direction.
The position (pos) is incremented by the specified step; if step is negative it is actually a decrement.

You call this function from loop() with the desired parameters instead of using the for loop. You can write a moveEyes() function similar to moveJaw().

Compiles for an Uno but not tested.

Along the same lines

#include <Servo.h>

Servo jaw;
Servo rightEye;
Servo leftEye;

void setup()
{
    Serial.begin(115200);
    jaw.attach(9);
    leftEye.attach(8);
    rightEye.attach(10);
    moveJaw(20, 160, 1, 20);
    moveEyes(10, 170, 2, 10);
}

void loop()
{
}

void moveJaw(int from, int to, int increment, int wait)
{
    for (int s = from; s < to; s += increment)
    {
        jaw.write(s);
        delay(wait);
    }
}

void moveEyes(int from, int to, int increment, int wait)
{
    for (int s = from; s < to; s += increment)
    {
        leftEye.write(s);
        rightEye.write(s);
        delay(wait);
    }
}

I did contemplate that but decided against it; what if to is smaller than from? s < 0 has to change to s > 0.

Good point

However, I suspect that @anarchistjester has bigger problems than that if they are trying to synchronise the mouth and eye movements with a song

Absolutely; that's why I stated

i'll post this code, but it may be very difficult for you to grasp.

looks like you want to coordinate the movements of various servos to do animation and have started writing a program to do that. but each loop performs just one animation.

i think you'll quickly realize, if you haven't already, that multiple servos may need to start at different times and before one servo has completed it's movement.

others have already suggested code to move a servo to a specified "target" position and to update all servos to move toward their target whether clockwise or ccw

in the code below uses "tables", arrays of C strutures (pg 114).

the feature [] table maintains a description of a servo, it's current position and target position. servoUpdate() is called to move it toward its target position if not at that position.

the 2nd table, movement [] describes a sequence of positions and the delay between steps (i.e. speed), allowing multiple movements at the same time, starting at different/overlapping times.

the goal is to provide the underlying support to specify a sequence of movements -- an animation -- by editing the sequence without getting bogged down with coding of specific servo functions

no doubt you'll have questions which i'm more than willing to answer if you'll take the time to understand this approach.

// animation

# include <Servo.h>

unsigned long msec;

char s [90];

// -----------------------------------------------------------------------------
// servo descriptions

enum { F_Jaw, F_LeftEye, F_RightEye };

struct Feature {
    const byte      PinServo;
    int             pos;
    const char     *desc;

    int             posTarg;
    unsigned long   msec0;
    unsigned long   msecDelay;
    Servo           servo;
}
feature [] = {
    {  9,  90, "jaw" },
    { 10,   0, "left-eye" },
    { 11,   0, "right-eye" },
};
int Nfeature = sizeof(feature)/sizeof(Feature);

// -------------------------------------
unsigned long msecUpdt;

void servoUpdate ()
{
    for (int n = 0; n < Nfeature; n++)  {
        int dPos = feature [n].posTarg - feature [n].pos;

#if 0
        sprintf (s, " servoUpdate: %2d, dPos %6d, %6d %6d, %8lu %8lu msec  %s", 
                                n, dPos,
                                feature [n].posTarg, feature [n].pos,
                                feature [n].msec0, msec,
                                feature [n].desc);
        Serial.println (s);
#endif

        if (0 != dPos)  {
            if (msec - feature [n].msec0 < feature [n].msecDelay)
                break;

            feature [n].msec0 += feature [n].msecDelay;

            if (0 < dPos)
                feature [n].pos++;
            else if (0 > dPos)
                feature [n].pos--;
            feature [n].servo.write (feature [n].pos);
        }
    }
}

// -----------------------------------------------------------------------------
struct Movement {
    unsigned long   msec;
    unsigned        featureIdx;
    int             posTarg;
    unsigned long   msecDelay;
    const char     *desc;
}
movement [] {
    {     0, F_Jaw,      145,  15, "open jaw" },
    {   500, F_RightEye,  45,  15, "move right eye left" },
    {   500, F_LeftEye,   45,  15, "move left  eye left" },
    {  1000, F_Jaw,       90,  15, "close jaw" },
    {  1200, F_RightEye,   0,  15, "move right eye right" },
    {  1200, F_LeftEye,    0,  15, "move left  eye right" },
};
int Nmovement = sizeof(movement)/sizeof(Movement);

// -----------------------------------------------------------------------------
unsigned long msecMovement0;
int           mIdx;

void loop ()
{
    msec = millis ();
    
    // update new feature movements
    if (msec - msecMovement0 >= movement [mIdx].msec)  {
        Serial.println (movement [mIdx].desc);

        int fIdx                 = movement [mIdx].featureIdx;

        feature [fIdx].posTarg   = movement [mIdx].posTarg;
        feature [fIdx].msecDelay = movement [mIdx].msecDelay;

        if (Nmovement <= ++mIdx)  {     // restart sequence
            mIdx          = 0;
            msecMovement0 = msec;
            Serial.println ("restart sequence");
        }
    }

    // update servo positions
    servoUpdate ();
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin   (115200);
    Serial.println ("animation");

    for (int n = 0; n < Nfeature; n++)  {
        feature [n].servo.attach  (feature [n].PinServo);
        feature [n].servo.write   (feature [n].pos);

        feature [n].posTarg = feature [n].pos;
    }
}