ryokosaka
Published © GPL3+

Minimal MIDI Drum Kit with 3D Printer

This is minimal drum kit using Arduino UNO.

IntermediateFull instructions provided34,742
Minimal MIDI Drum Kit with 3D Printer

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Standard LCD - 16x2 White on Blue
Adafruit Standard LCD - 16x2 White on Blue
×1
SparkFun Piezo
×1
Adafruit Force Sensitive Resistor (FSR)
×1
Resistor 10k ohm
Resistor 10k ohm
×1
Resistor 1M ohm
Resistor 1M ohm
×1
SparkFun Zener Diode - 5.1V 1W
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×1
Slide Switch
Slide Switch
×1
TRS Socket
×1
USB-A to B Cable
USB-A to B Cable
×1
Apple Lightning to USB Camera Adapter
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Laser cutter (generic)
Laser cutter (generic)
not necessary,extra
Soldering iron (generic)
Soldering iron (generic)
circle cutter

Story

Read more

Schematics

circuit_x5tIBQ5SLw.png

circuit_nZotR7rJMM.fzz

Code

Hello Drum v2

Arduino
Modified: 05/12/2019 by George Brotherston
/*
	Drum MIDI Controller
	Created:  28/06/2017 by Ryo Kosaka as " HELLO DRUM " Ver.1.0
	Modified: 05/12/2019 by George Brotherston
*/

// Library Includes

//	#include <Arduino.h>		// Arduino Library (automatically included)
		// LOW (Line 41)
		// HIGH (Line 40)
		// INPUT_PULLUP (Line 47)
		// digitalRead() (Line 177)
		// analogRead() (Line 178)
	#include <MIDI.h>           // MIDI Library		- Version: 4.3.1
		// includes <midi_Namespace.h>
			// class MIDI (Line 30)
		// class method 'begin' (Line 55)
	#include <LiquidCrystal.h>  // LiquidCrystal	- Version: 1.0.7
		// lcd object instantiatied (in Variables section below) from LiquidCrystal class (Line 45)

//	Variables - Declare and Initialize

	// Variables - Program
		boolean	bSnareFlag			= false;
		boolean	bHihatFlag			= false;
		boolean	bKickFlag			= false;
		boolean	bPedalFlag			= false;
		boolean	bButtonState		= true;
		boolean	bButtonState_set	= true;
		int		iUPDOWN				= 0;
		int		iNEXTBACK			= 0;

	//	Arrays - Program
		// InstrumentSensor[6] = {threshold, sensitivity, note, flag, velocity, iPeakValue}
		// 'iPeakValue' and 'velocity' must be zero for all InstrumentSensor arrays
		// All 'aHIHAT[]' and 'aHIHAT_CLOSE[]' array elements should have the same value except for 'note' element.
			int		aSNARE[6]		= {150, 950, 38, 3, 0, 0};
			int		aSNARE_RIM[6]	= {5, 500, 37, 3 , 0, 0};
			int		aHIHAT[6]		= {100, 800, 46, 1, 0, 0};     
			int		aHIHAT_CLOSE[6]	= {100, 800, 42, 1, 0, 0};
			int		aKICK[6]		= {200, 700, 36, 1, 0, 0};
		// Instrument_ContinuousController[4] = {scantime, snare/rim, pedalVelocity , masktime}
			int		aHIHAT_PEDAL[4]	= {600, 0, 44, 0};
		// InstrumentSensor_ParameterValue[4] = {threshold, sensitivity, note, flag}
			int		aSETTING[4]		= {4, 500 ,100 ,1};

	//	Libraries
		//	LiquidCrystal.h
			//	Constants (already defined in Library, still in scope?  If not then define below)
				//	const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
			//	lcd object instantiatiated from LiquidCrystal class (LiquidCrystal.h Line 45)
				LiquidCrystal lcd(rs, en, d4, d5, d6, d7);	//	Associate LCD interface pins to associated Arduino pin number
		// MIDI.h
			//	Initialize the library
				MIDI_CREATE_DEFAULT_INSTANCE();

// Program Code

	// Program Execution - Initial (program setup)

		void setup() {
			MIDI.begin(10);						// begin (MIDI.h Line 55)
			lcd.begin(16, 2);					// begin (LiquidCrystal.h Line 62)
			lcd.print("INITIALIZING...");		// print (LiquidCrystal.h Line 45)
			lcd.setCursor(0, 1);				// setCursor (LiquidCrystal.h Line 82)
			lcd.print("DRUM MIDI CONTROLLER");
			pinMode(6, INPUT_PULLUP);			// pinMode (Arduino.h Line 175); INPUT_PULLUP (Arduino.h Line 47)
			pinMode(7, INPUT_PULLUP);
			pinMode(8, INPUT_PULLUP);
			pinMode(9, INPUT_PULLUP);
			pinMode(10, INPUT_PULLUP);
		}

	// Program Execution - Steadystate (continuous loop until power is lost)

		void loop() {
		// Drum MIDI Controller Circuit
		// Declare and Initialize Variables

			int		iButton_set		= digitalRead(6);	// Set Button			// digitalRead() (Arduino.h Line 177)
			int		iButton_up		= digitalRead(7);	// Up Button
			int		iButton_down	= digitalRead(8);	// Down Button
			int		iButton_next	= digitalRead(9);	// Next Button
			int		iButton_back	= digitalRead(10);	// Back Button
			int		iPiezoValue_A0	= analogRead(A0);   // Piezo - Snare Head	// analogRead() (Arduino.h Line 178)
			int		iPiezoValue_A1	= analogRead(A1);   // Piezo - Snare Rim
			int		iPiezoValue_A2	= analogRead(A2);   // Hi-hat
			int		iPiezoValue_A3	= analogRead(A3);   // Kick Drum
			int		iFSRValue_A4	= analogRead(A4);   // Hi-hat Pedal
	
		// Edit Mode

			int		aUP[4]			= {5, 50, 1,1};		// {threshold, sensitivity, note, flag}
			int		aUP_ADVANCE[4]	= {1, 50, 1,1};		// {scantime, rim/head, pedal velocity, masktime}

			// Note: aINSTRUMENT[] array was not declared in 'Arrays' above
			char* aINSTRUMENT[] = {
				"SNARE HEAD",  "SNARE RIM", "HIHAT OPEN", "HIHAT CLOSE", "HIHAT PEDAL", "KICK", "ADVANCED SETTING"
			};

			// Note: aSETTING[] array WAS declared in 'Arrays' above
			char* aSETTING[] = {
				"THRESHOLD",  "SENSITIVITY", "NOTE", "FLAG"
			};

			// Note: aSETTING_ADVANCE[] was not declared in 'Arrays' above
			char* aSETTING_ADVANCE[] = {
				"SCAN TIME", "HEAD / RIM ","PEDAL VELO", "MASK TIME"
			};

			if (iUPDOWN < 0) {
				iUPDOWN = 6;
			}

			if (iUPDOWN > 6) {
				iUPDOWN = 0;
			}

			if (iNEXTBACK < 0) {
				iNEXTBACK = 3;
			}

			if (iNEXTBACK > 3) {
				iNEXTBACK = 0;
			}

		// Pushbutton EDIT
			// LOW (Arduino.h Line 41)
			if (iButton_set == LOW && bButtonState == true && bButtonState_set == true) {
				lcd.clear();
				lcd.print("EDIT");
				bButtonState		= false;
				bButtonState_set	= false;
				delay(500);
			}

			if (iButton_set == LOW && bButtonState == true && bButtonState_set == false) {
				lcd.clear();
            	lcd.print("EDIT DONE");
            	bButtonState		= false;
            	bButtonState_set	= true;
            	delay(500);
			}

			if (iButton_up == LOW && bButtonState == true && bButtonState_set == false) {
				switch (iUPDOWN) {
					case 0:
					aSNARE[iNEXTBACK] = aSNARE[iNEXTBACK] + aUP[iNEXTBACK];
					break;

					case 1:
					aSNARE_RIM[iNEXTBACK] = aSNARE_RIM[iNEXTBACK] + aUP[iNEXTBACK];
					break;

					case 2:
					switch (iNEXTBACK) {
						case 2:
						aHIHAT[iNEXTBACK] = aHIHAT[iNEXTBACK] + aUP[iNEXTBACK];
						break;

						default:
						aHIHAT_CLOSE[iNEXTBACK] = aHIHAT_CLOSE[iNEXTBACK] + aUP[iNEXTBACK];
						aHIHAT[iNEXTBACK] = aHIHAT[iNEXTBACK] + aUP[iNEXTBACK];
					}
					break;

					case 3:
					switch (iNEXTBACK) {
						case 2:
						aHIHAT_CLOSE[iNEXTBACK] = aHIHAT_CLOSE[iNEXTBACK] + aUP[iNEXTBACK];
						break;
						
						default:
						aHIHAT_CLOSE[iNEXTBACK] = aHIHAT_CLOSE[iNEXTBACK] + aUP[iNEXTBACK];
						aHIHAT[iNEXTBACK] = aHIHAT[iNEXTBACK] + aUP[iNEXTBACK];
					}
					break;

					case 4:
					switch (iNEXTBACK) {
						case 0:
						aHIHAT_PEDAL[iNEXTBACK] = aHIHAT_PEDAL[iNEXTBACK] + aUP[iNEXTBACK];
						break;
						
						case 2:
						aHIHAT_PEDAL[iNEXTBACK] = aHIHAT_PEDAL[iNEXTBACK] + aUP[iNEXTBACK];
						break;
					}
					break;

					case 5:
					aKICK[iNEXTBACK] = aKICK[iNEXTBACK] + aUP[iNEXTBACK];
					break;

					case 6:
					aSETTING[iNEXTBACK] = aSETTING[iNEXTBACK] + aUP_ADVANCE[iNEXTBACK];
					break;
				}
				bButtonState = false;
				delay(30);
			}

			if (iButton_down == LOW && bButtonState == true && bButtonState_set == false) {

				switch (iUPDOWN) {
					case 0:
					aSNARE[iNEXTBACK] = aSNARE[iNEXTBACK] - aUP[iNEXTBACK];
					break;

					case 1:
					aSNARE_RIM[iNEXTBACK] = aSNARE_RIM[iNEXTBACK] - aUP[iNEXTBACK];
					break;

					case 2:
					switch (iNEXTBACK) {
						case 2:
						aHIHAT[iNEXTBACK] = aHIHAT[iNEXTBACK] - aUP[iNEXTBACK];
						break;

						default:
						aHIHAT_CLOSE[iNEXTBACK] = aHIHAT_CLOSE[iNEXTBACK] - aUP[iNEXTBACK];
						aHIHAT[iNEXTBACK] = aHIHAT[iNEXTBACK] - aUP[iNEXTBACK];
					}
					break;

					case 3:
					switch (iNEXTBACK) {
						case 2:
						aHIHAT_CLOSE[iNEXTBACK] = aHIHAT_CLOSE[iNEXTBACK] - aUP[iNEXTBACK];
						break;

						default:
						aHIHAT_CLOSE[iNEXTBACK] = aHIHAT_CLOSE[iNEXTBACK] - aUP[iNEXTBACK];
						aHIHAT[iNEXTBACK] = aHIHAT[iNEXTBACK] - aUP[iNEXTBACK];
					}
					break;

					case 4:
					switch (iNEXTBACK) {
						case 0:
						aHIHAT_PEDAL[iNEXTBACK] = aHIHAT_PEDAL[iNEXTBACK] - aUP[iNEXTBACK];
						break;

						case 2:
						aHIHAT_PEDAL[iNEXTBACK] = aHIHAT_PEDAL[iNEXTBACK] - aUP[iNEXTBACK];
						break;
					}
					break;

					case 5:
					aKICK[iNEXTBACK] = aKICK[iNEXTBACK] - aUP[iNEXTBACK];
					break;

					case 6:
					aSETTING[iNEXTBACK] = aSETTING[iNEXTBACK] - aUP_ADVANCE[iNEXTBACK];
					break;
				}
				bButtonState = false;
				delay(30);
			}

		// Pushbuttons UP; DOWN; NEXT; BACK
			if (iButton_up == LOW && bButtonState == true && bButtonState_set == true) {
				iUPDOWN = ++iUPDOWN;
				bButtonState = false;
				delay(30);
			}

			if (iButton_down == LOW && bButtonState == true && bButtonState_set == true) {
				iUPDOWN = --iUPDOWN;
				bButtonState = false;
				delay(30);
			}

			if (iButton_next == LOW && bButtonState == true && bButtonState_set == true) {
				iNEXTBACK = ++iNEXTBACK;
				bButtonState = false;
				delay(30);
			}

			if (iButton_back == LOW && bButtonState == true && bButtonState_set == true) {
				iNEXTBACK = --iNEXTBACK;
				bButtonState = false;
				delay(30);
			}

			if (bButtonState == false && iButton_up == HIGH && iButton_down == HIGH && iButton_next == HIGH && iButton_back == HIGH && iButton_set == HIGH) {
				// HIGH is defined in Arduino.h Line 40

				switch (iUPDOWN) {

					case 0:
					lcd.clear();
					lcd.print(aINSTRUMENT[iUPDOWN]);
					lcd.setCursor(0, 1);
					lcd.print(aSETTING[iNEXTBACK]);
					lcd.setCursor(12, 1);
					lcd.print(aSNARE[iNEXTBACK]);
					break;

					case 1:
					lcd.clear();
					lcd.print(aINSTRUMENT[iUPDOWN]);
					lcd.setCursor(0, 1);
					lcd.print(aSETTING[iNEXTBACK]);
					lcd.setCursor(12, 1);
					lcd.print(aSNARE_RIM[iNEXTBACK]);
					break;

					case 2:
					lcd.clear();
					lcd.print(aINSTRUMENT[iUPDOWN]);
					lcd.setCursor(0, 1);
					lcd.print(aSETTING[iNEXTBACK]);
					lcd.setCursor(12, 1);
					lcd.print(aHIHAT[iNEXTBACK]);
					break;

					case 3:
					lcd.clear();lcd.print(aINSTRUMENT[iUPDOWN]);
					lcd.setCursor(0, 1);
					lcd.print(aSETTING[iNEXTBACK]);
					lcd.setCursor(12, 1);
					lcd.print(aHIHAT_CLOSE[iNEXTBACK]);
					break;

					case 4:
					lcd.clear();
					lcd.print(aINSTRUMENT[iUPDOWN]);
					lcd.setCursor(0, 1);
					lcd.print(aSETTING[iNEXTBACK]);
					lcd.setCursor(12, 1);
					lcd.print(aHIHAT_PEDAL[iNEXTBACK]);
					break;

					case 5:
					lcd.clear();
					lcd.print(aINSTRUMENT[iUPDOWN]);
					lcd.setCursor(0, 1);
					lcd.print(aSETTING[iNEXTBACK]);
					lcd.setCursor(12, 1);
					lcd.print(aKICK[iNEXTBACK]);
					break;

					case 6:
					lcd.clear();
					lcd.print(aINSTRUMENT[iUPDOWN]);
					lcd.setCursor(0, 1);
					lcd.print(aSETTING_ADVANCE[iNEXTBACK]);
					lcd.setCursor(12, 1);
					lcd.print(aSETTING[iNEXTBACK]);
					break;
				}

				bButtonState = true;
			}

		// Instrument Sensors

			// Snare Drum
			if (iPiezoValue_A0 > aSNARE[0] && bSnareFlag == false) {

				for (int i = 0; i < aSETTING[0]; i++) {
					int iPeak_A0 = analogRead(A0);
					int iPeak_A1 = analogRead(A1);
					delay(1);
					if (iPeak_A0 > aSNARE[4]) {
						aSNARE[4] = iPeak_A0;
					}
					if (iPeak_A1 > aSNARE_RIM[4]) {
						aSNARE_RIM[4] = iPeak_A1;
					}
				}
				aSNARE[5] = aSNARE[4];
				aSNARE_RIM[5] = aSNARE_RIM[4];
				aSNARE[4] = map(aSNARE[4], aSNARE[0], aSNARE[1], 0, 127);
				aSNARE_RIM[4] = map(aSNARE_RIM[4], aSNARE_RIM[0], aSNARE_RIM[1], 0, 127);
				aSNARE[4] = (aSNARE[4] *  aSNARE[4]) / 127; // Curve setting

			//aSNARE_RIM[4] = (aSNARE_RIM[4] * aSNARE_RIM[4]) / 127;
				if (aSNARE[4] <= 1) {
					aSNARE[4] = 1;
				}
				if (aSNARE[4] > 127) {
					aSNARE[4] = 127;
				}
				if (aSNARE_RIM[4] <= 0) {
					aSNARE_RIM[4] = 0;
				}
				if (aSNARE_RIM[4] > 127) {
					aSNARE_RIM[4] = 127;
				}
				if (aSNARE_RIM[5] > aSETTING[1]) {
					MIDI.sendNoteOn(aSNARE_RIM[2], aSNARE_RIM[4], 1);   //(note, velocity, channel)
					MIDI.sendNoteOn(aSNARE_RIM[2], 0, 1);
					lcd.clear();
					lcd.print("SNARE RIM");
					lcd.setCursor(0, 1);
					lcd.print(aSNARE_RIM[4]);
					bSnareFlag = true;
				}

			//else if (aSNARE[5] > aSNARE_RIM[5])
				else {
					MIDI.sendNoteOn(aSNARE[2], aSNARE[4], 1);   //(note, velocity, channel)
					MIDI.sendNoteOn(aSNARE[2], 0, 1);
					lcd.clear();
					lcd.print("SNARE HEAD");
					lcd.setCursor(0, 1);
					lcd.print(aSNARE[4]);
				//lcd.setCursor(10, 1);
				//lcd.print(aSNARE_RIM[5]);
					bSnareFlag = true;
				}
			}

		// Hi-Hat Cymbal
			if (iPiezoValue_A2 > aHIHAT[0] && bHihatFlag == false) {
				for (int i = 0; i < aSETTING[0]; i++) {
					int iPeak_A2 = analogRead(A2);
					delay(1);
					if (iPeak_A2 > aHIHAT[4]) {
						aHIHAT[4] = iPeak_A2;
					}
				}
				aHIHAT[5] = aHIHAT[4];
				aHIHAT[4] = map(aHIHAT[4], aHIHAT[0], aHIHAT[1], 0, 127);
				aHIHAT[4] = (aHIHAT[4] * aHIHAT[4]) / 127;
				if (aHIHAT[4] <= 1) {
					aHIHAT[4] = 1;
				}
				if (aHIHAT[4] > 127) {
					aHIHAT[4] = 127;
				}
				if (iPiezoValue_A0 < aHIHAT_PEDAL[0]) {
					MIDI.sendNoteOn(aHIHAT[2], aHIHAT[4], 1);
					MIDI.sendNoteOn(aHIHAT[2], 0, 1);
					lcd.clear();
					lcd.print("HIHAT OPEN");
					lcd.setCursor(0, 1);
					lcd.print(aHIHAT[4]);
					bHihatFlag = true;
				}
				else if (iPiezoValue_A0 >= aHIHAT_PEDAL[0]) {
					MIDI.sendNoteOn(aHIHAT_CLOSE[2], aHIHAT[4], 1);
					MIDI.sendNoteOn(aHIHAT_CLOSE[2], 0, 1);
					lcd.clear();
					lcd.print("HIHAT CLOSE");
					lcd.setCursor(0, 1);
					lcd.print(aHIHAT[4]);
					bHihatFlag = true;
				}
			}

		// Hi-hat Pedal
			if (iPiezoValue_A0 > aHIHAT_PEDAL[0] && bPedalFlag == false) {
				MIDI.sendNoteOn(aHIHAT_PEDAL[2], aSETTING[2], 1);  // (note, velocity, channel)
				MIDI.sendNoteOn(aHIHAT_PEDAL[2], 0, 1);
				lcd.clear();
				lcd.print("HIHAT PEDAL");
				lcd.setCursor(0, 1);
				lcd.print(aSETTING[2]);
				bPedalFlag = true;
			}

		// Kick Drum
			if (iPiezoValue_A3 > aKICK[0] && bKickFlag == false) {
				for (int i = 0; i < aSETTING[0]; i++) {
					int iPeak_A3 = analogRead(A3);
					delay(1);
					if (iPeak_A3 > aKICK[4]) {
						aKICK[4] = iPeak_A3;
					}
				}

				aKICK[5] = aKICK[4];
				aKICK[4] = map(aKICK[4], aKICK[0], aKICK[1], 0, 127);
				aKICK[4] = (aKICK[4] * aKICK[4]) / 127;
				if (aKICK[4] <= 1) {
					aKICK[4] = 1;
				}
				if (aKICK[4] > 127) {
					aKICK[4] = 127;
				}
				MIDI.sendNoteOn(aKICK[2], aKICK[4], 1);
				MIDI.sendNoteOn(aKICK[2], 0, 1);
				lcd.clear();
				lcd.print("KICK");
				lcd.setCursor(0, 1);
				lcd.print(aKICK[4]);
				bKickFlag = true;
			}

// --- BEGIN 'Code in Progress' --- //
// --- I could be wrong, but this is what it appears to be --- and out of curiousity what is purpose of this sequence? -- //

			// I=(A0);  // Previous Code
			// -- DOES iSensorValue_A0 need to be declared as an integer?  How does this relate to iPiezoValue_A0?  -- //
			if (iSensorValue_A0 < (aSNARE[5] * (0.01 * aSNARE[3]))) {
				bSnareFlag = false;
			}
			if (iPiezoValue_A0 <= aHIHAT_PEDAL[0] && iPiezoValue_A2 < (aHIHAT[5] * (0.01 * aHIHAT[3])) && bHihatFlag == true) {
				delay(aSETTING[3]);
				// iSensorValue_A1 is reading analogRead(A2), but this is aHIHAT_PEDAL (which is analogRead(A2)
				int iSensorValue_A1 = analogRead(A2);
				if (iSensorValue_A1 < (aHIHAT[5] * (0.01 * aHIHAT[3]))) {
					bHihatFlag = false;
				}
			}
			if (iPiezoValue_A0 >= aHIHAT_PEDAL[0] && iPiezoValue_A2 < (aHIHAT[5] *(0.01 * aHIHAT[3])) && bHihatFlag == true) {
				delay(aSETTING[3]);
				int iSensorValue_A2 = analogRead(A2);
				if (iSensorValue_A2 < (aHIHAT[5] * (0.01 * aHIHAT[3]))) {
					bHihatFlag = false;
				}
			}
			if (iPiezoValue_A3 < (aKICK[5] * (0.01 * aKICK[3])) && bKickFlag == true) {
				delay(aSETTING[3]);
				// -- Should declared iSensorValue_A3 be iPiezoValue_A3?  iSensorValue_A3 is declared but not used anywhere??
				int iSensorValue_A3 = analogRead(A3);
				if (iPiezoValue_A3 < (aKICK[5] * (0.01 * aKICK[3]))) {
				bKickFlag = false;
				}
			}
			if (iPiezoValue_A0 <= aHIHAT_PEDAL[0] && bPedalFlag == true) {
				bPedalFlag = false;
			}

// --- END 'Code in Progress' --- //
		}

Hello Drum

Credits

ryokosaka

ryokosaka

1 project • 21 followers

Comments