HELP WITH WIRING A SUSTAIN PEDAL TO BE USED AS A HI HAT PEDAL AND CODES FOR IT

I am new to arduino, wirings and codes, but luckily I was able to make my own USB MIDIdrums using piezos connected to my laptop running superior drummer on my MAGIX: Music Maker MX via HAIRLESS MIDI + MIDI YOKE. I was able to make it work just by following the guides I’ve found at http://www.instructables.com/id/Arduino-Xylophone/ I made a slight changes on its codes since my setup was a little different. It is working fine, but I’m planning to buy a sustain pedal momentary/on/off type https://www.amazon.com/Stage-KSP100-Universal-Sustain-Pedal/dp/B001ELP5WM to be able to control the hi hat by stepping the pedal to close the hi hat and vice versa. If someone could give me some advice with the wirings on how to connect a 1/4 mono to be able to connect the pedal to arduino and if I need additional stuff like resistors etc, and to add a code for it I would really appriciate it.

By the way, this is the code I’m using with Hairless MIDI:

int pinRead;
char pinAssignments[16] ={
 'A0','A1','A2','A3','A4','A5','A6','A7','A8','A9','A10','A11'};
byte PadNote[16] = {
 57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72};         // MIDI notes from 0 to 127 (Mid C = 60)
int PadCutOff[16] = 
{
 400,400,200,800,400,400,400,400,400,400,400,400,400,400,400,400};           // Minimum Analog value to cause a drum hit
int MaxPlayTime[16] = {
 90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90};               // Cycles before a 2nd hit is allowed
#define  midichannel 1;                              // MIDI channel from 0 to 15 (+1 in "real world")
boolean VelocityFlag  = true;                           // Velocity ON (true) or OFF (false)

//*******************************************************************************************************************
// Internal Use Variables
//*******************************************************************************************************************
boolean activePad[16] = {
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};                   // Array of flags of pad currently playing
int PinPlayTime[16] = {
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};                     // Counter since pad started to play
byte status1;

int pin = 0;     
int hitavg = 0;
//*******************************************************************************************************************
// Setup
//*******************************************************************************************************************
void setup() 
{
 Serial.begin(57600);                                  // SET HAIRLESS TO THE SAME BAUD RATE IN THE SETTINGS

}
//*******************************************************************************************************************
// Main Program
//*******************************************************************************************************************
void loop() 
{
 for(int pin=0; pin < 16; pin++)                          //
 {
   //int pin = 3;
   //   for (pinRead=0; pinRead < 16, pin++){
   hitavg = analogRead(pinAssignments[pin]);  
   //Serial.println(hitavg);   
   // read the input pin

   if((hitavg > PadCutOff[pin]))
   {
     if((activePad[pin] == false))
     {
       if(VelocityFlag == true)
       {
         //          hitavg = 127 / ((1023 - PadCutOff[pin]) / (hitavg - PadCutOff[pin]));    // With full range (Too sensitive ?)
         hitavg = (hitavg / 8) -1 ;                                                 // Upper range
       }
       else
       {
         hitavg = 127;
       }
       MIDI_TX(144,PadNote[pin],hitavg); //note on

       PinPlayTime[pin] = 0;
       activePad[pin] = true;
     }
     else
     {
       PinPlayTime[pin] = PinPlayTime[pin] + 1;
     }
   }
   else if((activePad[pin] == true))
   {
     PinPlayTime[pin] = PinPlayTime[pin] + 1;
     if(PinPlayTime[pin] > MaxPlayTime[pin])
     {
       activePad[pin] = false;
       MIDI_TX(144,PadNote[pin],0); 
     }
   }
 } 
}

//*******************************************************************************************************************
// Transmit MIDI Message
//*******************************************************************************************************************
void MIDI_TX(byte MESSAGE, byte PITCH, byte VELOCITY) 
{
 status1 = MESSAGE + midichannel;
 Serial.write(status1);
 Serial.write(PITCH);
 Serial.write(VELOCITY);

}

You connect the peddle with the tip to an Arduino input pin and the ring to ground. Then you set up the pin as an input with the internal pull up resistors enabled in the setUp function.

Then a digitalRead of that pin will give you a HIGH if the peddle is not depressed and a LOW when it is.

Use this information to send a CC 66 message with the data as 00 for off or 0x7f for on.

Note to prevent you flooding the system with messages only send the CC 66 message when the state of the switch changes. That is save the state of the switch last time round the loop and only send the CC 66 when the current reading of the switch is not the same as the last reading.

Please read this:-
How to use this forum
Because your post is breaking the rules about posting code.

Thank you for your reply, I'm sorry if I've posted the codes improperly, I've corrected it already. Thank you for letting me know how to wire the jack for connecting the pedal to Arduino, but sorry for my stupidity, I just don't know how I would go about writing and adding the codes to my existing sketch and to where or what line I'm supposed to write or add it. I tried to read more about the examples found in Arduino software about INPUT_PULLUP, I kinda understand how it works but my problem is how do I go about writing the exact code, and the If and Then coding to program the switch to send a CC, I mean I'm a complete novice with codes, and I'm thinking of searching the internet for lessons, tutorials, how-tos. I bought the Arduino board from someone without a box that I think includes some paper works like a manual or something. Sorry for giving you so much trouble, I'm willing to learn more about Arduino to be good at it just like you guys.

I'm sorry if I've posted the codes improperly, I've corrected it already.

Thanks a lot for that.

to where or what line I'm supposed to write or add it

OK - line that sets the pin you want to use as an input and sets the pull up option is the pinMode call. It goes in the setUp function, anywhere will do.

The code that looks at this pin and acts on the value it sees goes in the loop function at the very beginning before the for loop that scans the sensors.

to send a CC

To send a CC message you call the void MIDI_TX() function. You pass it three parameters, the CC message byte of 0xB0, the CC channel you want to send, your case 66, and finally the data you want to send it. In your case the data will be either 0 or 0x7F depending if you want it on or off.

So you look at the switch with a digitalRead call and write a CC 66 message of 0 or 0x7F depending on what you find by using the "if" structure.

So do that, post your code and you will be ready for the final touch to complete what you want.

Note numbers that have the prefix 0x are numbers written in the base 16 or in hex. We use that to make things easy although beginners often prefer to tie them selves in knots rather than apply a little effort.

I hope you appreciate I am trying to teach you something here, and not just give you the six lines of code that this represents.

i think there might be a slight misunderstanding here... of course connection wise everything that grumpy mike suggests is right, however code wise it should not be cc 66 (as used for sustain in midi) but a midi note on command, and a note off command once the pedal is released. so the code will be slightly different. in the original post it says:

I'm planning to buy a sustain pedal momentary/on/off type https://www.amazon.com/Stage-KSP100-Universal-Sustain-Pedal/dp/B001ELP5WM to be able to control the hi hat by stepping the pedal to close the hi hat and vice versa.

that suggests he wants to control the hi hat open close drum sound via midi. but i have no idea what note number that would be...

that suggests he wants to control the hi hat open close drum sound via midi. but i have no idea what note number that would be…

A good point.
However if that is true then it is not the note on / note off that needs to be changed but the program number. As no program number ( voice ) is defined anywhere in the code he needs to know what two voices he wants to switch between. The solution is still the same but instead of sending two CC messages you replace these with two program change messages.

ah ok. i thought there is some kind of midi drum standard. midi note 60 (c) is a high bongo and c# is a low bongo etc. the question is if he uses something like this. here is a link: Computer Music: General MIDI Percussion Key Map

that would suggest to send two note ons (and offs) number 42 for closed hat and 46 for open hat.

i thought there is some kind of midi drum standard. midi note 60 (c) is a high bongo and c# is a low bongo etc.

There is, but that is only applicable on MIDI channel 10, the original code showed that he was using MIDI channel 2:-
#define midichannel 1;

Note to actually use channel 1 then that line would have to be:-
#define midichannel 0;

For MIDI percussion you very rarely send note off messages.

Grumpy_Mike:
There is, but that is only applicable on MIDI channel 10, the original code showed that he was using MIDI channel 2:-
#define midichannel 1;

Note to actually use channel 1 then that line would have to be:-
#define midichannel 0;

For MIDI percussion you very rarely send note off messages.

that makes sense :slight_smile:

so i guess the question to the op boils down to:

what kind of message does superior drummer expect to close and open the hi hat?

Thanks for all the replies. First of all, I want to say how glad I am to receive help in this community specially for a newbie like me. You guys have explained the things I need to know with my setup very well, I am now trying to study these things you guys taught me. I'll go back to the sketch and apply what you guys taught me and hopefully when I go back home from vacation I would be able to make the pedal work as a hi hat controller. I will let you guys know of the result, and about what kind of message superior drummer expects, I think I can figure that out myself, I will also let you guys know. Thank you very much.

Hi guys, I just want to let you know that I’ve found a better code for my setup and it is working pretty well. However I’m still having the same problem. I can’t figure out how I would go about changing the code for controlling the hi hat, it seems that this code is programmed to control hi hat open/close on digitalpin # 3 using an ordinary push button. I’m almost done with my work, the only thing that I need is the code for controlling the hi hat using a momentary switch that I already have. I’m also done with soldering a 1/4 jack for connecting my pedal switch to my Arduino MEGA, I’ve connected it to digital pin # 2. If someone could edit this code and add the INPUT_PULLUP code for my momentary pedal switch, I can just copy and paste it to my sketch and my work will be completed and I will thank you a million times. Here’s the code by the way.

/*ROB HENRY /DEADASTRONAUTFX 'NANO-8 PAD KIT...8 PADS IN CHRONOLOGICAL ORDER.
* // TEMPLATE FOR EZDRUMMER 'BASIC'KIT, works on ALL EZDRUMMER KITS
* // HI HAT OPENS ONLY WHEN HIT VERSION.
* // WITH HI HAT OPEN/CLOSED CONTROL VIA MOMENTARY SWITCH socket 9.
* //
* // 8 piece DRUM KIT.
* // HI HAT CONTROL USES PAD 4.
* // 8 PADS / PAD 4 (which uses 2 sounds) FOR HI HAT CONTROL . (when used with momentary switch)
// (SEE LINES 129&231=22)TO CHANGE CLOSED HAT SOUND)
*/



//Piezo defines
#define NUM_PIEZOS 8
#define PAD1_THRESHOLD 10
#define PAD2_THRESHOLD 10
#define PAD3_THRESHOLD 10
#define PAD4_THRESHOLD 10
#define PAD5_THRESHOLD 10 //MIN/MAX VELOCITIES/sensitivity...
#define PAD6_THRESHOLD 10
#define PAD7_THRESHOLD 10
#define PAD8_THRESHOLD 10


#define START_SLOT 0 //0 START ANALOG INPUTS

//MIDI note defines for each trigger
#define PAD1_NOTE 34 //pad1 kick + // <these are the assigned midi notes, change to suit.
#define PAD2_NOTE 38 //pad2 snare +
#define PAD3_NOTE 49 //pad3 crash 1
#define PAD4_NOTE 17 //pad4 HAT SWITCHES MIDI NOTES BETWEEN 17/22.(CLOSED/OPEN HAT) 
#define PAD5_NOTE 53 //pad5 ride bell + //(SEE LINES 129&231=22)TO CHANGE CLOSED HAT SOUND
#define PAD6_NOTE 91 //pad6 ride cymbal + MIDI NOTE NUMBERS..
#define PAD7_NOTE 47 //pad7 mid tom 
#define PAD8_NOTE 41 //pad8 lo floor tom


//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 50
#define PEAK_BUFFER_SIZE 10
#define MAX_TIME_BETWEEN_PEAKS 10
#define MIN_TIME_BETWEEN_NOTES 10

//map that holds the mux 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];

//Variables used for switch mod
byte hihat_switch = 0;
unsigned long switch_pressed = 0;

void setup()
{
Serial.begin(SERIAL_RATE);
//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] = PAD1_THRESHOLD;
thresholdMap[1] = PAD2_THRESHOLD;
thresholdMap[2] = PAD3_THRESHOLD;
thresholdMap[3] = PAD4_THRESHOLD; //hi hat switch controlled
thresholdMap[4] = PAD5_THRESHOLD;
thresholdMap[5] = PAD6_THRESHOLD;
thresholdMap[6] = PAD7_THRESHOLD;
thresholdMap[7] = PAD8_THRESHOLD;
noteMap[0] = PAD1_NOTE;
noteMap[1] = PAD2_NOTE;
noteMap[2] = PAD3_NOTE;
noteMap[3] = PAD4_NOTE; // hi hat switch controlled
noteMap[4] = PAD5_NOTE;
noteMap[5] = PAD6_NOTE;
noteMap[6] = PAD7_NOTE;
noteMap[7] = PAD8_NOTE;

}

void loop()
{
unsigned long currentTime = millis();

if(currentTime > (switch_pressed + 2))
{
hihat_switch = (((hihat_switch << 1) | digitalRead(3)) & 3);
if(hihat_switch == 2){
noteFire(22, 127); // <CHANGE THIS NUMBER '22' FOR 'OPEN HAT' SOUND. 
switch_pressed = currentTime; 
}

}
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;
if((note == 17) && (hihat_switch == 0)) //if pad 4 is hit (note 17) and switch is pressed change note to 22 //
{ //
note = 22; // <CHANGE THIS NUMBER '22' FOR 'OPEN HAT' SOUND.
} 
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);
}

Additional info: I was able to determine the type of control change I need to send Superior Drummer 2.0 by highlighting the hi hat, clicking the articulation dropdown button and selecting hi hat controller and it shows a “CC4” in the key window. Please see the attached photos. So it seems that the key for a closed hi hat sound is “A#-1”, and “D0” when its fully open and a “C0” when its slightly open.

If someone could edit this code and add the INPUT_PULLUP code for my momentary pedal switch

Here:- pinMode put it in the setup function.

I've found a better code for my setup and it is working pretty well.

Shame it was written by someone with no clue as to how to code.

Thank you. I also figured that might be the case. That solved my problem with the ringing pedal. People here are more reliable than with other sites. Now this leaves me with one last problem, and that is trying to figure out how to send a control change message to control the hi hat. I really hope I can complete my work. I will recommend this site to my friends who appreciates my passion for music and wants to learn new things with Arduino. Thank you for being helpfull.

Look at the button example in the Arduino IDE found under the menu:-
Examples -> 02.Digital -> button

That will show you how to read the peddle and do an action based on it. The action you need, I think but see below, is to send a CC message. Unfortunately that code has the MIDI note on / off commands so that you can't re use it for anything else. As I said it is piss poor code.

Unfortunately

I was able to determine the type of control change I need to send Superior Drummer 2.0 by highlighting the hi hat, clicking the articulation dropdown button and selecting hi hat controller and it shows a "CC4" in the key window.

while it could be true is not consistent with:-

So it seems that the key for a closed hi hat sound is "A#-1", and "D0" when its fully open and a "C0" when its slightly open.

So I have no idea what code you need to sent. Those two quotes would suggest two different things.

Thanks everyone. I have completed my project. Cheers!

Hi. I started playing with my DIY electronic drum kit and I noticed 1 problem. If I hit the pad harder the sound is delayed, like 100ms. I looked at the Hairless MIDI screen and I noticed that if I hit the pad harder the midi message receive indicator is also delayed. It is kinda weird since everything is fine if I play a little softer. It happens with all the pads, I have a total of 16 pads. I've tried to search the internet and this site but I could not find anything similar to my problem. However I did found a forum: NerdKits - Piezo over-voltage (Basic Electronics) that talks about adding a 5v zener diode to each piezos in addition to the 1M ohm resistor, it appears that the main reason is to make sure that high voltage will not make it through Arduino and a guy there said that it somehow improved the response of the piezo when hitting it soft and hard. Do you guys think this might be the solution? I've also tried adding a little extra top padding on one of the pads (the snare pad), it prevents the delay when hitting the pad harder but it sacrifice dynamics on being able to play softer since it wont trigger if I hit it softly. Another solution that I think would work is by replacing the pads with mesh head type with a trigger foam cone between the piezo and the mesh head as seen in this tutorial: Low Budget Trigger Pad DIY (E-drums) - YouTube because I'm thinking that too much vibration could be the cause of the delay since I'm only using a plywood as a drum pad, I just don't have the money for such upgrade yet. What do you guys think is the best solution?

Well I am not surprised. What happens when you hit a sensor hard is that you get bounce, that is it carries on giving an output because it keeps on vibrating. Depending on your software this could delay the signal especially if you are looking for a drop below a threshold before you send the MIDI note on. Remember these sensors are not the ideal way to detect all the subtleties of a hit.

What you can do is to experiment with the value of the resistor across the sensor and the capacitor. A smaller resistor will allow harder hits. The other thing is you can experiment with is the software and the threshold levels.

Thank you for your reply. I'll play around with settings in hairless midi and with the code. If its still the same my last resort is to do something about the excess vibration to get rid of the delay when hitting the pads harder.