Moving 10 servos with pca9685, arduino uno, and midi

Hello, everybody. I'm new here. I wrote some pretty bad code, and had ChatGPT improve it. Here is the current code:

#include <MIDI.h>  // Add Midi Library
#include <Wire.h> // Add library allows to communicate with I2C devices
#include <Adafruit_PWMServoDriver.h> // Add 16-channel PWM & Servo driver library

#define SERVOMIN     200
#define SERVOMAX     400
#define FREQUENCY    50

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

MIDI_CREATE_DEFAULT_INSTANCE();

// Function Declarations
void NoteOn(byte channel, byte pitch, byte velocity);
void NoteOff(byte channel, byte pitch, byte velocity);

void setup() {
  pwm.begin();
  pwm.setPWMFreq(FREQUENCY);

  MIDI.begin(MIDI_CHANNEL_OMNI);
  Serial.begin(115200);
  MIDI.turnThruOff();
  MIDI.setHandleNoteOn(NoteOn);
  MIDI.setHandleNoteOff(NoteOff);
}

void loop() {
  // Your code here
}

// move servos - note on
void NoteOn(byte channel, byte pitch, byte velocity) {
  if (channel == 0) { // MIDI channel 1
    switch (pitch) {
      case 60: pwm.setPWM(1, 0, SERVOMAX); break;
      case 61: pwm.setPWM(2, 0, SERVOMAX); break;
      case 62: pwm.setPWM(3, 0, SERVOMAX); break;
      case 63: pwm.setPWM(4, 0, SERVOMAX); break;
      case 64: pwm.setPWM(5, 0, SERVOMAX); break;
      case 65: pwm.setPWM(6, 0, SERVOMAX); break;
      case 66: pwm.setPWM(7, 0, SERVOMAX); break;
      case 67: pwm.setPWM(8, 0, SERVOMAX); break;
      case 68: pwm.setPWM(9, 0, SERVOMAX); break;
      case 69: pwm.setPWM(10, 0, SERVOMAX); break;
      default: break; // Handle other pitches if needed
    }
  }
}

// move servos - note off
void NoteOff(byte channel, byte pitch, byte velocity) {
  if (channel == 0) { // MIDI channel 1
    switch (pitch) {
      case 60: pwm.setPWM(1, 0, SERVOMIN); break;
      case 61: pwm.setPWM(2, 0, SERVOMIN); break;
      case 62: pwm.setPWM(3, 0, SERVOMIN); break;
      case 63: pwm.setPWM(4, 0, SERVOMIN); break;
      case 64: pwm.setPWM(5, 0, SERVOMIN); break;
      case 65: pwm.setPWM(6, 0, SERVOMIN); break;
      case 66: pwm.setPWM(7, 0, SERVOMIN); break;
      case 67: pwm.setPWM(8, 0, SERVOMIN); break;
      case 68: pwm.setPWM(9, 0, SERVOMIN); break;
      case 69: pwm.setPWM(10, 0, SERVOMIN); break;
      default: break; // Handle other pitches if needed
    }
  }
}

I keep changing my methods. Currently, I'm using a program called Noteur to play the MIDI files. Note, I am VERY new to this stuff. My hardware is as follows: Arduino Uno, PCA9685, Correct wiring, 10 servos total, a pipe organ base (holds micro servos) - 8 notes (1 servo per note) - 3d printed to control organ pipes using valves that uncover and cover pipe feet, 2 3d printed drum mallets on stands, controlled by micro servos.

I cannot fine-tune all of the servo positions because of my main problem: No matter what program I use, COM5 (my current Arduino USB PC end port). I have all the required libraries. (MIDI is FourtySevenEffects' library). If anybody can help with either the code or the MIDI mapping problem, please let me know. I would really appreciate it!

Welcome and thanks for using code tags in your first post :+1:

That sounds like an incomplete sentence. Can you try to rephrase what the actual problem is?

A wiring diagram might also be useful (photo of hand drawn is fine); don't forget all power connections and power supplies.

Which servos are you using?

Thanks for such a quick reply. Sorry for any mistakes. I didn't have time to look back over the post before I had to leave to go somewhere. Mine is based on a sketch in a YouTube video. The differences are that I'm using a 5v 4 AA battery pack, and have 10 servos hooked up (brown side towards the outside), and I'm technically using an ELEGOO brand UNO R3 instead of the microcontroller shown in the image. All of the ports I hooked up are the same, using male-female wires for Arduinos/microcontrollers.


I am powering my ELEGOO with a USB-B to USB-A as stated earlier. My motors move a little when I turn on the battery pack.

Did you try the servo example included with that Adafruit library?

No! Great point! How did I not think about that?! I'm going to try that right now. Thanks!

As I recall, it goes through the servos one at a time. You'll see it.

Wow it looks really cool, thanks. Now I know the servos work! Sadly, I am still confused about how to route the midi channels though.

GUYS I GOT IT THANK YOU SO MUCH! I found a midi mapper yesterday, but it didn't work. Today, I restarted my pc and BAM, IT WORKED!

P.S. I also fixed my code.

1 Like

Ok so to specify, I meant the test code. I sent those out of order because I had one in my clipboard. I got the RX light on my Arduino to light up when I send an input using my AKAI MPK MINI Pro. The servos don't move though. I don't get any errors sadly... Once again, the code (not fine-tuned):

#include <MIDI.h>  // Add Midi Library
#include <Wire.h> // Add library allows to communicate with I2C devices
#include <Adafruit_PWMServoDriver.h> // Add 16-channel PWM & Servo driver library

#define SERVOMIN     200
#define SERVOMAX     400
#define FREQUENCY    50

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

MIDI_CREATE_DEFAULT_INSTANCE();

// Function Declarations
void NoteOn(byte channel, byte pitch, byte velocity);
void NoteOff(byte channel, byte pitch, byte velocity);

void setup() {
  pwm.begin();
  pwm.setPWMFreq(FREQUENCY);

  MIDI.begin(MIDI_CHANNEL_OMNI);
  Serial.begin(115200);
  MIDI.turnThruOff();
  MIDI.setHandleNoteOn(NoteOn);
  MIDI.setHandleNoteOff(NoteOff);
}

void loop() {

}

// move servos - note on
void NoteOn(byte channel, byte pitch, byte velocity) {
  Serial.print("Note On: ");
  Serial.print("Channel: "); Serial.print(channel);
  Serial.print(", Pitch: "); Serial.print(pitch);
  Serial.print(", Velocity: "); Serial.println(velocity);

  if (channel == 0) {
    switch (pitch) {
      case 60: pwm.setPWM(1, 0, SERVOMAX); break;
      case 62: pwm.setPWM(2, 0, SERVOMAX); break;
      case 64: pwm.setPWM(3, 0, SERVOMAX); break;
      case 65: pwm.setPWM(4, 0, SERVOMAX); break;
      case 67: pwm.setPWM(5, 0, SERVOMAX); break;
      case 69: pwm.setPWM(6, 0, SERVOMAX); break;
      case 71: pwm.setPWM(7, 0, SERVOMAX); break;
      case 72: pwm.setPWM(8, 0, SERVOMAX); break;
      case 74: pwm.setPWM(9, 0, SERVOMAX); break;
      case 76: pwm.setPWM(10, 0, SERVOMAX); break;
      default: break;
    }
  }
}

void NoteOff(byte channel, byte pitch, byte velocity) {
  Serial.print("Note Off: ");
  Serial.print("Channel: "); Serial.print(channel);
  Serial.print(", Pitch: "); Serial.print(pitch);
  Serial.print(", Velocity: "); Serial.println(velocity);

  if (channel == 0) {
    switch (pitch) {
      case 60: pwm.setPWM(1, 0, SERVOMIN); break;
      case 62: pwm.setPWM(2, 0, SERVOMIN); break;
      case 64: pwm.setPWM(3, 0, SERVOMIN); break;
      case 65: pwm.setPWM(4, 0, SERVOMIN); break;
      case 67: pwm.setPWM(5, 0, SERVOMIN); break;
      case 69: pwm.setPWM(6, 0, SERVOMIN); break;
      case 71: pwm.setPWM(7, 0, SERVOMIN); break;
      case 72: pwm.setPWM(8, 0, SERVOMIN); break;
      case 74: pwm.setPWM(9, 0, SERVOMIN); break;
      case 76: pwm.setPWM(10, 0, SERVOMIN); break;
      default: break;
    }
  }
}

I think I may have a solution. I ordered a 9 volt D battery holder for arduinos that plug in to the barrel plug. I'm using the same port to power and send two separate pieces of information to, so I think only one comes through.