What does it do?
Plays the song K.K. Bossa from Animal Crossing and an animation using an Arduino Uno, a piezo, and a 16X2 LCD.
The animation is based off of Animal Crossing New Leaf.
The top video is with the male villager and the bottom video is with the female villager (toggled within the sketch).
This is my first instructable, so enjoy!
Why do this?
I got bored of the simplicity of my Arduino Starter Kit Projects Book. I thought this would be something different and fun. I originally thought it would take me two weeks, but it ended up taking me about a month (3/23/2016 - 4/21/2016).
What makes this special?
First off the piezo is playing two tones simultaneously - one for the treble and one for the bass. This produces "richer" music by the inclusion of the bass. The code can easily be modified to remove all the animation aspects and simply be used to play two toned music (or more if you have an Arduino Mega, but more code needs be written in).
Secondly, I would consider the way I handled the animation to be an upgrade from current methods. Anyone that has created custom chars on a 16x2 LCD will know in order to simply move - say kk slider - across the screen, one must type in each custom char for each frame. My code, on the other hand, just pulls the appropriate panes from the larger kk slider image to create the custom chars for the display. I leave some details about it below in step 5. Searching on instructables, the only other person I saw that had the same idea is UselessBagOfMostlyWater.
Thirdly, this offers a range of some animation techniques beyond horizontal translations such as vertical translations (~1:31), displaying one pixel column at a time (~1:00), and overlapping images (~1:48 used for the weather).
Fourthly, the ability to fade using PWM. I just used a pull down resistor, but I have seen in forums that say you need a RC filter. I'm not sure it depends on the type of LCD, but my way worked.
Step 1: Materials
This project is compatible with the Arduino Starter Kit, i.e. all materials needed are within the kit.
1 x Arduino Uno
1 x LCD 16x2
1 x Piezo Buzzer
1 x Push Button
2 x 220 ohm Resistors
2 x 1,000 ohm Resistors
1 x 10,000 ohm Resistor
# x Jumper Cables
Step 2: Download Tone Library
The Tone Library allows one to be able to play up to three tones (on a Arduino Uno) using a single piezo. Click the link here for its documentation: https://code.google.com/archive/p/rogue-code/wikis/ToneLibraryDocumentation.wiki.
See here on how to import a zip library if you don't know how: https://www.arduino.cc/en/Guide/Libraries#toc2.
The Arduino Uno has three internal timers, hence it can play up to three tones on a single piezo. However taking over timer 0 to play tones will cause functions such as delay() and millis() to not work. Each Tone must use one timer. For the Arduino Uno: pins 5 and 6 are paired on timer 0, pins 9 and 10 are paired on timer 1, and pins 3 and 11 are paired on timer 2. So each Tone must use separate timer PWM pins.
For example: I used pins 10 and 11 which take up timers 1 and 2.
Important: For users that already have the Tone Library, you will need to copy and paste all note frequency definitions from my Tone.h file in order to use my code. Simply add the sharps and flats. If you remove any of the definitions from your Tone.h file, then you lose compatibility with your older codes that relied on it.
Three major things I changed from the standard Tone.h file:
1. I do not like the naming convention of calling sharps and flats as NOTE_AS4 and NOTE_AF4. I changed them all to NOTE_A4S and NOTE_A4F.
2. I included sharps and flats for all notes. Not too big of an issue, but some musical pieces will say use a C sharp instead of a D.
3. I included a rest. Anyone that has played music on an Arduino knows to include this.
Step 3: Wiring
Just follow the diagrams and hope I didn't make any mistakes. This was my first time using Fritzing and halfway through I realized I had rotated the breadboard upside down, so I had to start everything all over.
Note: There must be 1,000 ohm resistors in line with pin 10 and 11 as the Tone Library Documentation requires it.
In my image, I added an additional 1,000 ohm resistor in line with pin 11. I did this to make the bass play at lower volume.
Step 4: Upload Code
I have included the my sketch, my sprites that I used, and also the sheet music to give credit to the composer. Although I did alter the song a tiny bit in maybe three places because it sounded bad on the piezo.
The main sketch is titled: KK_Bossa_Song_PROGMEM_Animation
Step 5: How It Works
First, I think I need to address what PROGMEM is to beginners. PROGMEM is way to store variables into the program memory as opposed to the dynamic memory or SRAM. If a sketch has too many global variables, one may surpass the amount of SRAM. When that happens, the sketch won't work and will crash. So one may move all variables to the program memory to free up space within SRAM. However, special functions need to be called in order to retrieve the variables from program memory space. It is tricky business and can be very frustrating at times, but it is the best thing to do when working with very long arrays in order to save (SRAM) space. Refer here for more details and examples.
How the Song Works:
In order to play multiple tones, I divide each beat into four smaller beats - which I called mini beats. So each mini beat is equivalent to a 16th note. These mini beats act as the counter for when a note should be played and when it should end - simple as that. In actuality, the mini beat just needs to be the smallest note within the entire piece. I chose a 16th note because very few pieces have 32nd notes. Yes, some orchestra pieces have 32nd notes, but do you really want to play that on an arduino? In any case, it would be very easy to change it to 32nd note mini beats if you so desire.
How the Animation Works:
Instead of writing all of my custom char arrays in binary, octal, or hex, everything is written in decimal. You can in fact create custom char using decimal values between 0-31.
Now the computer still sees the integer as binary value in the back end, so by using bit operations you can shift that value to just grab a length five substring from it to use for the custom char creation. (note: each pane on the 16x2 LCD is five pixels wide).
For example: Looking at my excel spreadsheet, say I want the first five pixels on kk slider on row 0 from columns 12-8. The decimal value of the entire row is 896 - which is 0001110000000 in binary. So if I shift 896 eight times to the left, I will get 3 - which is 00011 in binary.
Do the above on eight total rows to get enough data to create a custom char. That's the gist of it.
So why use decimal values? You don't actually have to, it is purely for aesthetics. Typing a bunch of 0's and 1's could drive you insane and there is a lot more room for error. In addition, I don't like having an custom char take up so many rows, so that's why I just cram one image into a single row. If you were using binary values each row would be super long to scroll through. So it is whatever you prefer. To my surprise, my sketch actually works either way (I tested it).