Tone Generator Song Player
[EDIT 3]: I cleaned up the code big time (Arduino code in step 6). And I added two songs: This land is my land by Woody Guthrie and Für Elise by Beethoven. See the last step for the videos.
[EDIT 2]: uploaded a better version of The Wilhelmus. I calibrated the machine to the Hz with a calibration sketch. And I discovered a mistake in my notation of the song. I missed an F#. Now it is way better. The enhanced code is also uploaded.
[EDIT 1]: I attached a Processing file in the Music Step (6) for testing out the tunes.
I am a physics teacher for more than 20 years in The Netherlands. I love my job and I love physics. My students, as you can imagine, need a bit of encouragement to become as enthusiastic as I am for the sciences, so I try to come up with all kinds of activities to get them aboard.
When I introduce the subject "Sound" I often use a tone generator (or signal generator). With this machine you can make pure tone sine waves (and triangle and square) of all frequencies. I show them the waveforms on an oscilloscope. To make it more fun I always end this lesson by trying to play a song on this machine. I usually try to play our national anthem, "The Wilhelmus" because I like the discrepancy between the solemn son and the somewhat strange instrument. That is quite difficult: you have to listen very carefully and the moves are very subtle sometimes.
A colleague of mine always asks their students what they want to hear at their graduation ceremony. One of them answered: "Het Wilhelmus op de oscilloscoop". "The Wilhelmus on the oscilloscope". He meant on the tone generator. I performed that o a youtube movie (see above) and it was shown at the graduation ceremony.
We were discussing this in a coffee break and one of my friends, colleague Marten said: "Can't you make a machine that plays that song?" I really loved that idea and it stayed in my head until it was summer break. The first three days of that break I worked hard at our school maker space and I succeeded. A working robot that plays different songs only by turning the frequency knob.
I am very fond of my invention and I hope you like it too. If you think this is worth it, you might consider a vote. Have fun reading it and if you make it too, I would really love to see and hear how it worked out!
Arjan van der Meij
twitter: @arjanvandermeij
e-mail: arjan (at) makered.nl
Materials and Tools
Materials
- Tone generator (signal generator). Mine is a Frederiksen Function Generator. Not for sale anymore. But any analogue signal generator with a turning knob will do.
- An Arduino. I prototyped on a regular Arduino Mega (happened to have one) but the one that I ended up using was an Arduino Nano (from China).
- Servo. It will work with all kinds of servos but I used a Hitec HS-475HB that I found in a drawer here. You can't buy this one anymore but you can buy the 485.
- Filament for the 3D printer. We use PET.
- Wood for the box
- A switch to power the system.
- A rotary switch with 6 positions to choose the song.
- A switch for launching the song.
- A power adapter (5V)
- Scrap wood
- Small magnets
- Wires
- Glue
Tools
- 3D-printer. I used a LeapFrog Creatr HS. Not necessary though. I used it especially because I wanted to learn TinkerCad
- Laser Cutter. We love our Trotec 100R. Without it, you can make it anyway.
- A caliper. I never measured more than in this project.
- Soldering iron
- Pliers, scissors, knifes, screwdrivers, etc.
Designing the Adaptor
The idea was quite simple. A servo motor is able to turn about 180° and is strong enough to turn the knob of the tone generator. The first problem you have to encounter is to make an adaptor that fits the servo motor on one side and fits the knob of the tone generator on the other side.
- You can make use of datasheets or, if you like to measure things, like I do, you can do all the measurements by yourself. All you need is a calliper. I do own a digital one but the analogue I used at the maker space at my school suited me just fine. If you have a plate on the servo with mounting holes, you can make use of them. That's what I did.
- Just make a lot of cylinders, positive and negative and make the design. Make use of the align tools and the ruler because you can easily lose control of the postion of the elements of your design. It makes sense to make regular backups by duplicating your design and work in the next version.
- When you finish the design of the servo side adapter, make prototypes. There are all kinds of reasons why a design won't work (a 3D print is slightly larger than your design for example. A trick I learned from a friends to make your whole design but only print a small pice of it by making a large block and make that a hole in Tinkercad. With that you can cut off the piece you don't want to print. You will save lots of time this way.
- When you have made a snuggly fit adaptor for the servo side, it';s time for the knob side. Of course, all knobs are different but the method I used is fitting for more knobs. First try to replicate the knob as accurate as you can. Use the calliper often! If the knob has a conic form, you can choose to make the knob a little bit longer (keeping the proportions.). That will come handy later
- When you have finished designing the positive knob, copy that and take it to your servo adapter. Make the knob negative (a hole) and put it on the other side of the servo adapter. Try to make a wise decision about the angle it makes (I had to 3D print a new one because I didn't) and print it out.
- Being a geek I was thrilled that I need some maths to make the knob. The knob was not straight up but had a slope, so trigonometry was needed.
- The knob also had notches that had the form of a part of a circle. And the easiest way to make those notches was to make a cylinder with the right dimensions. You can see my calculations in the picture (Dutch but I think you get it).
You can download the STL of my adaptor above and if you want to tinker with it, check the design here in Tinkercad: https://tinkercad.com/things/2wxYreDDtmj
Downloads
Calculating Notes, Angles and More
The thing with a tone generator is that every angle the knob turns, it sends out a different frequency . So you have to measure what the frequency/angle ratio is, that is: how many Hz does the generator change when you turn the knob 1 degree. For me it turned out to be 4 Hz/°. In the Arduino Servo library you can make use of the writeMicroseconds command and that will move the servo in steps of tenths of a degree. The table with the calculations you can see above.
Test the ranges of your servo. Mine went from 550 Microseconds to 2080 Microseconds (and turned 153° obviously). Check if you have to turn your tone generator clockwise or anti clockwise and calculate accordingly. Make accurate notes of all your findings.
The Electronics
I recommend you first use a regular Arduino like the Uno or the Mega and a breadboard and use that to prototype. And of course you put all this together and when you think everything is OK, you power it.
- First solder wires tot the rotary switch. Best is to use flexible wires. Later on you want to fit them in a tiny space and then this come in handy. It is handy to solder the ends of breadboard wires to your wires to make it easy to put them in a breadboard. Alternatively you could use some clip wires and breadboard wires.
- Hook up the wires to the two switches.
- Connect the wires to the Arduino ports (see the illustration above).
- The data wire (yellow) of the servo to port 9
- The power wire (red) of the servo to Vin
- The ground wire (black) to GND
- Connect one of the wires of the launch switch to port 8 and the other to GND (doesn't matter which GND)
- Connect the six wires of the rotary switch to ports 2, 3, 4, 5, 6, 7 of the Arduino and connect the ground wire to GND
- The power line goes into Vin and GND. Check the polarity!
Pay attention: if you want the power cable to enter the box nicely, you have to do that first, before you attach and solder everything. It will nog fit a small hole when you have to put it in later. See step 6!
The Arduino Code
Now it's time to get the thing working!
The code I used and you are free to use is included here (TGMI.ino). The only library I used is the standard servo library that is included in all Arduino distributions. I tried to comment everything that is important in the code. There are a few things that require some more explaining:
- The music is hard coded. See next page.
- I wanted all the notes to start the moment they were supposed to start. That seems obvious but this instrument is different than for example a piano or a guitar. Maybe the best comparison is that with a steel guitar. It takes time to reach the next note. So in the code you should take that into account. Find the speed of the servo motor in a data sheet and find the place in the code where the delay is.
int rest = duration*notetime-abs((notes[note+1]-notes[note])/1530)*turntime-extra; <p>delay(rest);</p>
You see here the calculation of the delay time (rest). The duration is the time the note has to be played; notes[note+1]-notes[note] is the angle change (in Microseconds) between this note and the next. That amount is divided by the maximum angle (1530 Microseconds) to get the fraction of a full swing and that is multiplied by the time for a full swing. This is then subtracted from the duration to have the knob start at the right time. The "extra" term is explained in the next step.
- There is a complication when you use the tone generator as a musical instrument. When the next note is the same as the former, you can't distinguish between them. You hear one, long note. If you use a normal instrument, even when you play the steel guitar, you have a small pause. But I had decided that I only wanted to make a robot for the frequency knob (maybe I will, one day, make a volume robot alongside). So I had to make up a work around. I decide to introduce a hick-up. In between two notes, the knob is turned a few degrees up. I experimented with this and I am not really satisfied by it. I intend to experiment a little more. You can do the same or maybe you can make the volume robot!
- I tried to make the code as tidy as possible. No unnecessary code and everything is commented. If you see a way to improve the code, please do.
When everything looks fine, try it out! Do this without a load, let the knob turn in the air. If it works fine, you could already hear the song a bit in the rhythm. If you are confident it works, try it with the adaptor on the knob. You will hear the song for the first time. For me, that was a magical moment (see the attached movie, the box is already made but not glued yet).
[EDIT 1] I uploaded a new version of the code. I cleaned it up, I improved the music of The Wilhelmus and added "This land is your land"
[EDIT 2] Another version. I think I will nog get it any smaller. Every line has its comment and For Elise is added ("Poesie Mauw" was discarded).
Downloads
The Music
Obviously the music that this instrument can play must be very simple. A chord is only possible when you make more than two of these machines. So you can only play simple tunes. I did a search if there was a standard notation system for this. I looked into MIDI, Lilypond and the Curwen notation. These were all great but far too complicated for what I wanted to achieve. So I designed a notation myself.
If you want to use my code and put another song in (or put a song in place 6, which I haven't had time to fill), then you have to use this notation. It is quite easy. I use a two dimensional array. The first element is the note. It has to be an integer so I have made a translation table for the notes which you can see above. I also made a scale with the right numbers in a picture.
When you make a song, say "Twinkle, twinkle, little star", you put it down like this:
int twinkle[][2] {<br>{5,4},{5,4},{12,4},{12,4},{14,4},{14,4},{12,8},.. }
The first entry {5,4} means: note 5 (that is a G) and it lasts 4 (times 100 ms in the code but you can change that). The second note is the same, the third note is {12,4}. That is a (higher) C that also lasts 4. The last note ("staaaaar") is {12,8}. That is a C again but now it lasts 2 times longer than the predecessors. It takes some time to translate sheet music into this notation but it is worth the while.
A plus point is, that it is very easy to transpose your music. Say you want to transpose it 1,5 note lower, you just subtract 3 from the number of the note.
int note=twinkle[i][0]<strong>-3</strong>;
Here you have to pay attention that you are not able to get lower than your lowest note or higher than your highest.
EDIT
I made a Processing program in which you can put the notes you use. If you play the code, you will hear the song. I did this because I wasn't satisfied with the way my machine played The Wilhelmus. Turned out I missed a F# and put an F there. If you want to test your music, put the music code on the place of the "wilhelmus" and it will play. You need the Sound library. You can import that from the menu in Processing (Import Library..).
Downloads
Designing, Cutting and Glueing the Box
The servo motor has to be held in place. The best thing I could think of was a wooden box. I am a lucky guy: we have a laser cutter at our disposal. But I am sure it will be possible to make a box like this without this great machine.
- Design a wooden box. You can use Boxmaker and put in all the dimensions. A box of 10x10x5 cm can hold all the components . Maybe it's better to make a slightly larger one. It is kind of crowded inside the box. You can find the designs I made in the files (box.ai, box.pdf and box.svg).
- The vertical placement of the servo motor is very important. Measure this carefully and make some prototypes to be absolutely sure. It has to be firmly on the ground, otherwise it will work inaccurately.
- Let the laser cuter do its work. Carefully choose the right values for your laser cutter that matches your material. I always do a check cut to see if it goes through.
- If you use different switches than I did, you have to change the design for the top.
- Before you glue the box, put the power cord through the back panel. See step 4 for the warning.
- Use wood glue if you want to do it as it should or use super glue if you are as impatient as I am.
- Put the (small) Arduino and the wire in. Be careful not to mess up your wiring. If you solder everything, that is not a problem anymore.
Of course you wanted to be able to get in the inside of the box, so you have to make an accessible back door.
- Take some scrap wood and glue a magnet on top of four small beams (8x8x30mm).
- Glue those beams in the four corners on the backside.
- Glue some small irons rings to the backside opposite the magnets.
- Put the backside in. See the drawing for more explanation.
- To secure the power chord, you can use some hot glue or sugru.
Playing the Songs
Now it's time to make some music!
- First hook up the tone generator and put it on. Choose the frequency interval wisely. If you choose a higher interval (most of the time 10 times higher) the songs wil be awful.
- Power up the Tone Generator Musical Machine (TGMI). Do not attach it to the tone generator at this point. The TGMI will go to the starting position.
- The starting position is the lowest note. In my case that is the G at 196 Hz. Try to get as close as possible to that frequency.
- Now it is time to slide the TGMI with the adaptor in it's place.
- Choose a song by turning the rotary switch in one of the five first positions In my code:
- 1: Wilhelmus (our national anthem)
- 2: Vader Jacob (Frère Jacques}
- 3: Lang zal hij leven )(Birthday Song)
- 4: Ode an die Freude (Ode to joy, Beethoven)
- 5: Für Elise (Beethoven)
- 6: This land is your land (Woody Guthry)
- Start the song by using the launch switch. It starts to play immediately.
Have fun!
Arjan van der Meij