Components and supplies
Arduino UNO
SparkFun Electret Microphone Breakout
Rotary potentiometer (generic)
Piezo Element
Transistor - NPN, 60V 200mA (2N3904)
Slide Switch
Ultra-small LM2596 Power Supply Module DC / DC BUCK 3A adjustable buck Module Regulator Ultra LM2596S Compatible With Arduino by Atomic Market
SG90 Micro-servo motor
Tactile Switch, Top Actuated
Breadboard (generic)
LAOMAO DC-DC Step-up Boost Power Supply Module Adjustable Power Apply 3V-32V to 5V-35V XL6009 400KHz 4A Max
Tools and machines
Soldering iron (generic)
Mastech MS8217 Autorange Digital Multimeter
Apps and platforms
Arduino IDE
Project description
Code
DrumCube, a robot drummer
arduino
1// DrumCube - a robot drummer 2// written by Franco Molina @artefrancomolina 3 4// Setting servos 5#include <Servo.h> 6Servo servo1; 7Servo servo2; 8Servo servo3; 9 10// Servo positions 11// this will differ depending on your servos, please test yours to find out the values that best suit you 12byte restServo1 = 12; 13byte hitServo1 = 21; 14byte restServo2 = 123; 15byte hitServo2 = 114; 16byte restServo3 = 4; 17byte hitServo3 = 19; 18 19// Setting the HiHat white noise generator 20#define noiseGenerator 12 21#define noiseLed 13 //turn on led as a visual representation of the noise being generated 22 23// Setting servo times 24// this will also differ depending on your servos, please test yours to find out the values that best suit you 25byte timeSnare1 = 110; 26byte timeSnare2 = 108; 27byte timeKick = 71; 28byte timeHihat = 20; 29byte sustainTimeHihat = 70; 30 31// Setting previous Snare and Kick 32byte previousSnare = 2; 33byte previousKick = 0; 34 35 36// Setting cycle times 37static unsigned long timeStartCycle; 38static 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 39 40// Bar and Cycles variables 41int cycleNumber; 42int 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 43byte timeSignature = 44; 44int drumbeatID = 0; // ID number for each drumbeat 45 46// 47int i; // for counting the time in the "for loop" of the cyclePlayer function 48int b; // for the "for loop" that counts the number of cycles 49 50// control interface 51#define switchPlayStop 2 // switch bettween playing and stop 52#define buttonSelect 3 // tact button that select the drumbeat to play 53 54 55 56 57 58 59 60void setup(void) { 61 62 // define pins for each servo 63 pinMode (5, OUTPUT); 64 pinMode (6, OUTPUT); 65 pinMode (9, OUTPUT); 66 67 // attach servos to those pins 68 servo1.attach(5); //caja 1 69 servo2.attach(6); //caja 2 70 servo3.attach(9); //bombo 71 delay(150); 72 73 // put all servos on rest position 74 servo1.write(restServo1); 75 servo2.write(restServo2); 76 servo3.write(restServo3); 77 delay(300); 78 79 // Setting hihat and led pinmodes 80 pinMode (noiseGenerator, OUTPUT); 81 digitalWrite(noiseGenerator, LOW); 82 pinMode (noiseLed, OUTPUT); 83 digitalWrite(noiseLed, LOW); 84 85 // Setting control interface pinmodes 86 pinMode (switchPlayStop, INPUT_PULLUP); 87 pinMode (buttonSelect, INPUT_PULLUP); 88 89} 90 91 92 93void loop(void) { 94 if (switchPlayStop == LOW) { //if the play/stop switch is ON (logical LOW) 95 96 //We start a "for loop" to play a semiquaver cycle a maximum of 16 times, for every bar 97 for (b = 0; b < 16; b = b + 1) { 98 99 selectDrumBeat(); // select the drumbeat based on the drumbeatID selected 100 cyclePlayer(cycleNumbers[b]); //play the semiquaver cycle for each number stored in the cycleNumbers array 101 102 // if we reach the maximum number of cycles (16 for 4/4, 12 for 6/8, 12/8 or 3/4) we start again 103 if (b == 11 && (timeSignature == 68 || timeSignature == 128)) { 104 b = -1; 105 } 106 if (b == 15) { 107 b = -1; 108 } 109 } 110 111 } 112 // If the play/stop switch is OFF (logical HIGH) we enter settingMode 113 else { 114 settingMode(); // function that lets you choose between different drumbeats and wait for the play switch to be activated 115 } 116} 117 118 119 120 121 122// CYCLE PLAYER 123// this functions runs a semiquaver cycle every time is called. 124void cyclePlayer(int cycleNumber) { // we store every single value of the cycleNumbers array into the cycleNumber variable 125 timeStartCycle = millis(); // we save the starting time, to compare it later with the actual time and get the time past 126 127 //set both snare servos to rest position in case they were on hit position 128 servo1.write(restServo1); 129 servo2.write(restServo2); 130 131 //we star a "for loop" for the entire duration of every semiquaver cycle 132 for (i = 0; i < timeTotalCycle; i++) { 133 134 //now we send the hitting commands on time so they reach their destination on time (the end of the semiquaver cycle) 135 136 // 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. 137 if ((millis() - timeStartCycle >= timeTotalCycle - timeSnare1)) { 138 // we check if this is the one snare of the two, that has to be played, 139 // 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) 140 if ((previousSnare == 2) && ((cycleNumber == 9) || (cycleNumber == 8) || (cycleNumber == 4) || (cycleNumber == 3)) ) { 141 servo1.write(hitServo1 + 5); // we send the servo command 142 } 143 // if we reach the time to send the command to the snare on servo2 144 if (millis() - timeStartCycle >= timeTotalCycle - timeSnare2) { 145 // 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 146 if ((previousSnare == 1) && ((cycleNumber == 9) || (cycleNumber == 8) || (cycleNumber == 4) || (cycleNumber == 3)) ) { 147 servo2.write(hitServo2 - 5); // we send the servo command 148 } 149 // we now check if we reached the time to send the command to the third servo, the kick 150 if ((millis() - timeStartCycle >= timeTotalCycle - timeKick)) { 151 // we check if in this cycle a snare has to be played 152 if ( (cycleNumber == 9) || (cycleNumber == 4) || (cycleNumber == 6) || (cycleNumber == 1) ) { 153 // we check on what position was previosly the servo, either hiting the left or the right piezo, this state will be saved later 154 if (previousKick == 0) { 155 servo3.write(hitServo3); 156 } 157 else if (previousKick == 1) { 158 servo3.write(restServo3); 159 } 160 } 161 // finally, we check if the time to turn on the white noise generator was reached, for the hihat 162 if (millis() - timeStartCycle >= (timeTotalCycle - timeHihat)) { 163 // we check if in this cycle the hihat has to be played 164 if ( (cycleNumber == 9) || (cycleNumber == 8) || (cycleNumber == 6) || (cycleNumber == 5) ) { 165 digitalWrite(noiseLed, HIGH); 166 digitalWrite(noiseGenerator, HIGH); 167 } 168 } 169 } 170 } 171 } 172 // This is where the semiquaver cycle ends. 173 174 // HIHAT DURATION 175 // turn off hi-hat noise generator, but only under the following conditions: 176 // //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 177 if ( (digitalRead(noiseGenerator) == HIGH) && (millis() - timeStartCycle >= sustainTimeHihat) && (millis() - timeStartCycle < (timeTotalCycle - (timeHihat + 10))) ) { 178 digitalWrite(noiseGenerator, LOW); 179 digitalWrite(noiseLed, LOW); 180 } 181 182 // Check if the play/stop switch is switched OFF 183 if (digitalRead(switchPlayStop) == HIGH) { 184 i = timeTotalCycle; //reset time counting 185 digitalWrite(noiseGenerator, LOW); //turn off noise 186 digitalWrite(noiseLed, LOW); //turn off noise 187 servo1.write(restServo1); //stop servos 188 servo2.write(restServo2); //stop servos 189 } 190 191 delay(1); 192 } 193 194 // If one of the Snares was hit, then declare it as the previous one, in order to hit the other one the next time 195 if ((cycleNumber == 9) || (cycleNumber == 8) || (cycleNumber == 4) || (cycleNumber == 3)) { 196 switch (previousSnare) { 197 case 1: 198 previousSnare = 2; 199 break; 200 case 2: 201 previousSnare = 1; 202 break; 203 default: 204 break; 205 } 206 } 207 208 // 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 209 if ( (cycleNumber == 9) || (cycleNumber == 4) || (cycleNumber == 6) || (cycleNumber == 1) ) { 210 switch (previousKick) { 211 case 0: 212 previousKick = 1; 213 break; 214 case 1: 215 previousKick = 0; 216 break; 217 default: 218 break; 219 } 220 } 221} 222 223 224 225 226// SETTING MODE 227// this mode is activated when the play/stop switch is swiched OFF (logical LOW) 228void settingMode() { 229 while (digitalRead(switchPlayStop) == HIGH) { // keep doing the following actions while the play/stop switch is OFF 230 if (digitalRead(buttonSelect) == LOW) { // if the selection button is pressed (logical LOW), we change the drumbeat 231 drumbeatID ++; // we select the next drumbeat each time the button is pressed 232 selectDrumBeat(); // select the drumbeat based on the drumbeatID 233 // OPTIONAL 234 // Here you can add whatever piece of code to indicate which drumbeat is being selected, 235 // this could be turning in a led, sending a serial.print(), etc. 236 if (drumbeatID > 7) { //in case we exceed the total number of drumbeats availabe (), we go back to 0. 237 drumbeatID = 0; 238 } 239 delay(100); //delay to avoid detecting button twice when pressed once 240 } 241 } 242} 243 244 245 246 247 248 249// SELECT DRUMBEAT 250// this functions uses the value stored in drumbeatID, to modify all the variables needed in order to choose between drumbeats. 251void selectDrumBeat() { 252 switch (drumbeatID) { 253 case 1: // DiscoBasic 254 timeTotalCycle = 124; 255 timeSignature = 44; 256 cycleNumbers[0] = 1; 257 cycleNumbers[1] = 0; 258 cycleNumbers[2] = 5; 259 cycleNumbers[3] = 0; 260 cycleNumbers[4] = 4; 261 cycleNumbers[5] = 0; 262 cycleNumbers[6] = 5; 263 cycleNumbers[7] = 0; 264 cycleNumbers[8] = 1; 265 cycleNumbers[9] = 0; 266 cycleNumbers[10] = 5; 267 cycleNumbers[11] = 0; 268 cycleNumbers[12] = 4; 269 cycleNumbers[13] = 0; 270 cycleNumbers[14] = 5; 271 cycleNumbers[15] = 0; 272 break; 273 case 2: // NewBugalú 274 timeTotalCycle = 155; 275 timeSignature = 44; 276 cycleNumbers[0] = 6; 277 cycleNumbers[1] = 0; 278 cycleNumbers[2] = 5; 279 cycleNumbers[3] = 0; 280 cycleNumbers[4] = 8; 281 cycleNumbers[5] = 0; 282 cycleNumbers[6] = 5; 283 cycleNumbers[7] = 3; 284 cycleNumbers[8] = 5; 285 cycleNumbers[9] = 3; 286 cycleNumbers[10] = 6; 287 cycleNumbers[11] = 0; 288 cycleNumbers[12] = 8; 289 cycleNumbers[13] = 0; 290 cycleNumbers[14] = 5; 291 cycleNumbers[15] = 0; 292 break; 293 case 3: // HiHat16 294 timeTotalCycle = 134; 295 timeSignature = 44; 296 cycleNumbers[0] = 6; 297 cycleNumbers[1] = 5; 298 cycleNumbers[2] = 5; 299 cycleNumbers[3] = 5; 300 cycleNumbers[4] = 8; 301 cycleNumbers[5] = 5; 302 cycleNumbers[6] = 5; 303 cycleNumbers[7] = 5; 304 cycleNumbers[8] = 6; 305 cycleNumbers[9] = 5; 306 cycleNumbers[10] = 5; 307 cycleNumbers[11] = 5; 308 cycleNumbers[12] = 8; 309 cycleNumbers[13] = 5; 310 cycleNumbers[14] = 5; 311 cycleNumbers[15] = 5; 312 break; 313 case 4: // SwingGroove 314 timeTotalCycle = 153; 315 timeSignature = 128; // (12/8) 316 cycleNumbers[0] = 6; 317 cycleNumbers[1] = 0; 318 cycleNumbers[2] = 0; 319 cycleNumbers[3] = 6; 320 cycleNumbers[4] = 0; 321 cycleNumbers[5] = 5; 322 cycleNumbers[6] = 6; 323 cycleNumbers[7] = 0; 324 cycleNumbers[8] = 0; 325 cycleNumbers[9] = 6; 326 cycleNumbers[10] = 0; 327 cycleNumbers[11] = 5; 328 break; 329 case 5: // BossaNova 330 timeTotalCycle = 200; 331 timeSignature = 44; 332 cycleNumbers[0] = 6; 333 cycleNumbers[1] = 5; 334 cycleNumbers[2] = 5; 335 cycleNumbers[3] = 9; 336 cycleNumbers[4] = 6; 337 cycleNumbers[5] = 5; 338 cycleNumbers[6] = 8; 339 cycleNumbers[7] = 6; 340 cycleNumbers[8] = 6; 341 cycleNumbers[9] = 5; 342 cycleNumbers[10] = 8; 343 cycleNumbers[11] = 6; 344 cycleNumbers[12] = 9; 345 cycleNumbers[13] = 5; 346 cycleNumbers[14] = 5; 347 cycleNumbers[15] = 6; 348 break; 349 case 6: // ShuffleGroove 350 timeTotalCycle = 134; 351 timeSignature = 128; // (12/8) 352 cycleNumbers[0] = 6; 353 cycleNumbers[1] = 0; 354 cycleNumbers[2] = 5; 355 cycleNumbers[3] = 9; 356 cycleNumbers[4] = 0; 357 cycleNumbers[5] = 5; 358 cycleNumbers[6] = 6; 359 cycleNumbers[7] = 0; 360 cycleNumbers[8] = 5; 361 cycleNumbers[9] = 9; 362 cycleNumbers[10] = 0; 363 cycleNumbers[11] = 5; 364 break; 365 case 7: // Franco's beat 366 timeTotalCycle = 142; 367 timeSignature = 44; 368 cycleNumbers[0] = 6; 369 cycleNumbers[1] = 0; 370 cycleNumbers[2] = 5; 371 cycleNumbers[3] = 1; 372 cycleNumbers[4] = 8; 373 cycleNumbers[5] = 0; 374 cycleNumbers[6] = 6; 375 cycleNumbers[7] = 0; 376 cycleNumbers[8] = 5; 377 cycleNumbers[9] = 1; 378 cycleNumbers[10] = 6; 379 cycleNumbers[11] = 0; 380 cycleNumbers[12] = 8; 381 cycleNumbers[13] = 0; 382 cycleNumbers[14] = 6; 383 cycleNumbers[15] = 0; 384 break; 385 default: // Basic 4/4 386 timeTotalCycle = 144; 387 timeSignature = 44; 388 cycleNumbers[0] = 6; 389 cycleNumbers[1] = 0; 390 cycleNumbers[2] = 5; 391 cycleNumbers[3] = 0; 392 cycleNumbers[4] = 8; 393 cycleNumbers[5] = 0; 394 cycleNumbers[6] = 5; 395 cycleNumbers[7] = 0; 396 cycleNumbers[8] = 6; 397 cycleNumbers[9] = 0; 398 cycleNumbers[10] = 5; 399 cycleNumbers[11] = 0; 400 cycleNumbers[12] = 8; 401 cycleNumbers[13] = 0; 402 cycleNumbers[14] = 5; 403 cycleNumbers[15] = 0; 404 break; 405 } 406}
Downloadable files
Kick Schematic
Amplifier circuit for the piezos in the kick system
Kick Schematic
Snare Schematic
Amplifier circuit for the electret microphone in the Snare system
Snare Schematic
Full Diagram
Full diagram of the project
Full Diagram
Audio signal mixer
Audio signal mixer
Kick Schematic
Amplifier circuit for the piezos in the kick system
Kick Schematic
Snare Schematic
Amplifier circuit for the electret microphone in the Snare system
Snare Schematic
HiHat Generator Schematic
White noise generator and high-pass filter to replicate the cymbals sound.
HiHat Generator Schematic
Full Diagram
Full diagram of the project
Full Diagram
Audio signal mixer
Audio signal mixer
HiHat Generator Schematic
White noise generator and high-pass filter to replicate the cymbals sound.
HiHat Generator Schematic
Comments
Only logged in users can leave comments
FrancoMolina
0 Followers
•0 Projects
Table of contents
Intro
45
0