#technology #music
CTK 2500 to MIDI
I have been progressing steadily in guitar playing for the past two years and recently decided to pick up the piano as well to expand my knowledge of chords & scales. So while packing for college, as well as bringing my guitar and audio interface, I brought my Casio CTK-2500 electric keyboard with me.
I play my audio through a computer so I can produce songs/jam loops, as well as to simply play quietly. One problem with this is that the CTK-25001 does not support MIDI. I don’t know why it doesn’t support MIDI. It supports an app which enables MIDI playback integration, but for whatever reason Casio decided not to add a MIDI plug to this keyboard. I figured it wouldn’t be too hard to wire up the keyboard to support MIDI.
Parts List
- Microcontroller: I used a Teensy 4.1, an arduino-compatible microcontroller that is more than sufficient for reading and driving multiple pins and sending real time MIDI to a computer.
- 10k ohm resistors: Needed for pull-down resistor support. Internal pull-down resistors did not settle fast enough for real time use. You can maybe go lower to 4.7k.
- An assorted selection of wires: For wiring pins
- Solder kit: For making reliable connections to the board.
Process
The basic idea behind the project is that whenever you press a key, a signal is sent over a wire. If I can route those signals to the microcontroller and send that data over USB to a computer, then I can mimic a MIDI device.
The CTK-2500 is a 61 key piano. It would be a hassle to have 61 individual traces inside a PCB, so this keyboard (and indeed, most digital keyboards) uses a scanning matrix. The link above provides a great explanation about how a scanning matrix works, but in short you can think of it as a grid of n + m traces, with n rows that are driven (scanned) by a voltage, and m columns which are read. Each intersection of a row and column corresponds to an individual key, and so with an nxm matrix you can support a maximum of nxm total inputs for a fraction of the total traces. At each intersection is a switch, where current is allowed to pass from the row to the column by a completed connection. A diode is also placed in series to prevent the current flowing backwards to prior intersections and activating keys that aren’t actually activated.
We can disconnect the 16 wires from the PCB and wire each one to a breadboard to test the connections with a multimeter. This process is rather time consuming but after testing an octave’s worth of keys, a pattern begins to present itself, as shown below:
/*
8 7 6 5 4 3 2 1
16 C1 C#1 D1 D#1 E1 F1 F#1 G1
15 G#1 A1 A#1 B1 C2 C#2 D2 D#2
14 E2 F2 F#2 G2 G#2 A2 A#2 B2
13 C3 C#3 D3 D#3 E3 F3 F#3 G3
12 G#3 A3 A#3 B3 C4 C#4 D4 D#4
11 E4 F4 F#4 G4 G#4 A4 A#4 B4
10 C5 C#5 D5 D#5 E5 F5 F#5 G5
9 G#5 A5 A#5 B5 C6
*/
// Board Pin 16, 15, 14, 13, 12, 11, 10, 9, 8
const int rowPins[] = {38, 39, 40, 41, 14, 15, 16, 17};
// Board Pin 8, 7, 6, 5, 4, 3, 2, 1
const int colPins[] = {18, 19, 20, 21, 22, 23, 26, 25};
const int8_t noteTable[8][8] = {
{ 24, 25, 26, 27, 28, 29, 30, 31 }, // row 16: C1 C#1 D1 D#1 E1 F1 F#1 G1
{ 32, 33, 34, 35, 36, 37, 38, 39 }, // row 15: G#1 A1 A#1 B1 C2 C#2 D2 D#2
{ 40, 41, 42, 43, 44, 45, 46, 47 }, // row 14: E2 F2 F#2 G2 G#2 A2 A#2 B2
{ 48, 49, 50, 51, 52, 53, 54, 55 }, // row 13: C3 C#3 D3 D#3 E3 F3 F#3 G3
{ 56, 57, 58, 59, 60, 61, 62, 63 }, // row 12: G#3 A3 A#3 B3 C4 C#4 D4 D#4
{ 64, 65, 66, 67, 68, 69, 70, 71 }, // row 11: E4 F4 F#4 G4 G#4 A4 A#4 B4
{ 72, 73, 74, 75, 76, 77, 78, 79 }, // row 10: C5 C#5 D5 D#5 E5 F5 F#5 G5
{ 80, 81, 82, 83, 84, -1, -1, -1 } // row 9: G#5 A5 A#5 B5 C6 (unused)(unused)(unused)
};
Note that the board pin numbers correspond to the numberings 1 through 16 printed on the PCB, but is otherwise arbitrary. The row and column pins correspond to the pins of the Teensy. Your mileage may vary. Also note that with 16 pins, we have a maximum of 64 (8x8) total connections. But since we only have 61 keys, three of the matrix positions go unused. The note table values correspond to absolute MIDI note values. By design, The CTK-2500 does not the contacts required per key for recording velocity values so we provide a set velocity value which is not pictured above.
The code for this project can be found here. I won’t explain it here in detail, but it is quite simple. Within the loop() function, the rows are driven HIGH one after another. The column pins are then checked (with a simple logic to factor in debouncing), and if a note is played or is not being played, a MIDI signal is sent to the computer. By using the usbMIDI library and the MIDI USB type, the program works on startup when the USB is plugged in and the Teensy is powered by the USB connection, so it is quite literally plug and play.
Final thoughts
This was quite a simple project but enjoyable. The one downside of this build was that I had to disconnect the keyboard from the main PCB itself, which means the main keyboard no longer operates independently. However, a good further project could include wiring the speakers to the Teensy to enable independent playback (assuming a power source is provided, which is a problem that should be approached with special care). Additionally, the buttons on the front of the panel are connected to the PCB by an additional 16 pins, which likely correspond to another scanning matrix. These could be repurposed into the Teensy to provide more extended functionality, such as MIDI effects, octave and velocity adjustments, different independent sounds, etc. The segment display could in theory be rewired too, but probably isn’t worth the hassle.
Footnotes
-
While this model is currently discontinued, this principle can be applied to most digital keyboards without MIDI support. ↩