Add MIDI Port to Keyboard

45,769

286

55

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

Intro: Add MIDI Port to Keyboard

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.

4 People Made This Project!

Recommendations

  • Optics Contest

    Optics Contest
  • Plastics Contest

    Plastics Contest
  • Audio Contest 2018

    Audio Contest 2018

55 Discussions

0
None
TalhaA48

Question 5 months 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 more answers
0
None
NeailTalhaA48

Answer 2 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 4 weeks 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 23 days 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 4 weeks 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 23 days 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

4 weeks 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 6 months 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.

0
None
StéphaneA14JavadK9

Reply 4 weeks ago

Well it depends ^^ Mine was a bit messy. I had 13 + 4 and thought it could be 13 * 4 matrix (25 keys * 2 for velocity = 50, it would match with 52), but it was not the case lol. It was actually a 8*8 matrix with one pin unused and 4 outputs were on the 13 pins ribbon.

I found an effective way to test all the inputs without using a multimeter (mine was not working well, don't know why). I just set up one output pin and one input pin in an arduino program. I sent high on the output and read the input (connected via a resistor on the bread board). If I detected high on the input, I printed a line on the serial monitor. Then I just had to move the input pins and output pins on the different ribbon pins. Then you can hit the keyboard and see when it prints something. I got all the connections pretty quickly with this method :)

0
None
Nesemis

Question 2 months ago on Step 12

I have serious problems. There are informations on a serial port in very fast rate and I can not do anything about that. It happens even if I plug off everything. I sat for about 40 h on it, I am so tired of this nonsense, I don't know what to do. Anybody, help!

1533469425000397263423.jpg
1 more answer
0
None
NesemisNesemis

Answer 2 months ago

I've finished the project, but still don't know why that happend, the problem just magically disappeared :p

1
None
F.ZAMPIVA

3 years ago on Introduction

hi, I'm trying to do this with a Casio keyboard CTK480.

But I'm not getting, help me?

I have a pull-up 8x8 matrix.

I used only one 74HC595.

I changed the codes ...

But when I press a button detects the Synthesia 8 keys. I do not know how to solve.

6 replies
0
None
JavadK9F.ZAMPIVA

Reply 6 months ago

Change scanColumn method like this maybe solving your problem:

void scanColumn(int colNum)

{

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, MSBFIRST, bits[colNum]);

digitalWrite(latchPin, HIGH);

}

0
None
dalcaroboJavadK9

Reply 3 months ago

I had the same problem, but this solution did not solve. I press a key and the MIDI OX reading is another key. I'm stucked!

0
None
Nesemisdalcarobo

Reply 2 months ago

I have so much problems with my project, but I think I can help with yours.
I assume you have a problem with key mapping. You need to change the value which is assigned to a certain address ( col and row)
In order to do that , go to section below void setup and take those 2 lines:
keyPressed[rowCtr][colCtr] = false;
keyToMidiMap[rowCtr][colCtr] = note;
Delete the section from int note to note++ and two } below

And change the rowctr and colctr to for example 0 , 0 for both lines, and in the place for note try to write for example 36 (which stands for C2)
Upload the sketch, find the key which is C2 and see what should be the mapping. Then for this addres write down the number that should be in the place in sketch where you replaced "note" and repeat the process for each note. Hope someone will help also me, please!

1
None
JavadK9dalcarobo

Reply 2 months ago

First of all check both PullDown & PullUp sheets. If you still have same problem, maybe its because of your connection matrix! For example you didn't connect your row or column respectively to your shift register and arduino pins. Keep working on it ;) The solve is really easy.

0
None
dalcaroboJavadK9

Reply 2 months ago

Mine was pullUp, changed the circuit and software. Works like a charm. Now I changed to Arduino Pro Micro, with a MIDIUSB library, with native USB connection, works much better. Thanks for the reply! (Sorry about english, I'm form Brasil)

0
None
KevW9

Question 3 months ago

It worked fine on the breadboard but once I have made it on the proto board, MIDI-OX displays eight notes when I only hit one key; I noticed that each note of the eight corresponds to one note from each column scanned by the shift register. I made the connections on the proto just the way they were on te breadboard and now I don't know what's going on. Even I tried adding a delay on the shiftOut fuction from the code just to see what's happening and now MIDI-OX keeps displaying the eight notes but slower. Just and example: I hit C#2 and C#2, G2, C#3, G3... appears on the screen not even in order. Please help :c