Midi controlling two servos

I wonder if anyone could help me with code written for one controller and adapt it for two?
The original code takes midi input and rotates one servo to a set position for each midi note received whilst a second servo with a beater attached plays a note on a glockenspiel. Everything runs fine with this setup but I wish to employ a second set of servos to share the load so to speak. Left servo will handle 5 notes and so will the right servo.
This is the original code below for a single set of servos.

// include MIDI library
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

// include libraries for controlling servos and debouncing buttons
#include <Servo.h>
#include <Bounce2.h>

// declare objects to represent the two servos
Servo bigServo;
Servo littleServo;

// declare object to represent the button
Bounce button = Bounce();

// set global variables
int notePositions[] = {109,104,99,94,89,85,79,75};
int beaterRestAngle = 100;
int beaterHitAngle = 117;
int postHitDelay = 50;
int ledPin = 2;

void setup() {
  bigServo.attach(8);
  littleServo.attach(9);
  bigServo.write(90);
  littleServo.write(beaterRestAngle);
  pinMode(ledPin, OUTPUT);
  MIDI.setHandleNoteOn(moveToMidiNote);
  MIDI.setHandleNoteOff(hitBeater);
  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop() {
  MIDI.read();
}

int moveToMidiNote(byte channel, byte midiNote, byte velocity) {
  int noteNum = getGlockNoteFromMidiNote(midiNote);
  if(noteNum >= 0) {
    digitalWrite(ledPin, HIGH);
    bigServo.write(notePositions[noteNum]);
  } else {
    digitalWrite(ledPin, HIGH);
    delay(50);
    digitalWrite(ledPin, LOW);
    delay(50);
  }
}

int hitBeater(byte channel, byte midiNote, byte velocity) {
  int noteNum = getGlockNoteFromMidiNote(midiNote);
  if(noteNum >= 0) {
    digitalWrite(ledPin, LOW);
    littleServo.write(beaterHitAngle);
    delay(postHitDelay);
    littleServo.write(beaterRestAngle);
  } else {
    digitalWrite(ledPin, HIGH);
    delay(50);
    digitalWrite(ledPin, LOW);
    delay(50);
  }
}

int getGlockNoteFromMidiNote(int midiNote) {
  switch(midiNote) {
    case 60:
    return 0;
    case 62:
    return 1;
    case 64:
    return 2;
    case 65:
    return 3;
    case 67:
    return 4;
    case 69:
    return 5;
    case 71:
    return 6;
    case 72:
    return 7;
  }
  return -1;
}

And below is my attempt to double up the code for two sets of servos. However, only four notes from the right servo function and they don't correspond to the correct keys. Can anyone point me in the right direction? Possibly I need to use a different method altogether?
Thanks in advance!

// include MIDI library
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

// include libraries for controlling servos and debouncing buttons
#include <Servo.h>

// declare objects to represent the two servos
Servo bigServoLeft;
Servo littleServoLeft;

Servo bigServoRight;
Servo littleServoRight;

// declare object to represent the button

// set global variables for left servo
int notePositionsLeft[] = {60, 75, 90, 105, 120};
int beaterRestAngleLeft = 126; // (68)
int beaterHitAngleLeft = 115; // (85) 117
int postHitDelayLeft = 50; // (100) 50

// set global variables for right servo
int notePositionsRight[] = {85, 100, 116, 134, 150};
int beaterRestAngleRight = 66; // (68)
int beaterHitAngleRight = 76; // (85) 117
int postHitDelayRight = 100; // (100) 50


void setup() {
  // left servo
  bigServoLeft.attach(8);
  littleServoLeft.attach(9);
  bigServoLeft.write(120);
  littleServoLeft.write(beaterRestAngleLeft);

  // right servo
  bigServoRight.attach(10);
  littleServoRight.attach(11);
  bigServoRight.write(100);
  littleServoRight.write(beaterRestAngleRight);

  // left servo
  MIDI.setHandleNoteOn(moveToMidiNoteLeft);
  MIDI.setHandleNoteOff(hitBeaterLeft);

  // right servo
  MIDI.setHandleNoteOn(moveToMidiNoteRight);
  MIDI.setHandleNoteOff(hitBeaterRight);

  MIDI.begin(MIDI_CHANNEL_OMNI);

}

void loop() {
  MIDI.read();
}

int moveToMidiNoteLeft(byte channel, byte midiNoteLeft, byte velocity) {
  int noteNumLeft = getGlockNoteFromMidiNoteLeft(midiNoteLeft);
  if (noteNumLeft >= 0) {
    bigServoLeft.write(notePositionsLeft[noteNumLeft]);
  } else {
  }
}

int hitBeaterLeft(byte channel, byte midiNoteLeft, byte velocity) {
  int noteNumLeft = getGlockNoteFromMidiNoteLeft(midiNoteLeft);
  if (noteNumLeft >= 0) {
    littleServoLeft.write(beaterHitAngleLeft);
    delay(postHitDelayLeft);
    littleServoLeft.write(beaterRestAngleLeft);
  } else {
  }
}

int moveToMidiNoteRight(byte channel, byte midiNoteRight, byte velocity) {
  int noteNumRight = getGlockNoteFromMidiNoteRight(midiNoteRight);
  if (noteNumRight >= 0) {
    bigServoRight.write(notePositionsRight[noteNumRight]);
  } else {
  }
}

int hitBeaterRight(byte channel, byte midiNoteRight, byte velocity) {
  int noteNumRight = getGlockNoteFromMidiNoteRight(midiNoteRight);
  if (noteNumRight >= 0) {
    littleServoRight.write(beaterHitAngleRight);
    delay(postHitDelayRight);
    littleServoRight.write(beaterRestAngleRight);
  } else {

  }
}

// left servo
int getGlockNoteFromMidiNoteLeft(int midiNoteLeft) {
  switch (midiNoteLeft) {
    case 60:
      return 0;
    case 62:
      return 1;
    case 64:
      return 2;
    case 65:
      return 3;
    case 67:
      return 4;
  }
  return -1;
}
// right servo
int getGlockNoteFromMidiNoteRight(int midiNoteRight) {
  switch (midiNoteRight) {
    case 69:
      return 0;
    case 71:
      return 1;
    case 73:
      return 2;
    case 75:
      return 3;
    case 77:
      return 4;
  }
  return -1;
}

Time for some serial debugging I suspect. Which note doesn't work? What are the wrong ones instead?

On the right servo, case 69, 71 and 77 work respectively to their keys. However, 72 and 74 only respond when keys for 73 and 75 are pressed ( midi keyboard). Left servo isn't responding at all.

It looks like you can't have multiple callbacks. When you set up the right servo, the left one has its callbacks overwritten.

You only have one MIDI object so you can only have one NoteOn and one NoteOff callback.

Since the difference is just in input note numbers you can easily manage the servos by selecting on ranges of note numbers.

Steve

Does this mean I should only use one call back with all the notes shared with both servos?

Ok, following your advice I have come up with a solution that almost works!

// include MIDI library
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

// include libraries for controlling servos and debouncing buttons
#include <Servo.h>

// declare objects to represent the two servos
Servo bigServoLeft;
Servo littleServoLeft;

Servo bigServoRight;
Servo littleServoRight;

// declare object to represent the button

// set global variables for left servo
int notePositionsLeft[] = {60, 75, 90, 105, 120};
int beaterRestAngleLeft = 126; // (68)
int beaterHitAngleLeft = 115; // (85) 117
int postHitDelayLeft = 50; // (100) 50

// set global variables for right servo
int notePositionsRight[] = {85, 100, 116, 134, 150};
int beaterRestAngleRight = 66; // (68)
int beaterHitAngleRight = 76; // (85) 117
int postHitDelayRight = 50; // (100) 50


void setup() {
  // left servo
  bigServoLeft.attach(8);
  littleServoLeft.attach(9);
  bigServoLeft.write(90);
  littleServoLeft.write(beaterRestAngleLeft);

  // right servo
  bigServoRight.attach(10);
  littleServoRight.attach(11);
  bigServoRight.write(116);
  littleServoRight.write(beaterRestAngleRight);

  // left servo
  MIDI.setHandleNoteOn(moveToMidiNote);
  MIDI.setHandleNoteOff(hitBeater);



  MIDI.begin(MIDI_CHANNEL_OMNI);

}

void loop() {
  MIDI.read();
}

int moveToMidiNote(byte channel, byte midiNote, byte velocity) {
  int noteNum = getGlockNoteFromMidiNote(midiNote);
  if (noteNum >= 0 & noteNum <= 4) {
    bigServoLeft.write(notePositionsLeft[noteNum]);
  } else {
  }
  if (noteNum >= 5 & noteNum <= 9) {
    bigServoRight.write(notePositionsRight[noteNum]);
  } else {
  }

}

int hitBeater(byte channel, byte midiNote, byte velocity) {
  int noteNum = getGlockNoteFromMidiNote(midiNote);
  if (noteNum >= 0 & noteNum <= 4) {
    littleServoLeft.write(beaterHitAngleLeft);
    delay(postHitDelayLeft);
    littleServoLeft.write(beaterRestAngleLeft);
  } else {
  }
  if (noteNum >= 5 & noteNum <= 9) {
    littleServoRight.write(beaterHitAngleRight);
    delay(postHitDelayRight);
    littleServoRight.write(beaterRestAngleRight);
  } else {
  }
}


int getGlockNoteFromMidiNote(int midiNote) {
  switch (midiNote) {
    case 60:
      return 0;
    case 62:
      return 1;
    case 64:
      return 2;
    case 65:
      return 3;
    case 67:
      return 4;
    case 69:
      return 5;
    case 71:
      return 6;
    case 72:
      return 7;
    case 74:
      return 8;
    case 76:
      return 9;
  }
  return -1;
}

The left servo functions perfectly to its corresponding notes. The right servo responds to the correct notes but doesn't go to the correct positions exactly. Whilst the positions are sequential, it appears the right servo isn't taking positions from int notePositionsRight[] = {85, 100, 116, 134, 150}; It resets to the correct position of 116 though.

Just solved this issue by adding 5 extra positions to the positions array " int notePositionsRight[] = {0,0,0,0,0,85, 100, 116, 134, 150};" even though this works fine what is a better method to use?

You could subtract 5 from noteNum when you index notePositionsRight. And use the original array.

 bigServoRight.write(notePositionsRight[noteNum - 5]);

a7

I thought of doing this to play glockenspiel, but it wouldn’t really be fast enough, so I’ve done it with solenoids for each key.

This is the prototype.

Thunderstruck on glockenspiel video

@alto777 Thanks for that! Works a charm!
Love the servos Ambient Power!