Newbie needs help with MIDI xylophone

Hello, I'm a technology teacher and quite new to Arduino. I'm actually a phys ed teacher, who has been teaching technology last two years.

I was very inspired by the MIDI xylophone (MIDI Xylophone with Arduino Mega — Johnny Devine) I wanted to try to build my own. I made a few changes like using 32 to pin xylophone that starts on the F note, which is quite a few more notes t used in the inspirational project.

I used MOSFET Button IRF520 to fire the solenoids, instead of 16 relay module boards. I but I'm have a hard time figuring out how to change the code and use the correct MIDI library.

This one's a little bit above my pay grade. I don't exactly understand what I need to change. When I look up the other projects listed MIDI number codes, it seems that his listed number are not actually match the notes. I know he you lower the octaves, but it is just confusing to a som one just learning.

My learning goal is to: have students write MIDI that we can play on the xylophone.

Where I need help here is learning how to program the Arduino, mega to be a USB midi receiver that sends the signal to the correct note. I eat this xylophone has more notes, then the below code.

Declare and define variables

//Pins numbers on Mega and the note they play (relay pin is second number).  h for high, m for middle, and l for low

int hG = 23;   //16
int hFs = 4;   //4
int hF = 22;   //15
int hE = 25;   //14
int hDs = 5;   //5
int hD = 24;   //13
int hCs = 6;   //6
int hC = 27; //12
int hB = 26;  //11
int hAs = 7;  //7
int hA = 29;  //10
int mGs = 8;  //8
int mG = 28;   //9
int mFs = 13;   //13
int mF = 37;   //2
int mE = 34;   //3
int mDs = 12;   //12
int mD = 35;   //4
int mCs = 11; //11
int mC = 32;  //5
int mB = 33;  //6
int mAs = 10;  //10
int mA = 30;  //7
int lGs = 9;  //9
int lG = 31;  //8

//There are 128 notes in MIDI.  43 is the low G on the xylophone
//Midi for lG (or G2, I think) starts on 43 and goes to 67 for hG (or G4)
int baseNote = 32 //The G on the xylophone is actually 43, but I started an octave lower so more notes not on the xylophone still make sound, just an octave lower;

//This is the array of notes that can be played on the xylophone
//Notice that there are two sets of the lowest and highest octaves to catch MIDI notes that are not on the keys.  

Ok, but the code you posted here is a bare variables definition, you should always post the whole code. Or if you mean you use the exact code from that project link except the actual pin definitions, how you mapped the notes is irrilevant for us.

Well, maybe a diagram of the connections you made could help to better understand how you made it and check how can be activated from Arduino pins.
I suppose the hardware part is completed and you made at least some test to check the solenoids are correctly activated to play the notes, did you?

If you used the same pins formerly used with the relays, in theory you need to do nothing. The only difference I see is the xylophone of original project starts with G, and if the picture is from your one, your starts with F so you maybe need some changes to such mapping.

Do you mean you are completely new to Arduino programming (I hope not, we don't write code for third parties...), or you just need to know how to change that original project code to match your hardware?

I have done Arduino projects before, like making lightbulbs blink in different sequences to make signs, making stepper motors with adjustable speed with a dial, and some other beginner projects. MostlyI I have been modified other peoples code.

The physical machine has been completely tested. I used 5 volts the closest circuit to test each the MOSFET Button IRF520, to close the circuit to the 12 V to each solenoid to strike each metal bar.

Music is a type of program, and I have a little bit more experience with, I put the viola in high school. There are seven whole notes in each octave. Essentially want to start at an F on the third 2nd or 3rd octave of a piano. I am not not familiar with pianos.

Original cold below, but to be quick, there are three basic problems.

  • My xylophone has 32 notes. The xylophone in the OG code had less nose. But the author extended the playable notes by having an octave higher and lower play at the same pins. EX) a F note an octave higher than what the instrument had physically available, would use a pin at the same piece of metal and octave lower/Higher.

*Is there an easier way to do this with an existing library?

  • If I change int mF = 37; //2 to my understanding MIDI 37 is the C#/Db of the first octave, which was changed via wiring, just to lower the scale.

If I change it to hit the actual physical metal bar, that vibrates when struck to produce the sound wave of a F note in the octave, int mF = 41; //2 would this work ?
ALSO, the output from the Arduino would be from Pin 2?

If so, I think I could change all the code to hit the keys I want.

/*
  MIDI Xylophone
  
  This program runs on an Arduino Mega and listens for midi signals to be sent over the USB cable from a midi instrument or digital audio workstation application.
  When the Arduino recieves a 'note on' byte, it writes the corresponding pin LOW, triggering the connected relay and solenoid.

  Download the required library at http://fortyseveneffects.github.io/arduino_midi_library/index.html
  This is not the same MIDI libraries found in the library manager.  

  Circuit: GPIO pins on Mega (see below) are connected to the inputs of two 16 relay module boards.  
  GND from the Arduino Mega is connected to ground on the relay modules.  
  The Arduino is powered by the attached USB cable.  
  The relay modules are powered by a 12V ACDC switching power supply.
  A separate 10A 5V power supply is used for the 25 solenoids.  
  GND from the power supply is connected in parallel to the NO terminal of each relay.
  The common of each each relay is connected to its own solenoid.  
  The outputs of all the solenoids join together and connect to 5V on the power supply.  
 
  This is based on the MidiUSB example included with the library  
  Modified by Johnny Devine 2020

*/

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

// -----------------------------------------------------------------------------
//Declare and define variables

//Pins numbers on Mega and the note they play (relay pin is second number).  h for high, m for middle, and l for low

int hG = 23;   //16
int hFs = 4;   //4
int hF = 22;   //15
int hE = 25;   //14
int hDs = 5;   //5
int hD = 24;   //13
int hCs = 6;   //6
int hC = 27; //12
int hB = 26;  //11
int hAs = 7;  //7
int hA = 29;  //10
int mGs = 8;  //8
int mG = 28;   //9
int mFs = 13;   //13
int mF = 37;   //2
int mE = 34;   //3
int mDs = 12;   //12
int mD = 35;   //4
int mCs = 11; //11
int mC = 32;  //5
int mB = 33;  //6
int mAs = 10;  //10
int mA = 30;  //7
int lGs = 9;  //9
int lG = 31;  //8

//There are 128 notes in MIDI.  43 is the low G on the xylophone
//Midi for lG (or G2, I think) starts on 43 and goes to 67 for hG (or G4)
int baseNote = 32 //The G on the xylophone is actually 43, but I started an octave lower so more notes not on the xylophone still make sound, just an octave lower;

//This is the array of notes that can be played on the xylophone
//Notice that there are two sets of the lowest and highest octaves to catch MIDI notes that are not on the keys.  

// -----------------------------------------------------------------------------

//Define what action to take when a 'note on' byte is received 
void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity)
{
  //Only pluck if the midi note is in the range we can play:
  if(inNumber >= baseNote && inNumber < (baseNote + 49)){  //there are actually only 25 keys, but with the extra octave above and below, the total is 49
    byte stringnote = noteList[inNumber - baseNote];
    pluck(stringnote,8);  
  }
  //In setup() we are only listening to channel 1, so that info is not used here.  Neither is velocity, since that is defined as a constant in pluck()
}


void pluck(int stringnote, int velocity)
{
  digitalWrite(stringnote,LOW);
  delay(velocity);  //set to a constant 8ms above, which seems to sound nice on the xylophone keys.
  digitalWrite(stringnote,HIGH);
}

// -----------------------------------------------------------------------------

void setup()
{
  pinMode(hG,OUTPUT);
  pinMode(hFs,OUTPUT);
  pinMode(hF,OUTPUT);
  pinMode(hE,OUTPUT);
  pinMode(hDs,OUTPUT);
  pinMode(hD,OUTPUT);
  pinMode(hCs,OUTPUT);
  pinMode(hC,OUTPUT);
  pinMode(hB,OUTPUT);
  pinMode(hAs,OUTPUT);
  pinMode(hA,OUTPUT);
  pinMode(mGs,OUTPUT);
  pinMode(mG,OUTPUT);
  pinMode(mFs,OUTPUT);
  pinMode(mF,OUTPUT);
  pinMode(mE,OUTPUT);
  pinMode(mDs,OUTPUT);
  pinMode(mD,OUTPUT);
  pinMode(mCs,OUTPUT);
  pinMode(mC,OUTPUT);
  pinMode(mB,OUTPUT);
  pinMode(mAs,OUTPUT);
  pinMode(mA,OUTPUT);
  pinMode(lGs,OUTPUT);
  pinMode(lG,OUTPUT);

  //On the relay module, HIGH is the NC closed state of the relays
  digitalWrite(hG,HIGH);
  digitalWrite(hFs,HIGH);
  digitalWrite(hF,HIGH);
  digitalWrite(hE,HIGH);
  digitalWrite(hDs,HIGH);
  digitalWrite(hD,HIGH);
  digitalWrite(hCs,HIGH);
  digitalWrite(hC,HIGH);
  digitalWrite(hB,HIGH);
  digitalWrite(hAs,HIGH);
  digitalWrite(hA,HIGH);
  digitalWrite(mGs,HIGH);
  digitalWrite(mG,HIGH);
  digitalWrite(mFs,HIGH);
  digitalWrite(mF,HIGH);
  digitalWrite(mE,HIGH);
  digitalWrite(mDs,HIGH);
  digitalWrite(mD,HIGH);
  digitalWrite(mCs,HIGH);
  digitalWrite(mC,HIGH);
  digitalWrite(mB,HIGH);
  digitalWrite(mAs,HIGH);
  digitalWrite(mA,HIGH);
  digitalWrite(lGs,HIGH);
  digitalWrite(lG,HIGH);
  
  MIDI.begin();           // Launch MIDI, by default listening to channel 1.
  
  //Defines what to do when a 'note one' byte is detected during the read in the main loop
  MIDI.setHandleNoteOn(handleNoteOn);
  
  //Note the higher baud rate than is often used (9600)
  Serial.begin(115200);

}

void loop()
{
  
  MIDI.read();
  
  //Some relays were not being written back HIGH at the a strike, putting the soelnoids at risk of being burned out.
  //I was afraid these digitalWrites() would destroy the latency, but it still seems to move quickly enough.  
  digitalWrite(hG,HIGH);
  digitalWrite(hFs,HIGH);
  digitalWrite(hF,HIGH);
  digitalWrite(hE,HIGH);
  digitalWrite(hDs,HIGH);
  digitalWrite(hD,HIGH);
  digitalWrite(hCs,HIGH);
  digitalWrite(hC,HIGH);
  digitalWrite(hB,HIGH);
  digitalWrite(hAs,HIGH);
  digitalWrite(hA,HIGH);
  digitalWrite(mGs,HIGH);
  digitalWrite(mG,HIGH);
  digitalWrite(mFs,HIGH);
  digitalWrite(mF,HIGH);
  digitalWrite(mE,HIGH);
  digitalWrite(mDs,HIGH);
  digitalWrite(mD,HIGH);
  digitalWrite(mCs,HIGH);
  digitalWrite(mC,HIGH);
  digitalWrite(mB,HIGH);
  digitalWrite(mAs,HIGH);
  digitalWrite(mA,HIGH);
  digitalWrite(lGs,HIGH);
  digitalWrite(lG,HIGH);

}

Also, just so you guys know, I'm recovering from brain cancer and have dyslexia. Sorry for any misspellings.

Good. The thing I was concerned for is if the solenoids are still LOW-activated.

I play keyboards, and I have some experience with MIDI (but not with Arduino actually), so I know that topic a bit.

As far as I can understand, the code seems to simply match the pins used to play the notes with the MIDI note number via the "noteList" array (be aware in your code you haven't included the array, the line "int nodeList[]=..." is missing! Also a semicolon after "int baseNote = 32"), so all those variables are "constants" and are there just to fill the array in and to set pinMode and reset all the pins to HIGH, nothing more.
This means you could make any change you want, like changing the correspondance between note and pin, but to extend the number of notes you need nothing special than add the new notes constants and add them to the array.

Yes, you just need to change "baseNote" to match yours (you said your xylophone has a lower F instead of G so "baseNote should be two less, or 30), define your extra notes in the first section of the code, together with the corresponding pin number, and put them inside the "noteList" array. You also need to add them to the "pinMode" setting and to the two parts of the code where write HIGH to make sure all the solenoids are off.

But to make the code more easier, I made some changes and extensions to the original one, so have a look at the below version, where you can see the differences (you'll find a very simpler setup and loop!):

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

// -----------------------------------------------------------------------------
//Declare and define variables
//Pins numbers on Mega and the note they play (relay pin is second number).  h for high, m for middle, and l for low
const int hhC = ??; // pin for higher C
const int hhB = ??; // pin for higher B
const int hhAs= ??; // pin for higher A#
const int hhA = ??; // pin for higher A
const int hGs = ??; // pin for higher G#
const int hG  = 23; //16
const int hFs = 4;  //4
const int hF  = 22; //15
const int hE  = 25; //14
const int hDs = 5;  //5
const int hD  = 24; //13
const int hCs = 6;  //6
const int hC  = 27; //12
const int hB  = 26; //11
const int hAs = 7;  //7
const int hA  = 29; //10
const int mGs = 8;  //8
const int mG  = 28; //9
const int mFs = 13; //13
const int mF  = 37; //2
const int mE  = 34; //3
const int mDs = 12; //12
const int mD  = 35; //4
const int mCs = 11; //11
const int mC  = 32; //5
const int mB  = 33; //6
const int mAs = 10; //10
const int mA  = 30; //7
const int lGs = 9;  //9
const int lG  = 31; //8
const int lFs = ??; // pin for lower F#
const int lF  = ??; // pin for lower F

// The low F on the xylophone is 41, but we start an octave lower so more 
// notes not on the xylophone still make sound, just an octave lower;
const int baseNote = 30;

// The number of notes on the array
const int MAX_NOTES = 48;
//This is the array of notes that can be played on the xylophone
//Notice that there are two sets of the lowest and highest octaves to catch MIDI notes that are not on the keys.  
int noteList[MAX_NOTES] = {
  lF,lFs,lG,lGs,mA,mAs,mB,mC,mCs,mD,mDs,mE, // LOWER EXTENSION
  lF,lFs,lG,lGs,mA,mAs,mB,mC,mCs,mD,mDs,mE,
  mF,mFs,mG,mGs,hA,hAs,hB,hC,hCs,hD,hDs,hE,
  hF,hFs,hG,hGs,hhA,hhAs,hhB,hhC,
  hCs,hD,hDs,hE // HIGHER EXTENSION
  };

// -----------------------------------------------------------------------------

//Define what action to take when a 'note on' byte is received 
void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity)
{
  //Only pluck if the midi note is in the range we can play:
  // NOTE: changed from 49 to 56: 32 keys with the extra octave above and 
  // below (24 additional notes)
  if(inNumber >= baseNote && inNumber < (baseNote + 56)){  
    byte stringnote = noteList[inNumber - baseNote];
    pluck(stringnote,8);  
  }
  //In setup() we are only listening to channel 1, so that info is not used here.  Neither is velocity, since that is defined as a constant in pluck()
}


void pluck(int stringnote, int velocity)
{
  digitalWrite(stringnote,LOW);
  delay(velocity);  //set to a constant 8ms above, which seems to sound nice on the xylophone keys.
  digitalWrite(stringnote,HIGH);
}

void resetSolenoids() 
{
  for(inti=0; i<MAX_NOTES; ++i)
    digitalWrite(noteList[i],HIGH);
}

void setSolenoids()
{
  for(inti=0; i<MAX_NOTES; ++i)
    pinMode(noteList[i],OUTPUT);
  resetSolenoids();
}
// -----------------------------------------------------------------------------

void setup()
{
  setSolenoids();
  
  // Launch MIDI, by default listening to channel 1.
  MIDI.begin();
  
  //Defines what to do when a 'note one' byte is detected during the read in the main loop
  MIDI.setHandleNoteOn(handleNoteOn);
  
  //Note the higher baud rate than is often used (9600)
  Serial.begin(115200);

}

void loop()
{
  
  MIDI.read();
  
  //Some relays were not being written back HIGH at the a strike, putting the soelnoids at risk of being burned out.
  //I was afraid these digitalWrites() would destroy the latency, but it still seems to move quickly enough.  
  resetSolenoids();
}

Fill the required pin numbers, and give it a try (I haven't tested...) and feel free to ask me anything about it).

1 Like

Thank you so much,

I'll try to get on it this week. It's the end of the year it's getting harder and harder to get things done in the classroom on preps. Are you taking this then home to work on it.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.