Last active
June 7, 2020 16:35
-
-
Save codetinkerhack/4585458 to your computer and use it in GitHub Desktop.
Arduino based Velocity sensitive Midi keyboard with Aftertouch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Pin Definitions | |
// Rows are connected to Digital | |
const int rowPin[] = { 6, 7, 8, 5 }; | |
// FSRs connected to Analog | |
const int fsrPin[] = { 2, 3, 4, 5 }; | |
// The 74HC595 uses a serial communication | |
// link which has three pins | |
const int clock = 12; | |
const int latch = 13; | |
const int data = 11; | |
int keyToMidiMap[32]; | |
boolean keyPressed[32]; | |
int noteChannelPressed[4][64]; | |
int notesChannel[4] = { 0, 0, 0, 0 }; | |
// use prepared bit vectors instead of shifting bit left everytime | |
int bits[] = { B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000 }; | |
int fsrValue[4]; | |
unsigned long currentMillis; | |
unsigned long previousMillisChannel[4] = { 0, 0, 0, 0 }; | |
// miliseconds delay before aftertouch sent | |
unsigned long expressionDelay=1000; | |
// 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] = 48; | |
keyToMidiMap[1] = 41; | |
keyToMidiMap[2] = 42; | |
keyToMidiMap[3] = 43; | |
keyToMidiMap[4] = 44; | |
keyToMidiMap[5] = 45; | |
keyToMidiMap[6] = 46; | |
keyToMidiMap[7] = 47; | |
keyToMidiMap[8] = 56; | |
keyToMidiMap[1 + 8] = 49; | |
keyToMidiMap[2 + 8] = 50; | |
keyToMidiMap[3 + 8] = 51; | |
keyToMidiMap[4 + 8] = 52; | |
keyToMidiMap[5 + 8] = 53; | |
keyToMidiMap[6 + 8] = 54; | |
keyToMidiMap[7 + 8] = 55; | |
keyToMidiMap[16] = 64; | |
keyToMidiMap[1 + 16] = 57; | |
keyToMidiMap[2 + 16] = 58; | |
keyToMidiMap[3 + 16] = 59; | |
keyToMidiMap[4 + 16] = 60; | |
keyToMidiMap[5 + 16] = 61; | |
keyToMidiMap[6 + 16] = 62; | |
keyToMidiMap[7 + 16] = 63; | |
keyToMidiMap[24] = 72; | |
keyToMidiMap[1 + 24] = 65; | |
keyToMidiMap[2 + 24] = 66; | |
keyToMidiMap[3 + 24] = 67; | |
keyToMidiMap[4 + 24] = 68; | |
keyToMidiMap[5 + 24] = 69; | |
keyToMidiMap[6 + 24] = 70; | |
keyToMidiMap[7 + 24] = 71; | |
// setup pins output/input mode | |
pinMode(data, OUTPUT); | |
pinMode(clock, OUTPUT); | |
pinMode(latch, OUTPUT); | |
pinMode(rowPin[0], INPUT); | |
pinMode(rowPin[1], INPUT); | |
pinMode(rowPin[2], INPUT); | |
pinMode(rowPin[3], INPUT); | |
Serial.begin(31250); | |
delay(1000); | |
} | |
void loop() { | |
currentMillis = millis(); | |
getNote(); | |
sendChannelExpression(); | |
sendChannelNotes(); | |
} | |
void sendChannelExpression() { | |
for (int c = 0; c < 4; c++) { | |
if (currentMillis - previousMillisChannel[c] > expressionDelay) { | |
midiChannelExpression(c, fsrValue[c]); | |
} | |
} | |
} | |
void readChannelPressure(int channel) { | |
int sensor = analogRead(fsrPin[channel]); | |
if (sensor > 0) { | |
fsrValue[channel] = map(sensor, 0, 900, 10, 127); //log(sensor2)*30+abs(sensor2); | |
} | |
} | |
void sendChannelNotes() { | |
for (int i = 0; i < 4; i++) { | |
readChannelPressure(i); | |
if (notesChannel[i] > 0 && (currentMillis > previousMillisChannel[i])) { | |
for (int t = 0; t < notesChannel[i]; t++) { | |
if (keyPressed[noteChannelPressed[i][t]] == true) | |
noteOn(i, keyToMidiMap[noteChannelPressed[i][t]], fsrValue[i]); | |
} | |
notesChannel[i] = 0; | |
} | |
} | |
} | |
void getNote() { | |
for (int i = 0; i < 8; i++) { | |
scanColumn(bits[i]); | |
for (int t = 0; t < 4; t++) { | |
int groupValue = digitalRead(rowPin[t]); | |
// key pressed | |
if (groupValue != 0 && !keyPressed[8 * t + i]) { | |
keyPressed[8 * t + i] = true; | |
// put the note into buffer | |
previousMillisChannel[t] = currentMillis; | |
noteChannelPressed[t][notesChannel[t]] = 8 * t + i; | |
notesChannel[t]++; | |
} | |
// key released | |
if (groupValue == 0 && keyPressed[8 * t + i]) { | |
keyPressed[8 * t + i] = false; | |
noteOn(t, keyToMidiMap[8 * t + i], 0); | |
} | |
} | |
} | |
} | |
void noteOn(int channel, int pitch, int velocity) { | |
command(0x90 + channel, pitch, velocity); | |
} | |
void midiChannelExpression(int channel, int value) { | |
// Modulation wheel effect | |
command(0xB0 + channel, 0x01, value); | |
} | |
void command(int cmd, int value1, int value2) { | |
Serial.write(cmd); | |
Serial.write(value1); | |
Serial.write(value2); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment