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

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

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:

After running chord-zap and some transposing

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.



26 Responses to “Custom musical greeting card for less than $5”

  1. hey, great DIY!
    Could I put this up on my own blog? I won’t forget to credit you and limk back to this post!

  2. 3 Piotr

    Great! Will be an awesome and original gift for christmas.

  3. 4 Sam

    Sweet project! Any thoughts on how to rig it for repeated plays? I was thinking of putting one in a mailbox …

    • 5 jarv

      You can put a loop around it and play a song (or multiple songs) for how ever long you want battery permitting.

    • 6 beardy

      How about having it light triggered? When the box is opened it begins to sing!

  4. 7 dilbert

    Can this be used with anything other than a midi file, such as a .wav or .mp3? If not do you have any suggestions?

  5. This is a great DIY.

    I would like to make a similar project in the future. Can i use your project as a basis of mine? I will credit you and “link back” for sure :)

  6. 10 G_A

    What kind of chip could you use instead to play back a voice greeting or vocals? Are there any in a price AND size range that would be a god candidate?

  7. This is a very nice project – can we have this with just a single ceramic transducer.

    Posted it in my blog here(http://labratsgonewild.com/)

  8. I love this but is there a way to perform the same thing with the ability to record audio from any source. I am planning a “furry wall” for my daughter and wanted to put touch sensitive plates on it that will play various quotes from “Get Him to the Greek”. I have found no source for any inexpensive component that is relatively flat that stores the audio.

    • 13 jarv

      Unfortunately no way with this microprocessor though there are other devices that can record if you search for “custom greeting card” on google, might be more expensive though :/

  9. 14 Ram

    Nice project! Can we have it play multiple tunes, in sequencial or random order?

  10. 15 John

    I’m having some trouble figuring out how to use your Python script – I’ve got both the *.mxl file I want and your xml2h.py script, but I’m not sure what to do with them from there…

    • 16 jarv

      if you mail me your musicxml file (john@jarv.org) I can take a look.

  11. 17 Cameron

    I’m getting some pretty strange results with this. I’ve got a mxl file, pretty simple actually, only 1 track, use the python script to convert it fine, but when playing back all i get is really low sounding noise from the speaker. The only way to get it playing back in a way that resembles the original song is to go to 1MHz in the script, even then I’m getting weird things happening towards the end of the song, it’s dropping a lot of notes for no apparent reason (no higher/lower than other notes in the song). Bizzaro land…..

    • 18 jarv

      If you email me the musicxml and header file that you generated I can take a look (john@jarv.org)

  12. 19 kovianyo

    Makefile.atmega
    contains “MCU=atmega328p”. shouldn’t it be “MCU=atmega168″?

  13. 20 Shoo

    Could you make “xml2h.py” Windows exe Ver ?

  14. I’ve been messing with this thing for 8 hours and can’t get it to work… I used python 2.7 which looked like it worked till I plugged the arduino up and nothing came out, then I tried python 3 which wouldn’t work at all. :/ it just gives me errors :(

    File “C:UsersTheif DarkDesktopNew folder (2)xml2h.py”, line 10
    print “Usage: ” + sys.argv[0] + ” “

    • the pre complied songs work, I just can’t make any myself.

    • 23 jarv

      Hm, it’s possible wordpress isn’t giving me the full text of the error, can you mail me (john@jarv.org) what you are seeing?

  15. 24 Ryan

    This is great! Although I have no programing skills what so ever.
    Is there a way I could get any more detailed information on the actual setting up of the arduino and programming it. I’m ready to purchase everything I need.

    Thanks again!


  1. 1 Arduino based musical greeting card | Arduino Passion
  2. 2 Arduino based musical greeting card -- Arduino Passion