arduino Leanordo Midi Drum Kit
Inspired by the great tutorial from TheSpodShed on instructables, I have adopted the project using a Leonardo.
The main objective was to get rid of the USB-Midi cable and just use a Leonardo instead of an Arduino Uno or Nano.
The constraint is, that the Leonardo won’t provide the MIDI functionally out of the box.
You would need to use a special core called TeeOnArdu.
The one on github did not work out of the box, so I have used the one from Adafruit.
The setup in eclipse is described in another post here:
This is the first protoype using a Leonardo board with the green shield on the right.
The shield is only used to avoid a breadboard and provide connectors/plugs.
Anyway – the wiring is pretty straight forward as visible in the instructable mentioned at the very top.
This is the version using a Pro Micro – but still the same code:
The original code has been slightly updated to use the build-in MIDI functions.
[codesyntax lang=”c”]
/* This code is placed in the public domain by its author, Ian Harvey * October 2016. * http://www.instructables.com/id/Pringle-Can-MIDI-Drums/ * * update by Thomas Hoeser to Leonardo based on TeensyCore * December 2016 */ #include <Wire.h> #define LED_Status 2 // Pin for status LED (shows piezo got hit) #define LED_HeartBeat 3 // PWM Pin for heartbeat LED (shows code is working) int brightness = 0; // how bright the LED is int fadeAmount = 5; // how many points to fade the LED by uint8_t heart = 0; // Heartbeat LED counter unsigned long prevReadTime = 0L; // Keypad polling timer uint8_t note = 0; // On MIDI Channel 10, each MIDI Note number ("Key#") corresponds to a different drum sound, as shown below const int MIDI_CHANNEL=10; const int NCHANNELS = 4; const int inPins[NCHANNELS] = { A0, A1, A2, A3 }; const int midiNotes[NCHANNELS] = { // Follows General MIDI specs at https://www.midi.org/specifications/item/gm-level-1-sound-set 36, // C3, Kick 38, // D3, Snare 42, // F#3, Closed hi-hat 46, // A#3. Open hi-hat }; /* 35 Acoustic Bass Drum 36 Bass Drum 1 37 Side Stick 38 Acoustic Snare 39 Hand Clap 40 Electric Snare 41 Low Floor Tom 42 Closed Hi Hat 43 High Floor Tom 44 Pedal Hi-Hat 45 Low Tom 46 Open Hi-Hat 47 Low-Mid Tom 48 Hi-Mid Tom 49 Crash Cymbal 1 50 High Tom 51 Ride Cymbal 1 52 Chinese Cymbal */ const int thresholdLevel[NCHANNELS] = { 30, 30, 30, 30 }; // ADC reading to trigger; lower => more sensitive const long int maxLevel[NCHANNELS] = { 400, 400, 400, 400 }; // ADC reading for full velocity; lower => more sensitive static unsigned int vmax[NCHANNELS] = { 0 }; static unsigned int trigLevel[NCHANNELS]; static unsigned int counter[NCHANNELS] = { 0 }; static unsigned int CTR_NOTEON = 10; // Roughly 5ms sampling peak voltage static unsigned int CTR_NOTEOFF = CTR_NOTEON + 30; // Duration roughly 15ms // 0 -> not triggered // 1..CTR_NOTEON -> sampling note on // CTR_NOTEON+1 .. CTR_NOTEOFF -> note off //-------------------------------------------------------------------------------------------------- void setup() { pinMode(LED_HeartBeat, OUTPUT); digitalWrite(LED_HeartBeat, LOW); pinMode(LED_Status, OUTPUT); digitalWrite(LED_Status, LOW); for (int i = 0; i < NCHANNELS; i++) { pinMode(inPins[i], INPUT); analogRead(inPins[i]); trigLevel[i] = thresholdLevel[i]; } /* show module is ready for use */ digitalWrite(LED_Status, HIGH); analogWrite (LED_HeartBeat, 80); delay(500); digitalWrite(LED_Status, LOW); analogWrite (LED_HeartBeat, 160); delay(500); digitalWrite(LED_Status, HIGH); analogWrite (LED_HeartBeat, 254); delay(500); digitalWrite(LED_Status, LOW); analogWrite (LED_HeartBeat, 0); } // void setup() //-------------------------------------------------------------------------------------------------- void loop() { unsigned long t = millis(); int ch; // if((t - prevReadTime) >= 20L) { // 20ms = min Trellis poll time for (ch=0; ch < NCHANNELS; ch++) // Drums: NCHANNELS=4 { unsigned int aVal = analogRead(inPins[ch]); if ( counter[ch] == 0 ) { if ( aVal >= trigLevel[ch] ) { vmax[ch] = aVal; counter[ch] = 1; digitalWrite(LED_Status, HIGH); } } // if counter[ch] == 0 else { if ( aVal > vmax[ch] ) vmax[ch] = aVal; counter[ch]++; if ( counter[ch] == CTR_NOTEON ) { long int vel = ((long int)vmax[ch]*127)/maxLevel[ch]; //Serial.println(vel); if (vel < 5) vel = 5; if (vel > 127) vel = 127; // usbMIDI.sendNoteOn(note, velocity, channel) usbMIDI.sendNoteOn(midiNotes[ch], vel, MIDI_CHANNEL); trigLevel[ch] = vmax[ch]; } else if ( counter[ch] >= CTR_NOTEOFF ) { usbMIDI.sendNoteOn(midiNotes[ch], 0, MIDI_CHANNEL); counter[ch] = 0; digitalWrite(LED_Status, LOW); } } // else counter[ch] == 0 // The signal from the piezo is a damped oscillation decaying with // time constant 8-10ms. Prevent false retriggering by raising // trigger level when first triggered, then decaying it to the // threshold over several future samples. trigLevel[ch] = ((trigLevel[ch] * 19) + (thresholdLevel[ch] * 1)) / 20; } prevReadTime = t; analogWrite(LED_HeartBeat, brightness); // set the brightness brightness = brightness + fadeAmount; // change the brightness for next time if (brightness == 0 || brightness == 255) { // reverse the direction of the fading at the ends of the fade fadeAmount = -fadeAmount ; } //} // if t - prevReadTime) >= 20L while(usbMIDI.read()); // Discard incoming MIDI messages } // void loop() //-------------------------------------------------------------------------------------------------- /* Here's the set of MIDI functions for making your own projects: usbMIDI.sendNoteOn(note, velocity, channel) usbMIDI.sendNoteOff(note, velocity, channel) usbMIDI.sendPolyPressure(note, pressure, channel) usbMIDI.sendControlChange(control, value, channel) usbMIDI.sendProgramChange(program, channel) usbMIDI.sendAfterTouch(pressure, channel) usbMIDI.sendPitchBend(value, channel) usbMIDI.sendSysEx(length, array) usbMIDI.send_now() Some info on MIDI note numbers can be found here: http://www.phys.unsw.edu.au/jw/notes.html Rather than MIDI, one could theoretically try using Serial to create a sketch compatible with serialosc or monomeserial, but those tools have proven notoriously unreliable thus far. */
[/codesyntax]
Good day !
I was trying to make the same project, as inspired by the one in instructables, only that I’m using Leonardo Pro Micro. How am I going to do this? Do I need extra materials or a need to tweak some of the codes?
Thanks
The code shown in the post above is for applicable for any Leonardo. I.e. it can be used for the Leonardo Pro Micro.
The Leonardo used on the picture was just for settign up an sample. Finally I used the Pro Micro as well.
Thanks for the reply, man. I got tons of questions in store upon making this project
I am planning to use an Android phone instead of iPad, but with this first step, I am lost with the MIDI things.
Good day !
What do you call again that green ‘shield’ with headers?
I have updated the description above and added a picture of the version with a Pro Micro.
Hi,
thank you for this cool stuff.
I am using your script on a Leonardo with a Linux Tablet and hydrogen.
It works fine.
I’m new in programming arduinos.
Can you give me a little help how i can use more than 6 analog inputs with your Sketch?
Thanks im advance and best regards
Sascha
Sascha,
the code above is limited to 4 channels and defined in this line:
const int NCHANNELS = 4;
You may incrase the number of channels in the code, but it won’t give you more anolog inuputs on the Leonardo (A0-A3).
May be a stupid idea: why not adding a second controller with addt’l inputs. You would use the same MIDI channel but define other notes in const int midiNotes[NCHANNELS] ….
Thomas
Sir can i used android Mobile instead of ipad…
Sorry, but I do not have an Android device so I can’t test re confirm.