DrumCube, an Arduino Robot Drummer




Live music gigs are always a very special thing, but to produce it, you need humans, and humans are not always available. I occasionally play gigs equipped by my guitar and my voice, but music generally features many others instruments, like percussion, and these instruments tend to only sound when played by humans. This problem could be solved by just using a recording and playing over it, but that would somehow feel against the idea of the “live” concept.

So, I decided to get rid of the human element entirely, and build a robot drummer... The idea would be to make something portable, which could move and play sounds in different rhythms with no use of samples/recordings, that could be played or stopped at will, and that its sound could be amplified in a gig/band situation.

Disclaimer 1: As I said in my previous project, I have no formal electronics education, so I'm sure that many of the circuits described in this tutorial could be arranged in a better and more efficient/effective way. I'm open to suggestions. Btw, the same applies for all the code I wrote in this project.

Disclaimer 2: In order to keep this tutorial as short, easy and useful as possible, I decided to focus in the main functions of the projects. These being, how the sound is produced, how is captured and amplified, and how the arduino keeps everything under control. With this in mind, I simplified many aspect of the project, like the use of a simple tact switch instead of a rotary encoder.

Step 1: Materials

**I did all the wooden pieces by hand, so I don't really have any exact plans for them. I've drawn and explained everything as best as I could though, and I don't think it would be much hard to replicate them, more so if you have a cnc or a 3d printer.

Step 2: The General Idea

In first place, it is necessary to define what the drumkit elements will be. Following the logic of the frequency range, the standard drum-kit is usually conformed by three basic elements; the kick (low frequency range), the snare (mid range), and the hi-hat (high range). After a couple weeks of experimentation, I decided to replicate this sounds with the following arrangements:

Kick/LowRange: 2 piezos, covered with a small piece of sponge material, which are hit by a servo controlled stick with a soft rubber end.

Snare/MidRange: A can of pringles, with a small square sheet of tin for resonation, which is also hit by servo controlled sticks with a rubber end. The sound is then captured by an electret microphone.

HiHat/HighRange: A transistor-based white noise generator circuit, which is controlled directly by the arduino.

All of the above mentioned systems are set in time by the arduino board, and the audio signal generated by them is then amplified to an instrument level signal by three simple amplifier circuits for each one of them.

Step 3: The Kick Drum

This works by taking advantage of the low frequency sound which is produced when a piezo pickup is directly touched or hit with a soft object. To make this work, first we need to automatise the hitting of the piezo, and secondly, we need to amplify the audio signal generated by said piezo.

As I mentioned above, I used a servo controlled stick to hit two different piezos located at each end of the servo's movement range (in order to make use of all the movement). To help damp high frequencies, the piezos are covered with sponges and the stick has a soft rubber end.

It is important, at this point, to define the angle at which the servo will be when it is hitting each end of its range of movement. This information will be necessary later, and It can be easily obtained using a basic piece of arduino code (like the one described here) and the Serial.print(); command.

The audio signal from the piezos is then amplified by the circuit described on the image above, powered by 5v - 7v from a voltage regulator, which is fed from the main power supply (not the arduino board). This is important because, although the amplifier itself would be able to work with the 5v provided by the arduino, it is ideal to maintain the analog audio signal as separated as possible from the digital circuitry, in order to avoid any digital noise interference making its way into the final audio signal.

Again, I have no formal (or any lol) electronics education, and I've struggle a lot with this last problem. Noise is virtually impossible to get absolutely rid of in any audio application, but I've found that the filtering in the voltage regulator (as well as the analogue and digital separation, and a proper electrical shielding of the project) reduces noise to very acceptable levels.

Step 4: The Snare

This is a very complicated sound to replicate, even now I'm still not absolutely happy with the sound I’ve achieved. To pickup this sound, I decided to use an electret microphone, as they're usually more sensitive, and the unique acoustic nature of a snare sound makes this necessary.

As we did with the kick system, we need a mechanical part, and an audio one. I've attached a drawing of the mechanical system I designed. Yes, I used a Pringles can upside down, it was the perfect shape, had the best sound I could find, and the crisps were delicious.

Just like we did with the kick, we need to get the angle at which each servo will be when resting and when hitting. Again, tinkering with the Potentiometer+Servo tutorial, we can get that information.

The audio signal from the electret is amplified by another instance of the same circuit used in the kick's amplifier, although in this case with a few modifications to power the electret microphone, and without the low-pass filter used in the kick.

Step 5: The HiHat

I used a different approach to this sound, a transistor-based white noise generator circuit, and a led indicator, are activated by the arduino when it is required. White noise is a random signal with equal intensity at different frequencies. Roughly speaking, just as white light contains all colours, white noise contains all frequencies, and it sound like a nonexistent radio station (static). This is a noise commonly used in electronic music and audio synthesis, I read that it was even used to make the classic sound of the 80's snares and cymbals.

As the diagram shows, after the noise is generated, it then goes through a high-pass filter to eliminate the unwanted frequencies and to accentuate the drum cymbal sensation.

The white noise generator needs 12v or higher to function, that are provided by a step up voltage elevator, which itself is powered directly by an arduino pin. This is the only instance in which an audio system is attached directly to the arduino, because noise has to be generated only in certain times, and noise seems not to be an issue in a circuit that generates noise. You can't make white more white can you?

Step 6: The Signal Mix & Complete Diagram

After all of three drum-kit sounds are generated, each signal goes through a potentiometer and a basic passive mixer circuit, which mixes the final audio signal.

We also need a way to select what drumbeat to play and when to start and finish playing. For this instructable, we will use a tact button connected and a simple switch for each function respectively (connected to the arduino pins 2 and 3, as the image above shows)

Step 7: The Code I - Servo Time Calibration

Now, given that this project is a musical instrument, it needs to generate sound in the right time. So, before we start coding different rhythms and functionalities, specially in the case of the kick and the snare, we need to program the movement of the servos to start some milliseconds before their turn to sound, in order to compensate the time the stick takes to go from resting to hitting, and make the sticks hit their destination just in time.

To solve this problem, I improvised a simple system to measure the time it took every servo to go from its resting position to the exact point of hitting its destination. I covered the sticks and the areas where they hit with aluminum foil, and attached alligator clips to the foil, creating a connection only measurable by the arduino when the stick hits its target. Then I wrote a simple bit of code, which did two things: firstly, make the servo sticks hit repeatedly their target, going from resting angle, to hitting angle. And secondly, print the time when the servo command was sent, and the time when the stick close the connection with its target. Subtracting this two values will give us the time it takes the sticks to make a sound, from resting to hitting.

After doing this enough times, you'll end up with a lot of roughly similar numbers, which you can then average, and obtain a pretty much usable time of anticipation for every servo.

Step 8: The Code II - Drum Combinations

Now, we define a number code for every combination of kick, snare, and hihat in a beat. We assign the first odd numbers to each of our three drumkit elements:

Kick	Snare	HiHat
1 3 5

And then, if we need to play more than one element at the same time, we simply add the numbers of each element. Kick and snare would be 4, kick and HiHat 6, and so on. Nought/zero is a silence. Now we have a number for every possible drum elements combination, and we can store them in a variable (cycleNumber variable).

3 HiHat		x 	-	x	x
2 Snare - x x x 1 Kick x x - x _________________________________________ COMBINATION: 4 3 5 6

Step 9: The Code III - Semiquaver Cycle (hitting on Time)

We now know that is necessary to anticipate the commands for the kick and snare servos, but we also have to play the hi-hat on time, which is a circuit that work almost instantly.

To approach this problem, which might get a bit confusing down the road, I decided to establish a system of checkpoints inside every semiquaver (or sixteenth note) of every bar. I chose a sixteenth because in the tempo of most common rhythms, a sixteenth of a note last about 100 to 150 milliseconds, which is also the speed at which the slower servo (in my case) can go from rest to hitting, or vice verse. We can change the speed of the tempo by simply changing the amount of milliseconds assigned to the timeTotalCycle variable. Here is a useful table of tempo, notes, and milliseconds equivalence. If we tried to play something faster, and we reduce the total time of the cycle lower than the time the slower servo takes to move, this servo might be unable to reach hitting position from rest, and therefore no sound would be produced. A more detailed look at the diagram I've posted, will explain this better.

As shown in the diagram, at the start of what I called the semiquaver-cycle we send the command for positioning the snare servos on their rest position, in case that they had been commanded to hit in a previous cycle. Also at this point, we begin counting the milliseconds that has been set for the duration of the entire semiquaver cycle.

After that, the arduino will start checking if the amount of time left for the cycle to end, is equal to any of the times that each servo needs to produce sound. The idea here, is to detect the point in time at which we have to send the hitting command so that every servo reach and hit their target (and make their sound) at the exact end of the cycle. Every element will therefore have to start its movement at different checkpoints in the cycle, depending on how fast the servo and its mechanism are. The hihat white noise circuit, on the other hand, can be just turned on at the very end of the cycle or a few milliseconds earlier (20 recommended). Its ending will be commanded on the next cycle in a checkpoint defined by you, how long after the start of the cycle you set it, will be how long the hihat sound is (I set mine between 30 and 40 milliseconds, but that is up to you).

Every time one of these checkpoints are met, the arduino will check if its corresponding element is intended to action, by comparing it with the drum combination number stored on the cycleNumber variable (the number code system explained earlier). Example, if the snare's checkpoint is met, the snare's number is 3, so the hitting command will only be sent if the drum combination has the numbers 3, 4 (3+1), 8 (3+5) or 9 (3+1+5).

3 HiHat		x 	-	x	x
2 Snare - x x x 1 Kick x x - x

Why using two sets of sticks and servo in the snare mechanism?

Well, if you think about it, if only one servo would have been used, and lets say its rest-to-hitting time was 100 milliseconds, the shortest amount of time that our semiquaver cycle could last would be 200 milliseconds. 100 to allow going back from hitting to rest, and then 100 more from rest to hiting. 200 millisecond for each sixteenth note equals to a tempo of around 75 bpm (“dream on” by aerosmith), which is pretty slow and limiting in terms of possible rhythms.

Using two separate sets of sticks and servos, and alternating their use, making one go back from hitting to rest in its 100 milliseconds, while the other goes hitting in the same amount of time, reduces the minimum semiquaver cycle time from around 200 to 100 milliseconds approximately (“Call me” by blondie), much faster. In other words, the time of the slower servo, is also the minimum time the semiquaver cycle can last.

Step 10: The Code IV - Making the Drum Beat

We now have a way to define exactly what sounds to generate, and also, to do it all at the exact same time. We just need to play 16 of these sixteenth note cycles, one after another, with the desired drum combinations for each one, and we have a bar. We repeat that bar as long as we want, and voliá, we have a musical drum beat.

With a simple bit of code, we store our bar-sequence of 16 semiquaver in an array, and make the arduino go through over and over. Different drum beats can be stored and played by setting different arrays of 16 numbers, as shown in this diagram:

3 HiHat		x-x-x-x-x-x-x-x-
2 Snare		----x-------x---
1 Kick		x-------x-------
ARRAY:		6050805060508050
3 HiHat		x-x-x-x-x-x-x-x-
2 Snare		----x-------x---
1 Kick		x--x--x--xx---x- 
ARRAY:		6051806051608060

To switch between these arrays, we'll use the tact switch button connected to pin 3.

Step 11: The Code V - Putting It All Together

// DrumCube, an arduino robot drummer
// by Franco Molina @artefrancomolina

// Setting servos #include <Servo.h>
Servo servo1;
Servo servo2;
Servo servo3;

// Servo positions // this will differ depending on your servos, please test yours to find out the values that best suit you byte restServo1 = 12; byte hitServo1 = 21; byte restServo2 = 123; byte hitServo2 = 114; byte restServo3 = 4; byte hitServo3 = 19;

// Setting the HiHat white noise generator #define noiseGenerator 12 #define noiseLed 13 //turn on led as a visual representation of the noise being generated

// Setting servo times // this will also differ depending on your servos, please test yours to find out the values that best suit you byte timeSnare1 = 110; byte timeSnare2 = 108; byte timeKick = 71; byte timeHihat = 20; byte sustainTimeHihat = 70;

// Setting previous Snare and Kick byte previousSnare = 2; byte previousKick = 0;

// Setting cycle times static unsigned long timeStartCycle; static unsigned long timeTotalCycle; // changing this, change how fast/slow the rhythm is, you can set a specific value for each drumbeat in the selectDrumBeat() function

// Bar and Cycles variables int cycleNumber; int cycleNumbers[] = {6, 0, 5, 0, 8, 0, 5, 0, 6, 0, 5, 0, 8, 0, 5, 0}; // this array stores the drum elements combination for each cycle (semiquaver or sixteenth) of the drumbeat byte timeSignature = 44; int drumbeatID = 0; // ID number for each drumbeat

// int i; // for counting the time in the "for loop" of the cyclePlayer function int b; // for the "for loop" that counts the number of cycles

// control interface #define switchPlayStop 2 // switch bettween playing and stop #define buttonSelect 3 // tact button that select the drumbeat to play

void setup(void) {

// define pins for each servo pinMode (5, OUTPUT); pinMode (6, OUTPUT); pinMode (9, OUTPUT);

// attach servos to those pins servo1.attach(5); //caja 1 servo2.attach(6); //caja 2 servo3.attach(9); //bombo delay(150);

// put all servos on rest position servo1.write(restServo1); servo2.write(restServo2); servo3.write(restServo3); delay(300);

// Setting hihat and led pinmodes pinMode (noiseGenerator, OUTPUT); digitalWrite(noiseGenerator, LOW); pinMode (noiseLed, OUTPUT); digitalWrite(noiseLed, LOW);

// Setting control interface pinmodes pinMode (switchPlayStop, INPUT_PULLUP); pinMode (buttonSelect, INPUT_PULLUP);


void loop(void) { if (switchPlayStop == LOW) { //if the play/stop switch is ON (logical LOW) //We start a "for loop" to play a semiquaver cycle a maximum of 16 times, for every bar for (b = 0; b < 16; b = b + 1) { selectDrumBeat(); // select the drumbeat based on the drumbeatID selected cyclePlayer(cycleNumbers[b]); //play the semiquaver cycle for each number stored in the cycleNumbers array

// if we reach the maximum number of cycles (16 for 4/4, 12 for 6/8, 12/8 or 3/4) we start again if (b == 11 && (timeSignature == 68 || timeSignature == 128)) { b = -1; } if (b == 15) { b = -1; } } } // If the play/stop switch is OFF (logical HIGH) we enter settingMode else { settingMode(); // function that lets you choose between different drumbeats and wait for the play switch to be activated } }

// CYCLE PLAYER // this functions runs a semiquaver cycle every time is called. void cyclePlayer(int cycleNumber) { // we store every single value of the cycleNumbers array into the cycleNumber variable timeStartCycle = millis(); // we save the starting time, to compare it later with the actual time and get the time past

//set both snare servos to rest position in case they were on hit position servo1.write(restServo1); servo2.write(restServo2);

//we star a "for loop" for the entire duration of every semiquaver cycle for (i = 0; i < timeTotalCycle; i++) {

//now we send the hitting commands on time so they reach their destination on time (the end of the semiquaver cycle)

// if we reach the time to send the command to the snare on servo1. We start checking the element that takes the longest time to move, in this case is servo1, in yours could be different. if ((millis() - timeStartCycle >= timeTotalCycle - timeSnare1)) { // we check if this is the one snare of the two, that has to be played, // and also, if in this cycle a snare has to be played at, all based on the cycleNumber number (this number define the cobination of drum elements) if ((previousSnare == 2) && ((cycleNumber == 9) || (cycleNumber == 8) || (cycleNumber == 4) || (cycleNumber == 3)) ) { servo1.write(hitServo1 + 5); // we send the servo command } // if we reach the time to send the command to the snare on servo2 if (millis() - timeStartCycle >= timeTotalCycle - timeSnare2) { // we check if this is the one snare of the two, that has to be played, and also if in this cycle a snare has to be played at all if ((previousSnare == 1) && ((cycleNumber == 9) || (cycleNumber == 8) || (cycleNumber == 4) || (cycleNumber == 3)) ) { servo2.write(hitServo2 - 5); // we send the servo command } // we now check if we reached the time to send the command to the third servo, the kick if ((millis() - timeStartCycle >= timeTotalCycle - timeKick)) { // we check if in this cycle a snare has to be played if ( (cycleNumber == 9) || (cycleNumber == 4) || (cycleNumber == 6) || (cycleNumber == 1) ) { // we check on what position was previosly the servo, either hiting the left or the right piezo, this state will be saved later if (previousKick == 0) { servo3.write(hitServo3); } else if (previousKick == 1) { servo3.write(restServo3); } } // finally, we check if the time to turn on the white noise generator was reached, for the hihat if (millis() - timeStartCycle >= (timeTotalCycle - timeHihat)) { // we check if in this cycle the hihat has to be played if ( (cycleNumber == 9) || (cycleNumber == 8) || (cycleNumber == 6) || (cycleNumber == 5) ) { digitalWrite(noiseLed, HIGH); digitalWrite(noiseGenerator, HIGH); } } } } } // This is where the semiquaver cycle ends.

// HIHAT DURATION // turn off hi-hat noise generator, but only under the following conditions: // //if the noise-generator was ON //the time past exceed the time set as sustain //the time past does not reach yet the point where a new noise could start if ( (digitalRead(noiseGenerator) == HIGH) && (millis() - timeStartCycle >= sustainTimeHihat) && (millis() - timeStartCycle < (timeTotalCycle - (timeHihat + 10))) ) { digitalWrite(noiseGenerator, LOW); digitalWrite(noiseLed, LOW); }

// Check if the play/stop switch is switched OFF if (digitalRead(switchPlayStop) == HIGH) { i = timeTotalCycle; //reset time counting digitalWrite(noiseGenerator, LOW); //turn off noise digitalWrite(noiseLed, LOW); //turn off noise servo1.write(restServo1); //stop servos servo2.write(restServo2); //stop servos }

delay(1); }

// If one of the Snares was hit, then declare it as the previous one, in order to hit the other one the next time if ((cycleNumber == 9) || (cycleNumber == 8) || (cycleNumber == 4) || (cycleNumber == 3)) { switch (previousSnare) { case 1: previousSnare = 2; break; case 2: previousSnare = 1; break; default: break; } }

// If one of the piezo kick was hit, then declare it as the previous one, in order to hit the other one the next time if ( (cycleNumber == 9) || (cycleNumber == 4) || (cycleNumber == 6) || (cycleNumber == 1) ) { switch (previousKick) { case 0: previousKick = 1; break; case 1: previousKick = 0; break; default: break; } } }

// SETTING MODE // this mode is activated when the play/stop switch is swiched OFF (logical LOW) void settingMode() { while (digitalRead(switchPlayStop) == HIGH) { // keep doing the following actions while the play/stop switch is OFF if (digitalRead(buttonSelect) == LOW) { // if the selection button is pressed (logical LOW), we change the drumbeat drumbeatID ++; // we select the next drumbeat each time the button is pressed selectDrumBeat(); // select the drumbeat based on the drumbeatID // OPTIONAL // Here you can add whatever piece of code to indicate which drumbeat is being selected, // this could be turning in a led, sending a serial.print(), etc. if (drumbeatID > 7) { //in case we exceed the total number of drumbeats availabe (), we go back to 0. drumbeatID = 0; } delay(100); //delay to avoid detecting button twice when pressed once } } }

// SELECT DRUMBEAT // this functions uses the value stored in drumbeatID, to modify all the variables needed in order to choose between drumbeats. void selectDrumBeat() { switch (drumbeatID) { case 1: // DiscoBasic timeTotalCycle = 124; timeSignature = 44; cycleNumbers[0] = 1; cycleNumbers[1] = 0; cycleNumbers[2] = 5; cycleNumbers[3] = 0; cycleNumbers[4] = 4; cycleNumbers[5] = 0; cycleNumbers[6] = 5; cycleNumbers[7] = 0; cycleNumbers[8] = 1; cycleNumbers[9] = 0; cycleNumbers[10] = 5; cycleNumbers[11] = 0; cycleNumbers[12] = 4; cycleNumbers[13] = 0; cycleNumbers[14] = 5; cycleNumbers[15] = 0; break; case 2: // NewBugalú timeTotalCycle = 155; timeSignature = 44; cycleNumbers[0] = 6; cycleNumbers[1] = 0; cycleNumbers[2] = 5; cycleNumbers[3] = 0; cycleNumbers[4] = 8; cycleNumbers[5] = 0; cycleNumbers[6] = 5; cycleNumbers[7] = 3; cycleNumbers[8] = 5; cycleNumbers[9] = 3; cycleNumbers[10] = 6; cycleNumbers[11] = 0; cycleNumbers[12] = 8; cycleNumbers[13] = 0; cycleNumbers[14] = 5; cycleNumbers[15] = 0; break; case 3: // HiHat16 timeTotalCycle = 134; timeSignature = 44; cycleNumbers[0] = 6; cycleNumbers[1] = 5; cycleNumbers[2] = 5; cycleNumbers[3] = 5; cycleNumbers[4] = 8; cycleNumbers[5] = 5; cycleNumbers[6] = 5; cycleNumbers[7] = 5; cycleNumbers[8] = 6; cycleNumbers[9] = 5; cycleNumbers[10] = 5; cycleNumbers[11] = 5; cycleNumbers[12] = 8; cycleNumbers[13] = 5; cycleNumbers[14] = 5; cycleNumbers[15] = 5; break; case 4: // SwingGroove timeTotalCycle = 153; timeSignature = 128; // (12/8) cycleNumbers[0] = 6; cycleNumbers[1] = 0; cycleNumbers[2] = 0; cycleNumbers[3] = 6; cycleNumbers[4] = 0; cycleNumbers[5] = 5; cycleNumbers[6] = 6; cycleNumbers[7] = 0; cycleNumbers[8] = 0; cycleNumbers[9] = 6; cycleNumbers[10] = 0; cycleNumbers[11] = 5; break; case 5: // BossaNova timeTotalCycle = 200; timeSignature = 44; cycleNumbers[0] = 6; cycleNumbers[1] = 5; cycleNumbers[2] = 5; cycleNumbers[3] = 9; cycleNumbers[4] = 6; cycleNumbers[5] = 5; cycleNumbers[6] = 8; cycleNumbers[7] = 6; cycleNumbers[8] = 6; cycleNumbers[9] = 5; cycleNumbers[10] = 8; cycleNumbers[11] = 6; cycleNumbers[12] = 9; cycleNumbers[13] = 5; cycleNumbers[14] = 5; cycleNumbers[15] = 6; break; case 6: // ShuffleGroove timeTotalCycle = 134; timeSignature = 128; // (12/8) cycleNumbers[0] = 6; cycleNumbers[1] = 0; cycleNumbers[2] = 5; cycleNumbers[3] = 9; cycleNumbers[4] = 0; cycleNumbers[5] = 5; cycleNumbers[6] = 6; cycleNumbers[7] = 0; cycleNumbers[8] = 5; cycleNumbers[9] = 9; cycleNumbers[10] = 0; cycleNumbers[11] = 5; break; case 7: // Franco's beat timeTotalCycle = 142; timeSignature = 44; cycleNumbers[0] = 6; cycleNumbers[1] = 0; cycleNumbers[2] = 5; cycleNumbers[3] = 1; cycleNumbers[4] = 8; cycleNumbers[5] = 0; cycleNumbers[6] = 6; cycleNumbers[7] = 0; cycleNumbers[8] = 5; cycleNumbers[9] = 1; cycleNumbers[10] = 6; cycleNumbers[11] = 0; cycleNumbers[12] = 8; cycleNumbers[13] = 0; cycleNumbers[14] = 6; cycleNumbers[15] = 0; break; default: // Basic 4/4 timeTotalCycle = 144; timeSignature = 44; cycleNumbers[0] = 6; cycleNumbers[1] = 0; cycleNumbers[2] = 5; cycleNumbers[3] = 0; cycleNumbers[4] = 8; cycleNumbers[5] = 0; cycleNumbers[6] = 5; cycleNumbers[7] = 0; cycleNumbers[8] = 6; cycleNumbers[9] = 0; cycleNumbers[10] = 5; cycleNumbers[11] = 0; cycleNumbers[12] = 8; cycleNumbers[13] = 0; cycleNumbers[14] = 5; cycleNumbers[15] = 0; break; } }

Step 12: Play Music With Your Robot Drummer!

That's it, pickup your instrument of preference, plug in your robot drummer, switch on the play/stop switch, and start playing.

Step 13: What's Next?

Alternative line level output
This is, right now, the most needed feature for me, as it would improve a lot the machine's portability. I could simply plug in it into a common bluetooth portable speaker.

MIDI input
I'm currently working on making this thing MIDI controlled, to make it more versatile on live situations. The main challenge to this idea, is the anticipation time needed by this drummer that the midi protocol doesn't function with.

Battery operated
This is the thing that most headache gives me. I haven't been able to figured out how batteries work. I need a reliable and rechargeable way of providing the 12v needed for this thing to function, but nothing has worked so far. In my foolish attempts, I tried a couple of 18650 with a TP4056 module and a voltage elevator module… failed spectacularly. Any ideas?

Arduino Contest 2019

First Prize in the
Arduino Contest 2019



    • Frozen Treats Challenge

      Frozen Treats Challenge
    • Pets Challenge

      Pets Challenge
    • Colors of the Rainbow Contest

      Colors of the Rainbow Contest

    55 Discussions


    10 hours ago

    ABout the only way to handle delay with MIDI is to have the system do a FIXED delay on everything it play. So the sound comes out exatly 500 milisecond late. As long as EVERY soubd is delayed the same you will not notice.

    As for the battey. It is easier to regulate DOWN then up. Four or five of those 18650 batteries in series woud work. Be sure to buy the kind that have internal protection circuits unless you want to firast becaise a battery expert.

    The "old school" method works too - get a big lead-acid battery and a dolly to carry it

    And do you really need 12 volts? The servos run on 5, Aruino on 5


    6 days ago

    so interesting design i can suggest in a future improvement to add a crash and ride sounds , maybe made with a metal sheet that imitates its sound also you can put a hi and medium toms modules ! if someone plays music with a 1.44 floppy driver why cant be this made with yourr electronic drummer ? congratulations from mexico


    10 days ago

    Does it still show up 45 mins late and drunk? Need that for authenticity...

    Great project man. Now I wanna hear it play "Holy Wars... The Punishment Due"

    1 reply

    Reply 6 days ago

    Sorry, it doesn't do that... it also remains quiet while the band is tuning their instruments, so yeah, is not very accurate lol.
    Thank you!


    12 days ago

    Hey nice project. I hope its not unpolitely to ask, but next year i am going to have a final project in my crafts teach mechatronic. And I am thinking about rebuilding this project. So my question is to you have detailed plans or files of this project that i could use to get through this hard final exam?
    thank you in advance

    1 reply

    Reply 11 days ago

    Not at all unpolitely! It's awesome you want to make one, thank you!
    Unfortunately I don't have any plans o files whatsoever, I built it all by hand and kept redesigning the thing at the same time I built it. That's why I focused on the core elements of the project, so if someone wanted to replicate it, they use their own enclosures. I could take some measures of the sticks and other parts, but for example the enclosure doesn't have to be a cube, that only complicates things even more, I just did it that way because I wanted it to be portable.
    I could definitely send you more pictures of mine though, and give you advice while you build yours.


    13 days ago

    This is a great piece of work. Beautiful ! This is good project !

    1 reply

    16 days ago

    Wonderful work, artfully realized and beautifully executed. I had one suggestion however. I was thinking that your numbering system for the elements could be replaced by using a single byte, with one bit for each element, eg. Kick = 1 (b0000 0001), snare1 = 2 (b0000 0010), HiHat = 4 (b0000 0100) then Kick & HiHat = 5 (b0000 0101), kick and snare = 3 (b0000 0011) etc.
    You can reduce your storage requirements by using byte vs int (more room for tracks) and set up additional elements in the same amount of storage. Or use the High bit (b1000 0000) as your "previous" flag. This would also simplify your code by allowing you to do bitwise logic to select your instruments eg:
    "// we check if in this cycle a snare has to be played
    if ( (cycleNumber == 9) || (cycleNumber == 4) || (cycleNumber == 6) || (cycleNumber == 1) ) "
    can be replaced by:
    byte snare = 2; (in setup) then
    " if (cycleNumber & snare) {your code here}"
    or, by the same token,
    digitalWrite(SnarePin, cycleNumber & snare); //make snare output high
    Again, it would save you a lot of storage, allowing more instruments or more tracks, etc.
    But these are the sorts of things you learn from experience...

    1 reply

    Reply 13 days ago

    Mate, great idea!
    Such a simple and elegant solution, yet it never occurred to me. I wish I had this pointed out to me when I was all tangled up in my own code.
    As you said, I could include the previous flag in that byte, or even other parameters that I needed, like short or long sustain for hihat.
    I will definitely be incorporating this solution in my project.
    Thanks a lot!


    18 days ago

    Buenísimo!!! Probá enviar midi al ableton, y asi tendrás sonidos reales...


    4 weeks ago

    Wow, very nice work. I don't think you need to worry about any lack of formal electronics education: it's clear you know what you're doing in this regard. Now the only thing you need to learn is how to sing.

    1 reply

    4 weeks ago

    Excellent work - a "real-ization" of the famous Animusic concept. Especially impressive for someone with no formal training in electronics or programming. The anticipation timing, in particular, is mind-bending, and finding different solutions would be a great subject for a software design class.
    I had to chuckle at "switch-foot" - that's cute :-) Languages can separate us, but music and hobbies link us.

    3 replies

    Reply 4 weeks ago

    Haha! I practiced again and again what I was going to say, but I knew I was gonna mess something up. Always learning. Thank you for your nice words (:


    Reply 4 weeks ago

    You're welcome, Franco! And don't worry about the language: those of us who speak it every day usually do much worse! The "takeaway" here is that in English the adjectives come before the noun, so "footswitch" is correct. What is difficult is the stressing: if the adjective merely describes an object, the stress is on the noun, e.g. "wooden BOX", not "WOODEN box"; however if the adjective is used to specify WHICH box (i.e. if there are more than one), then we stress the adjective: the "OAK box, not the PINE box". If we are drawing particular attention to the state or condition of the object as we talk about it, we stress them equally: "the OPEN BOX".
    There is a fun exercise in learning to speak English out loud: the sentence "I didn't say she stole my money". Try to say it seven times, each time stressing a different word: it means something slightly different each time.
    Back to your footswitch: in this particular case, the fact that the switch is explicitly designed to be operated with the foot makes it so special that we stress it "FOOTswitch". Also, because the foot operation is such a fundamental part of the design, the adjective gets incorporated with the noun into a single word. That doesn't happen very often in modern English, but it is very common in German.
    One special and amusing case - I learned it when I moved from England to North America - is chicken soup: in England we pronounce it "chicken SOUP", while here we say "CHICKEN-soup" - almost as if it is one word, even though it isn't - yet!
    At least we don't have gender in English - the switch isn't a he or a she, it's an "it"!
    Good luck with your music, and your electronics/computing. My son has similar mixed interests; I will show him your project in the hope that it will inspire him!


    Reply 4 weeks ago

    This is very helpful! I've learned something here. Someone else pointed out to me that footswitch was the proper word, but I didn't really understand why. I think I have a better understanding know.
    I'd say you never finish learning a language, although English seems to be relatively simpler than say, Spanish (my first language). We do have gender for all nouns ):
    I hope your son like my project!
    Thank you very much for your comments (: