Skip to content

Instantly share code, notes, and snippets.

@felixroos
Created February 14, 2021 18:08
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felixroos/cd7111d1b1a2ba7e381b82faf6abb9e2 to your computer and use it in GitHub Desktop.
Save felixroos/cd7111d1b1a2ba7e381b82faf6abb9e2 to your computer and use it in GitHub Desktop.
arduino keyboard scanner
#include "MIDIUSB.h"
bool debug = 0;
int maxPressTime = 250;
int minVelocity = 10;
int maxVelocity = 90;
int midiChannel = 0;
int keys[98] = {
31, 29,
56, 59,
80, 83,
104, 107,
92, 95,
68, 71,
44, 47,
8, 11,
20, 23,
58, 57,
82, 81,
106, 105,
94, 93,
70, 69,
46, 45,
10, 9,
22, 21,
48, 51,
72, 75,
96, 99,
84, 87,
60, 63,
36, 39,
0, 3,
12, 15,
50, 49,
74, 73,
98, 97,
86, 85,
62, 61,
38, 37,
2, 1,
14, 13,
55, 53,
79, 77,
103, 101,
91, 89,
67, 65,
43, 41,
7, 5,
19, 17,
54, 52,
78, 76,
102, 100,
90, 88,
66, 64,
42, 40,
6, 4,
18, 16
};
unsigned long pressStart[49] = {};
bool pressed[49] = {};
void setup() {
Serial.begin(9600);
//select pins
// ABC of INPUT
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
// ABC of OUTPUTs
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
// from keyboard (9 pin)
pinMode(5, INPUT); // gray
digitalWrite(5, HIGH); // pullup
pinMode(6, INPUT); // yellow
digitalWrite(6, HIGH); // pullup
// to keyboard (12 pin)
pinMode(7, OUTPUT); // green
pinMode(8, OUTPUT); // green
}
void set4051(int pinA, int pinB, int pinC, int channel) {
// A = least significant bit
// bitRead also starts from least significant bit
digitalWrite(pinA, bitRead(channel, 0));
digitalWrite(pinB, bitRead(channel, 1));
digitalWrite(pinC, bitRead(channel, 2));
}
void loop() {
for (int n = 0; n < 98; n++) {
int k = keys[n];
// for finding out order of keys, comment out above line and rename n to k
int i = k / 12;
int o = k % 12;
int readPin = bitRead(i, 3) == 0 ? 6 : 5;
set4051(10, 11, 12, i);
set4051(2, 3, 4, o);
digitalWrite(7, bitRead(o, 3));
digitalWrite(8, !bitRead(o, 3));
bool isConnected = digitalRead(readPin) == LOW;
bool isDown = n % 2 == 1;
int keyIndex = n / 2;
int midi = keyIndex + 38;
bool isPressed = pressed[keyIndex] == 1;
// keypress starts
if (isConnected && !isPressed && !isDown && !pressStart[keyIndex]) {
if (debug) {
Serial.print("start pressing ");
}
pressStart[keyIndex] = millis();
}
// key is now fully pressed
if (isConnected && !isPressed && isDown) {
unsigned long pressTime = millis() - pressStart[keyIndex];
float f = (1 - (float)pressTime / (float)maxPressTime);
int velocity = f * (maxVelocity - minVelocity) + minVelocity;
if (debug) {
Serial.print("done pressing ");
Serial.println(f);
}
pressed[keyIndex] = 1;
if (pressTime <= maxPressTime) { // min velocity?
noteOn(midiChannel, midi, velocity);
MidiUSB.flush();
if (debug) {
Serial.print("on ");
Serial.print(midi);
Serial.println(" ");
}
}
}
// key is now fully unpressed
if (!isConnected && isPressed && !isDown) {
pressed[keyIndex] = 0;
noteOff(midiChannel, midi, 0);
MidiUSB.flush();
if (debug) {
Serial.print("off ");
Serial.print(midi);
Serial.print(" ");
Serial.println(" ");
}
}
// key is unpressed => may include keypresses that have started but did not go down
if (!isConnected && !isDown) {
pressStart[keyIndex] = 0; // reset time when key is released completely
}
}
}
void noteOn(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOn);
}
void noteOff(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOff);
}
@godbless876
Copy link

Hey... How can I implement this using a 61 keybed . without using multiplexer

@felixroos
Copy link
Author

Hey... How can I implement this using a 61 keybed . without using multiplexer

have you already taken it apart? how many ins and outs are on the pcb? what's your microcontroller?

@godbless876
Copy link

Thanks for the reply.. yes I have 8x8x8 matrix for a 61key novation ks4

@godbless876
Copy link

And a I was using a teensy 3.2 but I have 2 megas and some nanos and picos

@felixroos
Copy link
Author

Thanks for the reply.. yes I have 8x8x8 matrix for a 61key novation ks4

for 8x8 without multiplexer, you'd need 8 digital outputs and 8 digital inputs. if you have 2 multuplexers (1 to select input and 1 to select output), you'd only need 6 outputs and 2 inputs on your microcontroller.. btw arduino micro is good because it's already a compliant usb device

@godbless876
Copy link

Ok. I will get some of those then

@godbless876
Copy link

I guess 8x 16 is the correct way to say it.. 8 ins 16 outs

@felixroos
Copy link
Author

I guess 8x 16 is the correct way to say it.. 8 ins 16 outs

okay then you'd probably need 3 multiplexers (cd4051) + 9 digital i/o pins:

3 outputs to set the input channel of the mux1
3 outputs to set the output channels of mux2 + mux3 (can be connected together)
1 output to write the input of mux1
1 input to read the output of mux2
1 input to read the output mux3

maybe I am slightly off, but I guess you could double check yourself

@RandyRyanG
Copy link

How would I change the code to work with 25 keys with out the multiplexers?

@felixroos
Copy link
Author

How would I change the code to work with 25 keys with out the multiplexers?

that depends on your microcontroller pins and the exact arrangement of your keyboard pcb.. I cannot write the code for you, but I could give you some hints if you get stuck with a more specific problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment