Arduino Music From Sheet Music
by thedeveloperguy in Circuits > Arduino
7710 Views, 6 Favorites, 0 Comments
Arduino Music From Sheet Music
It's december again, already christmas. This season is (in)famous for those jingling ornaments, gift cards, you name it. Love it or hate it, it's pretty simple to make one of those with Your favorite tune.
In this tutorial you will learn how to transform a monophonic melody to code!
(since it's christmas, the example will be familiar)
Supplies
An Arduino (compatible) board
Piezo buzzer (with proper driver circuit)
Music to play
Convert From Notes to Frequency
Every note has a frequency. Higher frequency = higher sound.
You can check every note, for example here: online signal generator. Also, this site can play you the sine wave version and the square wave verision too. Get used to it - most of the Arduino boards can only play square waves.
It would be so much easier if someone had written down all the frequencies for all the notes! Oh wait, they did. Now we have to "decode" the frequency one musical note at a time. Do you know that weirdo f? That's the "violin key" - that means we know the absolute value of the notes, not just the relative. I included a little cheat sheet to speed up the decoding process. Start decoding the notes.
Note Lengths
You don't have to play a note forever!
Each note has a relative length, and the music has a tempo. BPM - beat per minute, or how many quarter notes in 4/4 music.
Some music to put the values in perspective:
- Taylor Swift: Willow - 78 BPM
- Billie Eilish: Dont Smile At Me - 92 BPM
- Bee Gees: Stayin' Alive - 104 BPM (hum this while performing a CPR, no joke)
- AC/DC: Thunderstruck - 136 BPM
- The Prodigy: No Good (Start The Dance) - 144 BPM
- Dune: Million miles from home - 171 BPM
- S3RL: Dopamine - 175 BPM
- Blümchen: Nur geträumt - 180 BPM
(yes, the 90' had some fast music in the radio)
60 / BPM * 1000 = how many miliseconds per 1/4 note. Do the math for the others.
The Circuit
I wasn't joking about the proper driver circuit! Piezo buzzers are more like "capacitive loads", that means they act like little capacitors. That means turning on and off them (more like driving one of its pin to HIGH or LOW) causes (relative) huge current spikes, and microcontrollers aren't into that stuff. If you don't believe me or would like to know a bit more about this, read this article from DigiKey!
⚠️Dumb Mistake Alert⚠️
Swapping to "regular" speaker isn't better, they are "inductive loads", even worse! Switching power supplies transform DC to DC with inductors, so worst case it can kick back even higher voltages than your power supply! And what happens when you "forget" to switch off an inductor? That's right, short circuit with unlimited amps drawn!
So either get a proper piezo module or make a driver circiut. Never ever drive a load directly from a pin. Select a friendly, PWM capable pin.
Convert to Code
Now you have the notes and lengths. That's already enough work, get the source code with the notes defined. Just copy-paste.
Store the notes and lengths in arrays, and play each oh them while iterating. Quick note: I used a "tempo" variable and relative note lengths for fast adjustments.
The tone() function plays the tone, only one at a time. First parameter is the pin, the second is the frequency to play, the third is how long.
While some Arduino functions "block" execution, meaning you stuck there until it finishes (yes, analogRead(), no one likes to wait), tone() just does everything "in the background", so wait manually, for example with a delay().
Sometimes the result just doesn't sound right. Adjust the weirdo notes!
Enjoy!
Upload the final version and enjoy your work!
I hope you found this tutorial useful!