
Audio sensors (read: microphones) connect to an Arduino. When the sensors create an audio signal (when the mics are hit) they trigger a MIDI note – generated by the Arduino – which is sent to a drum machine.
Trigger drums from piezo sensors.
These super cheap microphones have horrible sound quality, but they are great at detecting sound.

Each drum instrument (snare, kick, cymbals, etc) is assigned a piezo, and each piezo is connected to an input pin on the Arduino. All eight of ’em are wired up and labeled with their instrument name and associated Arduino pin.

An Arduino MEGA 2560 – the UNO’s big brother – is chosen because of the extra analog inputs. Analog inputs allow different levels to be sensed (based on the strength of the hit on the piezo) to let the Arduino generate a different velocity of note.

The MIDI signal is output through a standard MIDI connector, and can connect to anything which supports MIDI – keyboards, DAWs, drum machines, etc.

The sensors can be hooked up to pots and pans, cardboard boxes – anything!
Here they are taped to an traditional acoustic drum kit.

The code specifies which MIDI notes will be triggered, and also allows threshold calibration for each sensor.
CODE:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
/* --midiDrums-- http://creativetechnical.ca/mididrums/ Create 8 MIDI triggers with 8 piezo sensors Each piezo is connected to an Arduino analog input pin & ground, in parallel with a 1M ohm resistor. MIDI jack pin 5 connected to Arduino pin 1 (TX) MIDI jack pin 2 connected to ground MIDI jack pin 4 connected to +5V through 220-ohm resistor Attach a MIDI cable to the jack, then to a MIDI device, and play drums. Credit to Evan Kale for the following code and inspiration:-) Copyright (c) 2015 Evan Kale Email: EvanKale91@gmail.com Website: www.ISeeDeadPixel.com www.evankale.blogspot.ca */ //Piezo defines #define NUM_PIEZOS 8 //anything < TRIGGER_THRESHOLD is treated as 0 #define KICK_THRESHOLD 200 #define SNARE_THRESHOLD 300 #define HHAT_THRESHOLD 300 #define FTOM_THRESHOLD 800 #define MTOM_THRESHOLD 0 #define HTOM_THRESHOLD 800 //900 is good #define CRASH_THRESHOLD 1020 #define RIDE_THRESHOLD 800 #define START_SLOT 0 //first analog slot of piezos //MIDI note defines for each trigger #define KICK_NOTE 36 //c1 kick #define SNARE_NOTE 38 //d1 snare #define HHAT_NOTE 42 //F#1 hihat #define FTOM_NOTE 43 //g1 floor tom #define MTOM_NOTE 45 //b1 mid tom #define HTOM_NOTE 47 //g1 hi tom #define CRASH_NOTE 49 //a#1 crash #define RIDE_NOTE 51 //g2 ride //#define PEDAL_NOTE 44 //g#1 pedal (future) //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 300 //100 #define PEAK_BUFFER_SIZE 90 //30 #define MAX_TIME_BETWEEN_PEAKS 20 //20 #define MIN_TIME_BETWEEN_NOTES 80 //50 //delay between the same note (drumroll will not be a roll, but quarternotes) //however, 2 different drums can be fired simultaneously //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]; ////////////////////////////////////////////////////////////////////////////// void MIDIsoftreset() { Serial.write(0xF0); Serial.write(0x7F); Serial.write(0x7F); //device id 7F = 127 all channels Serial.write(0x02); Serial.write(0x7F); // command format 7F = all devices Serial.write(0x0A); // action 0x0A= reset Serial.write(0xF7); } ///////////////////////////////////////////////////////////////////////////// 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] = KICK_THRESHOLD; thresholdMap[1] = SNARE_THRESHOLD; thresholdMap[2] = HHAT_THRESHOLD; thresholdMap[3] = FTOM_THRESHOLD; thresholdMap[4] = MTOM_THRESHOLD; thresholdMap[5] = HTOM_THRESHOLD; thresholdMap[6] = CRASH_THRESHOLD; thresholdMap[7] = RIDE_THRESHOLD; noteMap[0] = KICK_NOTE; noteMap[1] = SNARE_NOTE; noteMap[2] = HHAT_NOTE; noteMap[3] = FTOM_NOTE; noteMap[4] = MTOM_NOTE; noteMap[5] = HTOM_NOTE; noteMap[6] = CRASH_NOTE; noteMap[7] = RIDE_NOTE; // Serial.write(0xff); // MIDIsoftreset(); } void loop() { 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); } |