Add MIDI Port to Keyboard

54,467

299

65

About: www.youtube.com/EvanKale91 === www.facebook.com/EvanKale91 === www.twitter.com/EvanKale91 === www.evankale.blogspot.ca

Having a MIDI keyboard will let you control digital audio workstations (DAWs) like Pro tools, FL Studio, Ableton Live, etc. As well, it will connect to a wide variety of MIDI gear such as table top synths.

This tutorial is useful for those who already have a non-MIDI keyboard, and want to upgrade it for music production use.

www.evankale.blogspot.ca

Step 1: Watch the Video!

Here is an 8 minute video with closed captioning that demonstrates all the steps below from start to finish!

Click here to watch on YouTube

Step 2: What You'll Need

  • 1 Arduino UNO, or any Arduino alternative
  • 2 Serial to parallel shift registers
  • Resistors (1 220Ω for the MIDI port, and 6 10kΩ for pull-up resistors - this will depend on step 4)
  • 1 Proto board
  • 1 Female MIDI port
  • 1 Male pin header

And the tools we'll need are breadboards, breadboard jumpers, a multimeter, soldering equipment and wires.

Where to buy

Soldering gear:

Prototype gear:

Step 3: Open the Keyboard

Open up the keyboard, and snip off the ribbon cable from the main board that goes to the keys.

Step 4: Figure Out the Scan Matrix

Put the multimeter on continuity (or resistance) reading. Attach the probes to two pins at a time and sweep the keyboard to find our keys.

For my keyboard, I have a 17 pin ribbon, which I concluded to be a 6x11 scan matrix. To fit all the keys on the Arduino UNO, I'll be combining 11 pins into 3 using 2 shift registers. Then our total input pins is then reduced from 17 to 9.

(The result of this will be different for every keyboard but the procedure will be the same)

Step 5: Setting Up First Shift Register

We'll start with the first shift register.

Wire up the ground and voltage pins as seen in the picture.

Then plug in our Clock, Latch, and Data lines and plug it into the digital pins 8,9,10 of the Arduino. Then we wire up the voltage and ground from the arduino to the board.

Run the first bit of test code from the image. Taking our voltmeter to measure the output of each of the data pins, we should 0 voltage for pins that we are shifting out a 0 and positive voltage for the pins we are shifting out a 1.

Step 6: Daisy Chain Second Shift Register

Once we have our first shift register working, we're going to daisy chain our second one.

We'll wire up the voltage and gnd just like the first one, then hook up the additional data pin of the first chip to the Data pin of the second chip. Then we'll also need to hook up Latch and Clock pins of the two chips (see image).

Now we plug in our Clock, Latch, and Data lines again same way as we did before, and make a small change in our Arduino program to accomodate for the second shift register (see image).

We should see the same alternating pattern with our data pins from this program throughout all of our data pins.

If you're wondering which chip comes first, then simply shift out 8-bits of 0's and 8 bits of 1's at a time and check which chip is outputting the signal.

Step 7: Setting Up Resistors

Hook up the power to our second breadboard.

We're going to extend the first 11 of our data pins from the shift registers to the second board (see image).

Then we're going to bring 6 lines into 6 digital pins of the arduino.

We'll need to add a 10k ohm resistor to ground for each of these lines so that we have a pull-down resistor configuration. This will guarantee that we have the signal we want when the switches on the keyboard are open.

Step 8: Pull Up or Pull Down?

One thing to note, if this direction of current doesn't work for your keyboard, we can switch over to a pull-up resistor configuration by simply doing the following (see the image):

  • First we remove the voltage and ground connection to the shift registers.
  • Then we connect our 6 resistors to positive voltage instead of ground.
  • And we also want to keep the shift register pins connected just the way they are.
  • This will create the pull-up configuration you see in the diagram.

Step 9: Add the Keyboard Ribbon

Plug the cable ribbon into place, matching the rows and columns of the scan matrix.

Step 10: Setting Up MIDI Port

We're going to wire the serial output pin of the port to the serial output of the Arduino, which is pin 1 for the Arduino UNO.

Then we wire up the ground pin and voltage pins like the diagram.

Step 11: Upload Arduino Program

Download the full Arduino code from GitHub (choose the correct version; pull-up or pull-down).

Watch the video from Step 1 at 4:30 - 5:45 to review any necessary changes you need to make to the code in order to get it to work with your specific configuration.

Step 12: Testing

To test our keyboard, we'll plug in our MIDI port to the computer and fire up a MIDI monitor program like MIDI-OX.

We'll hit all the keys to make sure we have everything wired up correctly.

If you don't have a MIDI port, you can get get one of these MIDI to USB adapters (see image) for a few bucks.

Step 13: Transferring to Proto Board

Once everything is working, we're going to transfer everything from our breadboard to the proto board and solder in all the connections.

Plug our wires into the Arduino just the way we had it before, and use the male pin headers here to lock them in place.

Step 14: Putting the Keyboard Back Together

I then traced over the shape of the MIDI and USB ports onto the keyboard case and cut out the hole.

I added a few popsicle sticks to support the Arduino and proto board and hot glued them in place.

Step 15: Final Testing

Plug it in, fire up a DAW, and give it a try!

That's it!

If you liked this instructable, then perhaps you'll like some of my other projects!

You can check them out at Blogspot, or visit my YouTube Channel.

6 People Made This Project!

Recommendations

  • Colors of the Rainbow Contest

    Colors of the Rainbow Contest
  • 1 Hour Challenge

    1 Hour Challenge
  • Frozen Treats Challenge

    Frozen Treats Challenge

65 Discussions

1
None
usamamd0

Question 5 weeks ago

I used pull up config for 8x8 matrix but when I press key , 8 notes appear

0
None
RafdiA

Question 7 months ago

I've make it. But i wasn't able to press 2 keys simultaneously like evan did in the video. It work when i press 2 key that not in same octave like C3 and C5, but won't work if i press C3 and D3. Can anyone help me?

1 answer
0
None
leuprinRafdiA

Answer 2 months ago

Hi, i have the same problem, its possible that it is for the code programm.

0
None
Elixr

2 months ago

Is there a way to add more octaves?

0
None
benwad21

4 months ago on Step 10

One note! In my pull-up configuration of the resistors, a pin 4 midi must be connected via a resistor of 220 ohm to gnd on arduino. Otherwise, it will not work from external power, for example from a battery or power supply.

0
None
DjD29

4 months ago

Como alguém vai aprender alguma coisa se tudo o que está postado é premium se não pagar não aprende e dizem que é livre . LIVRE...?

0
None
DjD29

4 months ago

Não consigo baixar os PDFs e dizem software Livre . Livre da onde ?

0
None
TahaT12

Question 5 months ago

Can someone explain me how to make it with usb instead of midi ?

0
None
SahajJ2

Question 1 year ago on Step 10

Can I skip the midi port and get the keyboard input to my PC via Arduino USB port?

1 answer
0
None
RafdiASahajJ2

Answer 7 months ago

sure you can. If you on windows use app Hairless serial midi bridge

0
None
kooroshi60

7 months ago

Hello Evan
Thank you for sharing this. I built it and it was so amazing to see my Casio PT-80 is upgraded with MIDI. This sketch works flawlessly on ATMega328 but not on ATMega8. Do you have any idea what could be the problem?
I tried using an Arduino Uno as ISP programmer and also burned the output .hex file using AVRISP Mkii but seems like the code does not run on mega8 although the Arduino IDE compiles the sketch for mega8 with no problem.

P.S. Would you please make a video explaining the sketch of this project? I will appreciate it.

0
None
TalhaA48

Question 1 year ago

I did this to a kawaii fs640 61 key 8x8 matrix keyboard using one shift register and my keys are not in sequence how can I fix this?

5 answers
0
None
NeailTalhaA48

Answer 10 months ago

hi Talha, i am having the same problem, i have a 8x6 matrix...but 44 keys and using pulldown config, everything except the sequence is working fine ...1 thing i have noticed that 2 adjacent keys are 1 octave apart...

Have you solved the problem??? Then plz let me know

By the way i am using casio sa76

And if you noticed Evan (the author) have altered the keyboard ribbon to breadboard.

0
None
TalhaA48Neail

Reply 9 months ago

Hi Neail, i couldnt fix the problem with this code so i used another code and modified it according to my piano

// Pin Definitions

// Rows are connected to

const int row1 = 9;

const int row2 = 8;

const int row3 = 7;

const int row4 = 6;

const int row5 = 5;

const int row6 = 4;

const int row7 = 3;

const int row8 = 2;

// The 74HC595 uses a serial communication

// link which has three pins

const int clock = 10;

const int latch = 11;

const int data = 12;

uint8_t keyToMidiMap[64];

boolean keyPressed[61];

int noteVelocity = 127;

// use prepared bit vectors instead of shifting bit left everytime

int bits[] =

{

B01111111,

B10111111,

B11011111,

B11101111,

B11110111,

B11111011,

B11111101,

B11111110

};

// 74HC595 shift to next column

void scanColumn(int value) {

digitalWrite(latch, LOW); //Pulls the chips latch low

shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register

digitalWrite(latch, HIGH); //Pulls the latch high displaying the data

}

void setup() {

// Map scan matrix buttons/keys to actual Midi note number. Lowest num 41 corresponds to F MIDI note.

keyToMidiMap[0] = 40;

keyToMidiMap[1] = 39;

keyToMidiMap[2] = 38;

keyToMidiMap[3] = 37;

keyToMidiMap[4] = 36;

keyToMidiMap[5] = 41;

keyToMidiMap[6] = 46;

keyToMidiMap[7] = 46;

keyToMidiMap[8] = 48;

keyToMidiMap[1 + 8] = 47;

keyToMidiMap[2 + 8] = 46;

keyToMidiMap[3 + 8] = 45;

keyToMidiMap[4 + 8] = 44;

keyToMidiMap[5 + 8] = 43;

keyToMidiMap[6 + 8] = 42;

keyToMidiMap[7 + 8] = 41;

keyToMidiMap[16] = 56;

keyToMidiMap[1 + 16] = 55;

keyToMidiMap[2 + 16] = 54;

keyToMidiMap[3 + 16] = 53;

keyToMidiMap[4 + 16] = 52;

keyToMidiMap[5 + 16] = 51;

keyToMidiMap[6 + 16] = 50;

keyToMidiMap[7 + 16] = 49;

keyToMidiMap[24] = 64;

keyToMidiMap[1 + 24] = 63;

keyToMidiMap[2 + 24] = 62;

keyToMidiMap[3 + 24] = 61;

keyToMidiMap[4 + 24] = 60;

keyToMidiMap[5 + 24] = 59;

keyToMidiMap[6 + 24] = 58;

keyToMidiMap[7 + 24] = 57;

keyToMidiMap[32] = 72;

keyToMidiMap[1 + 32] = 71;

keyToMidiMap[2 + 32] = 70;

keyToMidiMap[3 + 32] = 69;

keyToMidiMap[4 + 32] = 68;

keyToMidiMap[5 + 32] = 67;

keyToMidiMap[6 + 32] = 66;

keyToMidiMap[7 + 32] = 65;

keyToMidiMap[40] = 80;

keyToMidiMap[1 + 40] = 79;

keyToMidiMap[2 + 40] = 78;

keyToMidiMap[3 + 40] = 77;

keyToMidiMap[4 + 40] = 76;

keyToMidiMap[5 + 40] = 75;

keyToMidiMap[6 + 40] = 74;

keyToMidiMap[7 + 40] = 73;

keyToMidiMap[48] = 88;

keyToMidiMap[1 + 48] = 87;

keyToMidiMap[2 + 48] = 86;

keyToMidiMap[3 + 48] = 85;

keyToMidiMap[4 + 48] = 84;

keyToMidiMap[5 + 48] = 83;

keyToMidiMap[6 + 48] = 82;

keyToMidiMap[7 + 48] = 81;

keyToMidiMap[56] = 96;

keyToMidiMap[1 + 56] = 95;

keyToMidiMap[2 + 56] = 94;

keyToMidiMap[3 + 56] = 93;

keyToMidiMap[4 + 56] = 92;

keyToMidiMap[5 + 56] = 91;

keyToMidiMap[6 + 56] = 90;

keyToMidiMap[7 + 56] = 89;

// setup pins output/input mode

pinMode(data, OUTPUT);

pinMode(clock, OUTPUT);

pinMode(latch, OUTPUT);

pinMode(row1, INPUT);

pinMode(row2, INPUT);

pinMode(row3, INPUT);

pinMode(row4, INPUT);

pinMode(row5, INPUT);

pinMode(row6, INPUT);

pinMode(row7, INPUT);

pinMode(row8, INPUT);

Serial.begin(31250);

delay(1000);

}

void loop() {

for (int col = 0; col < 8; col++) {

// shift scan matrix to following column

scanColumn(bits[col]);

// check if any keys were pressed - rows will have HIGH output in this case corresponding

int groupValue1 = digitalRead(row1);

int groupValue2 = digitalRead(row2);

int groupValue3 = digitalRead(row3);

int groupValue4 = digitalRead(row4);

int groupValue5 = digitalRead(row5);

int groupValue6 = digitalRead(row6);

int groupValue7 = digitalRead(row7);

int groupValue8 = digitalRead(row8);

// process if any combination of keys pressed

if (groupValue1 == 0 || groupValue2 == 0 || groupValue3 == 0 || groupValue4 == 0 || groupValue5 == 0 || groupValue6 == 0 || groupValue7 == 0 || groupValue8 == 0) {

if (groupValue1 == 0 && !keyPressed[col]) {

keyPressed[col] = true;

noteOn(0x91, keyToMidiMap[col], noteVelocity);

}

if (groupValue2 == 0 && !keyPressed[col + 8]) {

keyPressed[col + 8] = true;

noteOn(0x91, keyToMidiMap[col + 8], noteVelocity);

}

if (groupValue3 == 0 && !keyPressed[col + 16]) {

keyPressed[col + 16] = true;

noteOn(0x91, keyToMidiMap[col + 16], noteVelocity);

}

if (groupValue4 == 0 && !keyPressed[col + 24]) {

keyPressed[col + 24] = true;

noteOn(0x91, keyToMidiMap[col + 24], noteVelocity);

}

if (groupValue5 == 0 && !keyPressed[col + 32]) {

keyPressed[col + 32] = true;

noteOn(0x91, keyToMidiMap[col + 32], noteVelocity);

}

if (groupValue6 == 0 && !keyPressed[col + 40]) {

keyPressed[col + 40] = true;

noteOn(0x91, keyToMidiMap[col + 40], noteVelocity);

}

if (groupValue7 == 0 && !keyPressed[col + 48]) {

keyPressed[col + 48] = true;

noteOn(0x91, keyToMidiMap[col + 48], noteVelocity);

}

if (groupValue8 == 0 && !keyPressed[col + 56]) {

keyPressed[col + 56] = true;

noteOn(0x91, keyToMidiMap[col + 56], noteVelocity);

}

}

// process if any combination of keys released

if (groupValue1 != 0 && keyPressed[col]) {

keyPressed[col] = false;

noteOn(0x91, keyToMidiMap[col], 0);

}

if (groupValue2 != 0 && keyPressed[col + 8]) {

keyPressed[col + 8] = false;

noteOn(0x91, keyToMidiMap[col + 8], 0);

}

if (groupValue3 != 0 && keyPressed[col + 16]) {

keyPressed[col + 16] = false;

noteOn(0x91, keyToMidiMap[col + 16], 0);

}

if (groupValue4 != 0 && keyPressed[col + 24]) {

keyPressed[col + 24] = false;

noteOn(0x91, keyToMidiMap[col + 24], 0);

}

if (groupValue5 != 0 && keyPressed[col + 32]) {

keyPressed[col + 32] = false;

noteOn(0x91, keyToMidiMap[col + 32], 0);

}

if (groupValue6 != 0 && keyPressed[col + 40]) {

keyPressed[col + 40] = false;

noteOn(0x91, keyToMidiMap[col + 40], 0);

}

if (groupValue7 != 0 && keyPressed[col + 48]) {

keyPressed[col + 48] = false;

noteOn(0x91, keyToMidiMap[col + 48], 0);

}

if (groupValue8 != 0 && keyPressed[col + 56]) {

keyPressed[col + 56] = false;

noteOn(0x91, keyToMidiMap[col + 56], 0);

}

}

}

void noteOn(int cmd, int pitch, int velocity) {

Serial.write(cmd);

Serial.write(pitch);

Serial.write(velocity);

}

0
None
NeailTalhaA48

Reply 9 months ago

I will certainly try this, thanks for the response ..i didnt managed to get the sequence right even repositioning the IC and Arduino connections consecutive keys are a octave apart ...i will try the code and remodel it upto my intellect to get the work done...thank you for the help.

0
None
StéphaneA14Neail

Reply 9 months ago

Hey ! If you can't find any sequence at all, you can fix that by ordering the cables yourself or by modifying the code. In Evan's code, the mapping array is filled automatically because the sequence is perfect.

I tested the process on a M-Audio Oxygen IV which has a 8x8 matrix, and the sequence was not perfect (some keys were sequential thankfully), so I ordered them nicely when I plugged them to the pins and I didn't have to modify too much code. Otherwise you can hardcode the mapping array so it matches your configuration. Then you can test it pretty easily without the midi pin by using the serial monitor and see what happens when you hit the keys. Then you can fix what's wrong either by switching cable positions or by modifying the mapping array. It's pretty simple once you get the logic :)

0
None
NeailStéphaneA14

Reply 9 months ago

its a herculian task to rearrange them though i did but no hope....i think something wrong with the code for my board...as i said no matter what i define the first note it ends 1 octave apart for two consecutive keys.

0
None
StéphaneA14

9 months ago

Hey Evan, thanks for the great tutorial. It looked quite hard at first but I dug deeper and could make it work like a charm :) My keyboard has velocity so the next step is to make it work too (I'm on my way!) but I'm very grateful for your knowledge! I'm also gonna find a way to make modulation wheel and a pitch wheel. Maybe it will be my turn to make an instructable then :D

1
None
JavadK9LayneS4

Answer 1 year ago

Its the same. For example If you have two ribbons with 8 cables each, just think you have one ribbon with 16 cables! :D

Its even easier than having one ribbon! For example if you have two ribbon with 8 cables each then you have 8x8 matrix like me. :) In many cases one ribbon stands for input that should connect to your 74hc595 and the other one stands for output and must connect to your Arduino pins and ground!

Another example: If you have If you have two ribbons with 9 and 4 cables each, Then your matrix goes like this: 9x4 or 4x9!

Best regards.