Today's pointless coronavirus-fueled project is playing Despacito on an Arduino. Yes, I know the meme is dead at this point.
Can't play the video? Download it (right click, save as) (28MB)
The idea is to use a piezo buzzer for the melody and a relay for the drums, but there are some technical problems to face:
To solve this problem in the easiest way possible, I decided to make a very simple tracker. The time is divided into intervals of 160ms (that's the length of a 1/8th note in Despacito), the song is stored as 3 arrays of equal length (64 for this song), a pointer is moved forward after each interval and points at what should be played in the next interval. The 3 arrays are
The loop simply iterates through this array at a constant rate determined by the value of INTERVAL, and at each iteration it reads the 3 arrays to determine what to do.
To play a note, we use the tone function of the Arduino. This was originally a library but was merged into the core library of Arduino a few years ago. This function uses one of the timers to pulse a square wave at a very precise timing to create a tone. This is done asynchronously so while the tone is playing we can click the relay. Technically we have enough timers to add a second tone and make it even better, but that will be a project for another day.
Parts used:
The schematic is very simple, but there are 2 things worthy of notice:
#define SPEAKER 3
#define DRUMS 5
#define INTERVAL 160
#define NOTE_SPACING 16
const uint16_t FREQUENCIES[]={0,31,33,35,37,39,41,44,46,49,52,55,58,62,65,69,73,78,82,87,93,98,104,110,117,123,131,139,147,156,165,175,185,196,208,220,233,247,262,277,294,311,330,349,370,392,415,440,466,494,523,554,587,622,659,698,740,784,831,880,932,988,1047,1109,1175,1245,1319,1397,1480,1568,1661,1760,1865,1976,2093,2217,2349,2489,2637,2794,2960,3136,3322,3520,3729,3951,4186,4435,4699,4978};
const uint16_t SONG_LENGTH=64;
const uint8_t LEADTK[]={52,0,0,0,51,0,0,0,49,0,44,0,44,44,44,44,44,49,49,49,49,0,47,49,0,0,45,0,45,45,45,45,45,49,49,49,49,0,51,52,0,0,47,0,47,47,47,47,52,51,52,51,52,0,54,54,0,51,0,0,0,0,0,0};
const uint8_t LEADLN[]={4,0,0,0,4,0,0,0,2,0,1,0,1,1,1,1,1,1,1,1,2,0,1,1,0,0,1,0,1,1,1,1,1,1,1,1,2,0,1,1,0,0,1,0,1,1,1,1,1,1,1,1,2,0,1,2,0,3,0,0,0,0,0};
const uint8_t DRUMTK[]={0,0,0,0,0,0,0,0,30,0,0,5,5,0,5,0,30,0,0,5,5,0,5,0,30,0,0,5,5,0,5,0,30,0,0,5,5,0,5,0,30,0,0,5,5,0,5,0,30,0,0,5,5,0,5,0,30,0,0,5,5,0,5,0};
void setup() {
pinMode(SPEAKER,OUTPUT);
pinMode(DRUMS,OUTPUT);
}
uint16_t ctr=0,t=0;
void loop() {
t=millis();
if(LEADLN[ctr]!=0){
noTone(SPEAKER);
if(LEADTK[ctr]!=0) tone(SPEAKER,FREQUENCIES[LEADTK[ctr]],LEADLN[ctr]*INTERVAL-NOTE_SPACING);
}
if(DRUMTK[ctr]!=0){
digitalWrite(DRUMS,HIGH);
delay(DRUMTK[ctr]);
digitalWrite(DRUMS,LOW);
}
ctr=(ctr+1)%SONG_LENGTH;
delay(INTERVAL-(millis()-t));
}
Download project for Arduino IDE and Fritzing
You are free to do what you want with this code and schematic.