Keyboard Matrix Decode

I found an old keyboard, a “KSP970” which is a sub £20 keyboard with full size (non touch sensitive) keys, that was being thrown out as battery acid had corroded away most of the circuit board inside, but the keyboard itself was still intact so I thought it would make an interesting project to attempt to read the keyboard.

2020-09-06 19.52.58

2020-09-06 19.53.14

These are the key Arduino tutorials for the main concepts used in this project:

If you are new to Arduino, see the Getting Started pages.

Parts list

  • Arduino Nano
  • 16x LEDs (optional)
  • 8x 220Ω resistors (to go with the LEDs – also optional)
  • Breadboard and jumper wires
  • Scrap keyboard!

The Circuit

Most keyboards and keypads use a “matrix” method of decoding keypresses.  I won’t go into the details here, but the Open Music Labs tutorial has an excellent description of the concept, but the general principle is that the keys are decoded as “rows” and “columns” even though on a music keyboard they are naturally sequential. If you are lucky, as I was, the keyboard will have two sets of connecting wires (see the two silvered ribbon cables in the photo) – one for “rows” and one for “columns” which can be linked up to your Arduino’s IO pins.

The trick is to work out which keys are linked to which pins, which is where this simple circuit comes in.

I have a 61 note keyboard and each of the ribbons is 8 wires wide.  I can see from the underside of the keyboard pcb that each key’s switch is linked via a diode to the “row” pins.  I’ve only shown one key circuit in the above, but the Open Music Lab’s tutorial shows the “matrix” in more detail and the same circuit seems to be used here.

One simplification for me though was that I have several of these really cheap “8 bit” LED “bars” which make decoding the key matrix very easy – they contain 8 LEDs and associated resistors in a breadboard-friendly format.

2020-09-21 20.11.05

My final test circuit looks like this:

2020-09-21 19.49.30

I feed power into the two breadboard rails (5V) and then can work out which keys light up the second set of LEDs and thus map keys to combinations of “rows” and “columns”.  Note, in the above photo I’ve applied power to all of the “rows”, but in practice you’d only want power on one at a time to see which keys light up the other LEDs.

Once I knew how the keys were decoded (it turned out pretty simple and logical) then I could hook it up to an Arduino and see if I could detect keypresses.

NanoKeyboardDecode_bb

I used a Nano which means I could relatively simply attach the two 8-way connectors to the two sides of the board, with one proviso.  I am using the analog ports as digital IO pins, which works fine for A0 to A5, but you can’t use A6 and A7 in that way so I had to re-route the last two pins over to D11 and D12.  As I had a new cheap Nano to use, I was able to desolder the pins on A6 and A7 leaving them unconnected from the 8-way headers.

The Code

Once the Nano was involved, I was able to install the Keypad library for the Arduino (search for Keypad and find the library simply called “Keypad” by Mark Stanley) and modify the MultiKey demo sketch as follows:

  • I need a 8×8 matrix decoding, so the array at the start of the sketch needs updating.
  • As the keys on my keyboard decoded sequentially in a straightforward manner, I didn’t have any complicated reordering of the keys to be done to match up with Arduino pin numbers.
  • I want to eventually output MIDI note numbers, so I changed the characters in the array to MIDI note numbers.
  • On printing, I forced the code to print the MIDI note number rather than the letter names.

My first try had the rows and columns the wrong way round and yielding nothing.  The mapping I eventually used was as follows.

const byte ROWS = 8;
const byte COLS = 8;
char keys[ROWS][COLS] = {
{36,37,38,39,40,41,42,43},
{44,45,46,47,48,49,50,51},
{52,53,54,55,56,57,58,59},
{60,61,62,63,64,65,66,67},
{68,69,70,71,72,73,74,75},
{76,77,78,79,80,81,82,83},
{84,85,86,87,88,89,90,91},
{92,93,94,95,96,97,98,99}
};
byte rowPins[ROWS] = {A0,A1,A2,A3,A4,A5,11,12}; //connect to the row pinouts of the kpd
byte colPins[COLS] = {2,3,4,5,6,7,8,9}; //connect to the column pinouts of the kpd

This seems to work very nicely.  You can see it hooked up and the serial output from playing a “chord” below.

Find it on GitHub here.

Closing Thoughts

Decoding the key presses ended up being relatively simple for this keyboard which was a bonus.  Next I will add the MIDI library and get it actually outputting MIDI messages.

I’ve had a play with the tone generating module, just to get an idea for what it can do (I might write that up one day too), but it isn’t really salvageable.

However the power supply and built-in amplifier and speakers seem fine so it would be really interesting to use this as a housing for some of my other Arduino music projects.

Kevin

Leave a comment