//***************************************** SET PIN ASSIGNMENT CONFIGURATION OPTIONS**************
const int PINS = 3; // number of signals incoming
const int analogPin[PINS] = {A0,A1,A2};//A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20,A21,}; //array of analog PINs
//***************************************** SET HIGH HAT ZONE CONFIGURATION OPTIONS**************
const int ZONECOUNT = 5 ; // number of zones for FSR as modifier for HH
const int zoneMap[ZONECOUNT] = {40,150,450,800,1024};
const int zoneClose = 800;
//***************************************** SET MIDI NOTE VALUE CONFIGURATION OPTIONS**************
//** two value arrays are for normal piezo in index 0 and HH pedal in index 1 (use !i in as index during PINS loops)
const int thresholdMin[2] = {60,800}; // minimum reading, avoid noise and false starts
const int velocityScaleMax[2] = {1023,1023}; // used to scale velocity as effective maximum
const int peakTrackMillis[2] = {12,55};
const int aftershockMillis[2] = {25,45}; // aftershocks & vibration reject
//***************************************** SET MIDI NOTE VALUE CONFIGURATION OPTIONS**************
const int channel = 10; // General MIDI: channel 10 = percussion sounds
const int note[PINS] = {0,0,36};//37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55}; // array of MIDI note values for read signals (0 placeholders for HH)
const int HHstickNote[ZONECOUNT] = {46,47,48,49,50} ; // note values for flavours of HH from open to closed (no general MIDI for intermediaries so used low values as placeholders)
const int HHsplashNote[ZONECOUNT] = {55,55,55,55,44}; // note values for splash/chick
int zone; // calculated zone
int zoneLag; // zone during last note on event
int state[PINS]; // 0=idle, 1=looking for peak, 2=ignore aftershocks
int peak[PINS]; // remember the highest reading
int piezo[PINS];
elapsedMillis displayLimiter;
elapsedMillis msec[PINS]; // timers to end states 1 and 2
int zoneNote[ZONECOUNT][PINS]; // matrix of note values with zone alterations for HH and it's piezo calc'd during setup
void setup() {
Serial.begin(115200);
while (!Serial && millis() < 2500) /* wait for serial monitor */ ;
Serial.println("Piezo Peak Capture w/ HH pedal");
//*****build matrix to hold zone options (different only for HH and it's piezo)
for (int i=0;i<PINS;i++){
for (int j=0;j<ZONECOUNT;j++){
if (i==0){
zoneNote[j][i] = HHsplashNote[j]; // HH pedal notes
}else if(i==1){
zoneNote[j][i] = HHstickNote[j]; // HH piezo notes
}else{
zoneNote[j][i] = note[i] ; // other piezo - same for all j
}
}
}
}
void loop() {
for (int i=0;i<PINS;i++){
piezo[i] = analogRead(analogPin[i]);
if (i==0){ // calc zone if pin index = 0
int j = 0;
while ( piezo[0]>zoneMap[j] ) {
j++;
}
zone = j;
}
peakDetect(i);
}
// MIDI Controllers should discard incoming MIDI messages.
// http://forum.pjrc.com/threads/24179-...ses-midi-crash
while (usbMIDI.read()) {
// ignore incoming messages
}
}
void peakDetect(int i) {
switch (state[i]) {
// IDLE state: wait for any reading is above threshold. Do not set threshold too low.
case 0:
if (piezo[i] > thresholdMin[!i]) {
peak[i] = piezo[i];
msec[i] = 0;
state[i] = 1;
}
return;
// Peak Tracking state: capture largest reading
case 1:
if (piezo[i] > peak[i]) {
peak[i] = piezo[i];
}
if (msec[i] >= peakTrackMillis[!i]) {
int velocity = map(peak[i], thresholdMin[!i], velocityScaleMax[!i], 1, 127);
usbMIDI.sendNoteOn(zoneNote[zone][i], velocity, channel);
zoneLag = zone;
printMIDI(true, zoneNote[zone][i], velocity, zone, peak[i]);
msec[i] = 0;
state[i] = 2;
}
return;
// Ignore Aftershock state: wait for things to be quiet again.
default:
if (piezo[i] > thresholdMin[i]) {
msec[i] = 0; // keep resetting timer if above threshold
} else if (msec[i] > aftershockMillis[!i]) {
usbMIDI.sendNoteOff(zoneNote[zoneLag][i], 0, channel);
printMIDI(false, zoneNote[zoneLag][i], 0, zone, peak[i]);
state[i] = 0; // go back to idle when
}
}
}
void printMIDI(boolean on, int noteID, int vel, int zone, int peak){
Serial.print("NoteOn: ");
Serial.print(on);
Serial.print(" NoteID: ");
Serial.print(noteID);
Serial.print(" Velocity: ");
Serial.print(vel);
Serial.print(" Zone: ");
Serial.print(zone);
Serial.print(" Peak: ");
Serial.println(peak);
}