SPDT foot pedal to control Hi-hat On/Off Problem (RB Midi Drum kit)

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).

int hatPin = A9;     // Hi-Hat Connected to Analog Pin A9
int switchPin = A10;  // Pedal Switch connected to Analog Pin A10

What Arduino is this?
You cannot analogWrite to analog pins, only to PWM enabled pins.

The specification is a bit confused. What exactly is the SPDT pedal supposed to do in programming terms? And how exactly is it connected? And then what is the other switch/pedal you talk about "the normal pedal Hat sound is connected to a separate Pedal". Where is that in the code?

I'm guessing HAT and HATP may be involved somewhere but the comment on HAT_NOTE seems to suggest that there's another note for the hi-hat that isn't either of those and isn't included in the notemap for some reason.

Steve

Sorry, frustration and being tired didn't help making that post, plus not knowing how to code anything really leaves me in the dark.

It is an Elegoo Mega 2560 R3 and the separate pedal was for either using it as a kick pedal or the pedal hi hat sound. The other pedal which is a momentary foot switch(got it for 5 bucks, thought it would be easy to just wire and use), that was used for changing the analog pins from 9(open midi note) to 10(closed midi note).

I thought posting the code would help, but I take it as it added to confusion to what I posted, originally I had , HatOP (Pin 9) and HatCL (Pin 10), changed it in code and rewired the hat and pedal setup after because it didn't work as intended.

I started to look up on trying to make the Hat change midi notes to the closed hat note when I held the SPDT pedal down, wired the pedal to analog pin 10 and tried to lookup some info and came across the Input Pullup thing, but obviously the code hasn't been finished because I don't have the knowledge of coding to put down.

After ~80 hours of trying to do this, was trying to keep some semblance of a good Edrum kit but now im thinking screw the pedal Idea and just attach another pad with a piezo and call it done.

Sorry.

Posting the code was very useful. Without that we'd have almost no idea what you were talking about. And we really can't help you changing something until we know what you have now. Oh and congratulations for using the correct </> code posting method. You'd be amazed how many people don't bother.

But let's get even more detailed in a programming sort of way...I think what you're trying to do is have a pedal switch connected to pin A10. The switch will either be open or closed (one is going to be pedal up and the other pedal down, I can't tell which from here). INPUT_PULLUP is good, that means it will reliably be HIGH if open and LOW if closed.

When the Hi-hat piezo is hit you want it to send either MIDI note 79 or note 80 depending on whether the pedal switch is open or closed. Is that the basic idea? That's part is pretty easy.

And then there's another more complicated idea where some time AFTER you've triggered the hi-hat and it has sent one MIDI note you can stamp on the switch and it will send the other note even though you haven't hit the HH piezo again. Does it have to do that as well? That's possible but not quite so straightforward.

Of course I'm not a drummer so I may have misunderstood it completely.

Steve

Ok so the Idea for the pedal is to change between notes 79 and 80 for the hi hat.

If the pedal is not pressed, hi hat should stay at midi note 79
If the pedal is held down, the midi note should change to 80

The pedal should not trigger any notes itself, should only change the hi hat's note when held down, when I hit the hi hat and then hold down on the pedal switch the moment after, it should make the next hit on the hi hat change to 80 and should stay to that note if I hold the pedal switch down. If I let go the of the pedal, the moment after the last hit should change back to 79 and stay to that note untill next pedal press.

There should be also little to no delay between me hitting the hi hat before and after holding down on the pedal. I can see that part being somewhat tricky because it has to change rather quickly after the note has fired.

What you want to do is to ignore the state of the switch until the sensor is hit. Then when it is you look at the state of the switch and send one note or the other depending on the state. This will not add any sort of delay you could possibly notice. Sort of like this:-

// sensor is now detecting a hit
if(digitalRead(switchPin) == LOW){
sendMIDI(80);
}
else{
sendMIDI(79);
}

Of course that is not the exact code for the send MIDI functions, and you have to have initialised the switch pin with a pinMode(switchPin, INPUT_PULLUP ) and wire the switch between the input pin and ground.