Hello Everyone,
Been Trying to tackle at this for a little while now, The whole drum kit was pretty simple to make minus the inclusion for the SPDT Pedal to switch the Hat Open/Closed (the normal pedal Hat sound is connected to a separate Pedal), I originally had the hat connected to the pedal and the pedal going to pin A9 and A10 in which both Hat sounds where going off at the same time.
I have since rewired the Hat piezo to go to Pin A9 and the SPDT Pedal to A10 to ground with the Input Pullup using that to try and control the Midi note change, but my lack of Programming knowledge stops me in my tracks into how to make the pedal control the Midi notes, been looking at other codes to try and understand but after countless hours, still can't do it.
This is the first sort of programming I've ever done, I got the code from Evan Kale's video and understood how to add more piezos and what not, but the pedal Open/Closed just threw everything into chaos.
Here's the whole code with what I got to so far with trying to add the Input Pullup stuff.
//Piezo defines
#define NUM_PIEZOS 10
#define SNARE_THRESHOLD 120 //anything < TRIGGER_THRESHOLD is treated as 0
#define TOM1_THRESHOLD 120
#define TOM2_THRESHOLD 120
#define TOM3_THRESHOLD 120
#define KICK_THRESHOLD 120
#define CYM1_THRESHOLD 80
#define CYM2_THRESHOLD 80
#define CYM3_THRESHOLD 80
#define HATP_THRESHOLD 120
#define HAT_THRESHOLD 50
#define START_SLOT 0 //first analog slot of piezos
#define START_NOTE 70 //starting note
//MIDI note defines for each trigger
#define SNARE_NOTE 70
#define TOM1_NOTE 71
#define TOM2_NOTE 72
#define TOM3_NOTE 73
#define KICK_NOTE 74
#define CYM1_NOTE 75
#define CYM2_NOTE 76
#define CYM3_NOTE 77
#define HATP_NOTE 78
#define HAT_NOTE 79 //HAT SWITCHES MIDI NOTES BETWEEN 79/80.(CLOSED/OPEN HAT)
//MIDI defines
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127
//MIDI baud rate
#define SERIAL_RATE 31250
//Program defines
//ALL TIME MEASURED IN MILLISECONDS
#define SIGNAL_BUFFER_SIZE 100
#define PEAK_BUFFER_SIZE 30
#define MAX_TIME_BETWEEN_PEAKS 10
#define MIN_TIME_BETWEEN_NOTES 50
//map that holds the max slots of the piezos
unsigned short slotMap[NUM_PIEZOS];
//map that holds the respective note to each piezo
unsigned short noteMap[NUM_PIEZOS];
//map that holds the respective threshold to each piezo
unsigned short thresholdMap[NUM_PIEZOS];
//Ring buffers to store analog signal and peaks
short currentSignalIndex[NUM_PIEZOS];
short currentPeakIndex[NUM_PIEZOS];
unsigned short signalBuffer[NUM_PIEZOS][SIGNAL_BUFFER_SIZE];
unsigned short peakBuffer[NUM_PIEZOS][PEAK_BUFFER_SIZE];
boolean noteReady[NUM_PIEZOS];
unsigned short noteReadyVelocity[NUM_PIEZOS];
boolean isLastPeakZeroed[NUM_PIEZOS];
unsigned long lastPeakTime[NUM_PIEZOS];
unsigned long lastNoteTime[NUM_PIEZOS];
int hatPin = A9; // Hi-Hat Connected to Analog Pin A9
int switchPin = A10; // Pedal Switch connected to Analog Pin A10
int val = 0; //variable to store the read value
void setup()
{
Serial.begin(SERIAL_RATE);
{
pinMode(A10, INPUT_PULLUP); //Sets the digital pin A10 as Input
analogWrite(A10, HIGH); //Pedal is Pressed
}
{
pinMode(hatPin, OUTPUT); //sets the Analog pin A9 as output
pinMode(switchPin, INPUT); //sets the Analog pin A10 as input
}
//initialize globals
for(short i=0; i<NUM_PIEZOS; ++i)
{
currentSignalIndex[i] = 0;
currentPeakIndex[i] = 0;
memset(signalBuffer[i],0,sizeof(signalBuffer[i]));
memset(peakBuffer[i],0,sizeof(peakBuffer[i]));
noteReady[i] = false;
noteReadyVelocity[i] = 0;
isLastPeakZeroed[i] = true;
lastPeakTime[i] = 0;
lastNoteTime[i] = 0;
slotMap[i] = START_SLOT + i;
}
thresholdMap[0] = KICK_THRESHOLD;
thresholdMap[1] = TOM1_THRESHOLD;
thresholdMap[2] = TOM2_THRESHOLD;
thresholdMap[3] = TOM3_THRESHOLD;
thresholdMap[4] = SNARE_THRESHOLD;
thresholdMap[5] = CYM1_THRESHOLD;
thresholdMap[6] = CYM2_THRESHOLD;
thresholdMap[7] = CYM3_THRESHOLD;
thresholdMap[8] = HATP_THRESHOLD;
thresholdMap[9] = HAT_THRESHOLD;
noteMap[0] = KICK_NOTE;
noteMap[1] = TOM1_NOTE;
noteMap[2] = TOM2_NOTE;
noteMap[3] = TOM3_NOTE;
noteMap[4] = SNARE_NOTE;
noteMap[5] = CYM1_NOTE;
noteMap[6] = CYM2_NOTE;
noteMap[7] = CYM3_NOTE;
noteMap[8] = HATP_NOTE;
noteMap[9] = HAT_NOTE;
}
void loop()
{
{
analogWrite(A10, HIGH); //sets the analog pin A10 on
analogWrite(A10, LOW); //sets the analog pin A10 off
}
{
val = analogRead(switchPin); // read the input pin
analogWrite(hatPin, val); // sets the Hat to the Switch's value
}
unsigned long currentTime = millis();
for(short i=0; i<NUM_PIEZOS; ++i)
{
//get a new signal from analog read
unsigned short newSignal = analogRead(slotMap[i]);
signalBuffer[i][currentSignalIndex[i]] = newSignal;
//if new signal is 0
if(newSignal < thresholdMap[i])
{
if(!isLastPeakZeroed[i] && (currentTime - lastPeakTime[i]) > MAX_TIME_BETWEEN_PEAKS)
{
recordNewPeak(i,0);
}
else
{
//get previous signal
short prevSignalIndex = currentSignalIndex[i]-1;
if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;
unsigned short prevSignal = signalBuffer[i][prevSignalIndex];
unsigned short newPeak = 0;
//find the wave peak if previous signal was not 0 by going
//through previous signal values until another 0 is reached
while(prevSignal >= thresholdMap[i])
{
if(signalBuffer[i][prevSignalIndex] > newPeak)
{
newPeak = signalBuffer[i][prevSignalIndex];
}
//decrement previous signal index, and get previous signal
prevSignalIndex--;
if(prevSignalIndex < 0) prevSignalIndex = SIGNAL_BUFFER_SIZE-1;
prevSignal = signalBuffer[i][prevSignalIndex];
}
if(newPeak > 0)
{
recordNewPeak(i, newPeak);
}
}
}
currentSignalIndex[i]++;
if(currentSignalIndex[i] == SIGNAL_BUFFER_SIZE) currentSignalIndex[i] = 0;
}
}
void recordNewPeak(short slot, short newPeak)
{
isLastPeakZeroed[slot] = (newPeak == 0);
unsigned long currentTime = millis();
lastPeakTime[slot] = currentTime;
//new peak recorded (newPeak)
peakBuffer[slot][currentPeakIndex[slot]] = newPeak;
//1 of 3 cases can happen:
// 1) note ready - if new peak >= previous peak
// 2) note fire - if new peak < previous peak and previous peak was a note ready
// 3) no note - if new peak < previous peak and previous peak was NOT note ready
//get previous peak
short prevPeakIndex = currentPeakIndex[slot]-1;
if(prevPeakIndex < 0) prevPeakIndex = PEAK_BUFFER_SIZE-1;
unsigned short prevPeak = peakBuffer[slot][prevPeakIndex];
if(newPeak > prevPeak && (currentTime - lastNoteTime[slot])>MIN_TIME_BETWEEN_NOTES)
{
noteReady[slot] = true;
if(newPeak > noteReadyVelocity[slot])
noteReadyVelocity[slot] = newPeak;
}
else if(newPeak < prevPeak && noteReady[slot])
{
noteFire(noteMap[slot], noteReadyVelocity[slot]);
noteReady[slot] = false;
noteReadyVelocity[slot] = 0;
lastNoteTime[slot] = currentTime;
}
currentPeakIndex[slot]++;
if(currentPeakIndex[slot] == PEAK_BUFFER_SIZE) currentPeakIndex[slot] = 0;
}
void noteFire(unsigned short note, unsigned short velocity)
{
if(velocity > MAX_MIDI_VELOCITY)
velocity = MAX_MIDI_VELOCITY;
midiNoteOn(note, velocity);
midiNoteOff(note, velocity);
}
void midiNoteOn(byte note, byte midiVelocity)
{
Serial.write(NOTE_ON_CMD);
Serial.write(note);
Serial.write(midiVelocity);
}
void midiNoteOff(byte note, byte midiVelocity)
{
Serial.write(NOTE_OFF_CMD);
Serial.write(note);
Serial.write(midiVelocity);
}
Honestly was fun building this beast though.
Thanks. (sorry if it was wordy, just trying to explain).