Amazing Musical Giftbox
I received mail from Piotr Zimnowlodzki last week who showed me this cool hack using the PlayTune library and my midi converter script to play “Can you feel the love tonight” an attiny. Much better than the cheap greeting card hack, amazing craftmanship!
Filed under: Uncategorized | Leave a Comment
Here is another weekend hack that plays around with my midi to AVR conversion script and library. With xmas fast approaching I thought it would be fun to convert a pacman candy tin to an xmas ornament and have it play music. Below is the result, pressing a button on the tin will cycle through three Ms. Pacman songs converted from midi files found online.
Construction
Once I had the circuit working on a breadboard it was just a matter of finding a prototype board that fit and some ugly soldering to glue it all together. In my case I had these parts lying around (including the tin) but if you wanted to buy everything it would cost between $5-$10.
- PacMan ghost candy tin
- Prototype Board
- A couple stand-offs and screws
- Two 1k potentiometers
- Piezzo Speaker
- Batter holder
- Coin cell battery
- DIP socket
- ATTINY85 Microcontroller(8k of flash, internal clock @ 8MHz)
- Push-button switch
Other materials..
- AVR SPI programmer or an Arduino to program the attiny
- A drill with a decent bit to cut through the tin
- Musescore sequencing software (free)
- Soldering iron, wires, a free afternoon, etc.
The circuit is only slightly more complicated than the musical greeting card. Two 1K potentiometers are used to mix the two square waves into one speaker. The push switch is connected to the external interrupt pin which is set low when pressed. On the prototype board the switch is wired on the opposite side of the circuit so that the speaker faces down when placed in the candy tin. This makes it louder by drilling holes in the back piece (see below). Standoffs are used to prop up the non-speaker side of the circuit.
Nothing is needed to hold the the circuit board in the tin since the button keeps it in place and there isn’t a lot of extra room when it is put together.
Software
(for more on the PlayTune library see my earlier post on using the PlayTune library with an Arduino)
Like the musical greeting card we will use the PlayTune library to play the melody and the xml2h.py to handle the musical conversion. The conversion takes a single track and converts it into two byte arrays of pitches and delays. The pitch values are a function of clock frequency and the prescaler.
The total size of the program ends up being around 2k so there is plenty of room to add more songs if you are inclined.
I used three midi files for the songs and loaded them into musescore. In the application it was necessary to transpose it an octave, other than that there wasn’t much else to do since these songs are already two-tracks which is exactly what we want for the attiny.
After saving the midi file as a MusicXML file a header file is created for each song. These header files are what the PlayTune library uses for tone and delay values.
The prescale values scale the frequency of the clock by a power of 2. Ideally you want the lowest value given in the list though TIMER0 only supports values of 1024, 256, 64 and 8 so for the first part “64″ is chosen.
For TIMER1 (part2) the lowest number can be selected to give the highest timer resolution. The reason this is important is because the frequency of the square waves generated on the two microcontroller pins are only an approximation of the note frequency. Higher frequency == greater timer resolution == better pitch accuracy.
The AVR is immediatly put into power-down sleep mode. When an external level change on the INT0 pin is detected (button press) the ISR routine will run which will play one of the three tunes.
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "playtune.h"
#include "songs/mspacman-acti-they-meet-attiny.h"
#include "songs/mspacman-game-start-attiny.h"
#include "songs/mspacman-actii-the-chase-attiny.h"
int main(void)
{
// setup interrupt
GIMSK |= (1<<INT0); // INT0 enabled for interrupts
while(1) {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
}
return(0);
}
volatile uint8_t tune = 0;
ISR (INT0_vect)
{
PlayTune theymeet0(0,MSPACMAN_ACTI_THEY_MEET0);
PlayTune theymeet1(1,MSPACMAN_ACTI_THEY_MEET1);
PlayTune gamestart0(0,MSPACMAN_GAME_START0);
PlayTune gamestart1(1,MSPACMAN_GAME_START1);
PlayTune thechase0(0,MSPACMAN_ACTII_THE_CHASE0);
PlayTune thechase1(1,MSPACMAN_ACTII_THE_CHASE1);
switch(tune) {
case 1:
while ( theymeet0.isPlaying() || theymeet1.isPlaying() ) {
theymeet0.playNote();
theymeet1.playNote();
_delay_ms(65);
}
break;
case 2:
while ( gamestart0.isPlaying() || gamestart1.isPlaying() ) {
gamestart0.playNote();
gamestart1.playNote();
_delay_ms(15);
}
break;
case 3:
while ( thechase0.isPlaying() || thechase1.isPlaying() ) {
thechase0.playNote();
thechase1.playNote();
_delay_ms(65);
}
break;
}
if (tune == 3) {
tune = 1;
} else {
tune++;
}
}
Filed under: Uncategorized | Leave a Comment
After playing around this week translating midi tracks into songs that the Arduino can play I thought that would it be interesting to see how cheap I could make a musical greeting card. These days you can pick up one at the store for about $5 that plays sampled music. If one or two part square wave tones are good enough it’s doable to make one for about the same price.
Other applications? Maybe a “musical throwy”, It’s almost cheap enough :)
Here is “You’ve got a friend in me” played on an attiny85 and two speakers converted from a midi version of the song:
Materials
- Attiny85 – Thru-hole, no frills AVR running at 8MHz $1.62
- Piezzo speaker(s) – I had some of these lying around $1.62/ea
- Battery holder - Plastic, thru-hole. $1.06
- Coin cell battery – You can probably find cheaper ones. $0.50
Total: $4.80 (cheaper than Hallmark)
(I’m going to use two speakers for mine bringing the cost up to $6.42)
Other misc materials
- Programmer for the attiny85 (you can use an Arduino if you have one)
- Soldering iron, solder, wires, etc
- Greeting card?
Construction
There are only 6 connections to solder, 5 if you tie black speaker wires together. I set all pins that are not being used to low to be used as ground connections. I would avoid connecting anything to the pin right beneath your +3V connection to avoid shorts.
Using a poor-man’s paper switch to complete the connection for the battery the tune only plays once and stops (the AVR is put into power-down mode after the song finishes). There is plenty more that could be done here including using more pins for LEDs, etc.
It would also be possible to mix the two outputs into one speaker with some resistors, this was easier though.
Creating the music
There are many places to find midi tracks, the challenge is finding one that will work for one or two parts. With Musescore you can merge multiple parts together if they don’t overlap. This example I’ll use “You’ve got a friend in me”, the Disney ToyStory theme-song.
First thing to do is to clean it up in musescore, copy the “zap chords” plugin into your Musescore plugin directory.

Loading the midi file in Musescore
After removing the chords, transposing it, increasing some note lengths in the second part and cleaning it up:
Looks pretty, right? Now it needs to converted into something that the Attiny85 AVR chip can read.
To do that we will use the xml2h.py script to create a header file for the PlayTune library.
Unlike running this for the Arduino in the last post we select a clock frequency of 8MHz.
Selecting Prescaler Values
Prescaler values of 2,4,16,32,128,512 are ONLY valid for the attiny85 TIMER1
The attiny85 has two timers each with their own prescaler value. The prescaler value is an integer clock modifier that will divide the clockspeed (in our case 8MHz) so the timer runs slower. On one hand this allows us to play lower frequencies, on the other it does not give us as much resolution resulting in less precise frequencies for the tones. In general you want to select the lowest pre-scaler value that is shown in the list that the timer supports.
For the attiny85 TIMER0 supports 1,8,64,256,1024. TIMER1 supports 1,8,16,32,64,128,256,512,1024,2048,4096
For the arduino atmega chips you should only use prescale values of 1,8,64,256,1024.
Software
Here is the code that plays the song using the PlayTune library, you can see more details about it here.
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include "playtune.h"
#include "songs/gotafriend.h"
int main(void)
{
// set everything low that we aren't using
DDRB |= (1<<PB2) | (1<<PB4) | (1<<PB3) | (1<<PB5);
PORTB &= ~(1<<PB2) | ~(1<<PB4) | ~(1<<PB3) | ~(1<<PB5);
PlayTune p0(0,PART0);
PlayTune p1(1,PART1);
while ( p0.isPlaying() || p1.isPlaying() ) {
p0.playNote();
p1.playNote();
_delay_ms(70);
}
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
return(0);
}
After the song is finished the Attiny85 will be put to sleep in low-power mode.
Filed under: Uncategorized | 23 Comments
Arduino music from a midi file
Recently I wrote an Arduino / AVR lib and python script so that I could take three parts from a midi file and playing them simultaneously using the three Arduino timers.
There are already plenty of other ways to generating tones using an Arduino. You can play music from a midi input there is a library for playing PCM audio and similar projects for playing music using all three Arduino timers simultaneously. I’ve also played around with AVR sound generation before in previous posts.
Note: if you just want to use the pre-generated header files in the songs/ directory you can download the lib and hook up your Arduino to a speaker to play tunes..
What you need to get started
- Arduino (or an atmega328, atmega168)
- A speaker and some potentiometers to mix the inputs.
- A midi file you want to convert
- Python and the beautifulsoup library for parsing xml
- Sequencing software like the Musescore (free) that will also convert the midi file to musicxml
- “xml2h.py” which parses a musicxml file and generates a header file with notes and delays for the arduino
- PlayTune library that will play the song on the atmega for any tune for up to three tracks simultaneously.
The result..
How music is generated using an Arduino
On the Arduino and in general on the atmega168 and 328 there are 3 timers that operate independently of each other in hardware. The timers count up (starting at 0) to either 255 or 65535 and reset to zero. When these timers are put into “CTC” (clear on timer compare) a pin is toggled every time the counter matches a specific value called the “match value”. The speed of the timer depends on two things, one is the speed of the clock ( for the Arduino this is 16MHz ) and a clock prescaler. The “prescaler” is an integer that can be set that will slow down the timer by a factor of 1024, 256, 64, or 8. Once the timer is setup in CTC mode and a match value is specified there will be square wave generated on a pin at a frequency proportional to how frequently the timer hits the match value.
Here are the match values that correspond to different pre-scalers and their corresponding piano notes at 16MHz. (This is from a spreadsheet I made which comes in handy especially when dealing with different clock frequencies)
Let’s start making music..
Using the PlayTune library
Copy playtune.cpp and playtune.h to a “PlayTune” directory in the libraries folder of your Arduino install. Once it’s copied there you should see it in the “import library” list under “Sketch”.
To initialize PlayTune pass into the constructor what timer you want to use, what prescaler, a list of match values and a list of corresponding delays.
- “isPlaying()” lets us know if there are still notes left to play for the part. When it’s finished it will reset back to the beginning.
- “playNote()” will iterate over the note list, playing the tone that corresponds to the match value or a rest if zero.
By default the PlayTune lib will play a scale from middle C to tenor C if you just pass in the timer you want to use.
In this example we will play the scale on all three timers simultaneously.
(connect your speaker to pins 6,9 and 11)
#include
#include
void setup(void)
{
PlayTune p0(0);
PlayTune p1(1);
PlayTune p2(2);
while (p0.isPlaying() || p1.isPlaying() || p2.isPlaying() ) {
p0.playNote();
p1.playNote();
p2.playNote();
_delay_ms(500);
}
}
void loop(void)
{
}
Note that the _delay_ms(500) function requires the additional include of util/delay.h.
Do not use the Arduino “delay()” function! It will cause problems because it uses TIMER0 which is being used by the lib for generating the tone.
So that was fun (but boring).. Now on to creating some more interesting music…
Midi, musescore and xml2h.py
Musescore is a wonderful free sequencing tool. Using that you can open midi files, adjust them, and convert them to musicxml.
“xml2h.py” is a script I wrote that takes a musicxml file and generates an header file that tracks two arrays for up to 3 parts, one for note values and another for delays (rests are note values equal to zero)
The conversion from midi to arduino tones is a bit of a hack :/
xml2h.py will do its best to:
- pick the best prescaler
- ignore chords
- combine voices if it can
- handle tied notes
I’ll walk through a video game theme as an example (it works well since the songs are simple). There are a number of sites out there with video game midi files most of them look like they were designed in 1997. Below I’ll use the Super Mario Brothers theme. In this score there are 4 parts, we will convert the first three to play on the Arduino.
There are some limitations to keep in mind for the midi conversion:
- If notes span multiple clefs then you there will probably be too large a range for the resolution of the timer, not many (simple) songs have this problem though.
- When you convert you will need to select between 1-3 parts to be played simultaneously.
- Chords will be ignored by the xml2h.py script.
- If there are more than voice on a part the script will try to merge them together.
I wrote a plugin called “chord zapper” for musescore that will (attempt to) remove all the chords. Copy this to the musescore plugin folder, select all, run the plugin to get rid of all the chords if you want to get a better sense of how the song will sound when converted. Whether or not you remove chords the “xml2h.py” script will ignore them, taking the top note in the chord if there are any.
When you are satisfied save the midi file save it as a “MusicXML” file and run it through xml2h.py.
The script takes the xml plus the name of the header file you want to write out.
For example:
Pick the clock frequency. This defaults to 16MHz which is what you want for the Arduino
Pick the part you wish to process (part0 corresponds to the top clef in the midi file)
Pick the prescaler, the script will give you a subset of prescalers, you should select the lowest one that is supported. (see note on prescalers below)
If it finishes without error you will end up with a header file that contains some arrays and macros for passing them into the PlayTune constructor.
Here is what the resulting header looks like, the macros for PART1, PART2, PART3 are used in the sketch below:
#include
#include
#include
void setup(void)
{
PlayTune p0(0,PART0);
PlayTune p1(1,PART1);
PlayTune p2(2,PART2);
while (p0.isPlaying() || p1.isPlaying() || p2.isPlaying() ) {
p0.playNote();
p1.playNote();
p2.playNote();
_delay_ms(50);
}
}
void loop(void)
{
}
Assuming you are converting two parts and the first part will be using Timer0 and the second part Timer1 pick the lowest value from the two sets that show up in the prescaler selection.
The only difference between this sketch and the last one is the additional include for the “smb.h” header file, the addition of the PART# macros used in the PlayTune constructors and a smaller delay.
The value of the delay will determine the tempo of the song and corresponds to the delay between each tick in the MusicXML file or the shortest note. Usually this is either 1/32 or 1/64.
If you have questions about the lib or if you create more songs let me knowand I will add them to collection.
Selecting Prescalers
In general you want to select a low value for a prescaler to give you the highest resolution (to match the pitch of the song as close as possible).
The two timers on the attiny support different prescalers though so you need to be aware of what timer you are using (0 or 1) and what prescalers it supports.
Timer0 supports: 1024, 256, 64, 8
Timer1 supports: 1024,512,256,128,64,32,16,8
Filed under: Uncategorized | 10 Comments
Recent Entries
- Amazing Musical Giftbox
- Musical Ms. Pacman Candy Tin Hack
- Picked up on lifehacker/hackaday
- Custom musical greeting card for less than $5
- Arduino music from a midi file
- Building the AVR toolchain on Linux
- Django 1.3 / JQuery tutorial – Making a flashcard game (Part 4)
- Django 1.3 / JQuery tutorial – Making a flashcard game (Part 3)
- Django 1.3 / JQuery tutorial – Making a flashcard game (Part 2)
- Django 1.3 / JQuery tutorial – Making a flashcard game (Part 1)
- Arduino and BlinkM Music Visualizer
Categories
- Uncategorized (21)














