This is the second in a series of articles about generating sound with an Arduino. The first article covered the various methods available for sound generation with an Arduino. In this article we take a small step; “Hello World” for Arduino sound. We prepare for our future experiments by hooking up a PC or powered speaker so we can hear the Arduino sing.
Driving a speaker.
To get started we need to drive a speaker. We could use a headset but to share sounds with others we need a speaker. Rather then build an audio power amplifier we can use our desktop PCs line input or a set of powered PC speakers.
Using a PC for sound output
The ideal setup would be to use a line input on your PC. The PC will do the work of amplifying the sound and driving the speakers. This has the added benefit of making it easy to record or use a program that lets you view the audio signals in real-time.
Most PCs today have a sound card with speaker outputs, microphone input, and a line input. Look at your sound connections, the connectors are usually color coded. Blue for line input, green for speaker out, and pink for microphone. You should find all three next to each other on the rear of your PC.
I recommend that you use the line input for these experiments. The microphone input might be OK but may require some careful circuitry and would be very sensitive to the voltage levels. The microphone input is designed for low level signals and provides amplification. The Line input is best for this project as it is designed for connection to an external device like an MP3 player. Please don’t use the microphone input unless you know what your doing and/or don’t mind breaking it.
Using Powered Speakers
A set of powered PC speakers would do the job as well. They have built in amplifiers to drive internal speakers and should work fine with line level signals. You will be all set for public demonstrations as you will have the sound output already taken care of. It might even be possible to build your project inside the speaker box. I bet there is lots of room inside the typical PC speaker box.
External speaker Amplifier
The big guns… Use your home stereo to really pump out the sound or build a custom speaker amp kit. This would be a good way to get enough power for a large presentation or event. Maybe you just want a powerful sound to scare the pants off someone next Halloween.
For just about any project with sound output we can plan for connection to a line input jack. I think its safe to assume that any line input would be AC coupled and would accept signals at 1 Volt Peak to Peak.
AC coupling means that the input has a series capacitor which blocks DC levels. Any DC voltage on the line input will decay to 0V. This input capacitor will distort the sound slightly depending on it’s value. You need a large value to pass low frequencies without loosing signal levels.
1 Volt Peak to Peak (1VPP)?
This means that the signal waveforms we output need to max out at 1 Volt from top to bottom. The average value is not important here as the AC coupling will set the average to 0 Volts effectively. So if we are generating a signal that is output from a 5VDC source, we need to make sure that the difference between the lowest voltage and the highest voltage is no more then 1 Volt. I like to bias single supply analog signals to 1/2 the supply voltage. Since the supply is typically 5V the middle voltage is 2.5V. To meet the 1VPP requirement we keep the output between 3V and 2V or a swing of +/- 0.5 around 2.5V. This is bound to be confusing right now. When we get to looking at waveforms it will make more since.
The line input on your sound card or powered speaker is probably a 1/8″ stereo jack. The neatest way to get hooked up would be to salvage one of these jacks from some gadget you don’t need anymore. I managed to scrounge up several jacks that work great with solderless breadboards. I use a long audio extension cable to run from the breadboard to the line input on my PC.
Another way is to find an old audio cable or purchase one at Radio Shack. Maybe you have an old Headset you can cut up. Wikipedia has an article showing the various types of stereo audio jacks and includes the pin outs. These jacks have three rings, the tip is left audio, the middle ring is right audio and the last ring is ground.
We will be using a Bit-Bang output from an I/O pin which switches from 0 to 5V so we need to attenuate it to about 1VPP. I recommend a simple voltage divider
as shown here. Just place the two resistors on your breadboard or build them into your cable. Leave room for two if you want to do stereo.
You probably don’t need a volume control as most things you would connect to already have one. To add volume control replace the 1K resistor with a potentiometer (POT). You might even find a dual pot to control the left and right channels at the same time. Add a volume POT by replacing the 1K resistor with a 1K pot as shown here.
“Hello World” in Sound
A “Hello World” program is software lingo for the simplest program we can do as a meaningful test. Just what we need to test out our development environment. In this case we need to hear some sound to see that everything is ready for our experiments.
“Hello World” in sound would be a simple Bit-Bang tone output from your microcontroller. As described in the previous article we just toggle an I/O pin on the Arduino. With this simple program we can test the connection to our speakers.
Here a version of “Hello World” for Arduino sound. It is a bit more advanced then it has to be. Usually a “Hello World” program should be the bare minimum but I could not resist a few good programming practices. Look over the code and read my description before you use it.
//Arduino Sound Hello World
//Created by David Fowler of uCHobby.com
//Define the I/O pin we will use for our sound output
#define SOUNDOUT_PIN 9
//Set the sound out pin to output mode
//Generate sound by toggling the I/O pin High and Low
//Generate a 1KHz tone. set the pin high for 500uS then
low for 500uS to make the period 1ms or 1KHz.
//Set the pin high and delay for 1/2 a cycle of 1KHz, 500uS.
//Set the pin low and delay for 1/2 a cycle of 1KHz, 500uS.
Starting with the “void setup(void)” function. This function is run once when the microcontroller starts and is where we set the sound pin to operate in the output mode. I use the “SOUNDOUT_PIN” name which is defined a few lines above. I could have just put “9” for digital pin 9 but using the define this way lets you change it to a different pin without having to hunt down every place the pin is used in the program. We can change the 9 to a 10 in the define and every place “SOUNDOUT_PIN” is used, changes automatically.
Next is the void loop(void) function. This function will toggle the I/O pin at 1Khz, a frequency that should be easy for anyone to hear. The Arduino system code will call Loop just after it calls setup (described above) then keep calling it every time it returns. All we need to do is generate one complete cycle in the loop function.
Changing the Frequency
The code above should generate a 1KHz tone. The frequency is caused by the toggling I/O pin. We get a 1Khz tone because there are 1000 cycles of the I/O pin per second. A cycle is one set of 0 state followed by the 1 state. This 0 to 1 back to 0 state happens 1000 times a second so we get a 1KHz tone.
To change the frequency we need to use different delay times. A longer delay would decrease the frequency because it would take longer to make a single cycle. The opposite is true for increasing the frequency. To generate 2Khz, twice 1Khz, we would half the times for both the high and low delays.
To calculate a new delay time for a given frequency, divide 1 by the frequency. This is also called taking the reciprocal. t=1/f where t is the cycle time and f is the frequency. We need to spread this total delay between the two delays, the high delay and the low delay. Just divide t by 2 to get the time we want the pin to stay high then low. This generates a square wave with a cycle time equal to t. In this case t=1mS so we need to set the pin high for 500uS (micro seconds) then low for the same. For a 2Khz tone, use 250uS for each of the delays.
Copy and paste this code or use the project file here. Once everything is connected and ready, load your Arduino and prepare to hear a tone.
This could be very loud so start with the volume turned way down. Remember to keep it down between experiments. You could hurt yourself if unexpectedly blasted with a 1KHz tone…
The sound is not very pure as your really generating an on/off or square wave type output. You can filter this with an RC (resistor capacitor) circuit but that will significantly attenuate the signal as you vary the frequency.
If you do not hear the sound, then check your wiring and the settings on your sound output system. Try using a volt meter on the output pin, it should read about 1/2 the supply voltage or about 2.5V. Mine read about 2.3V on the AC or DC scale. You could also connect an LED via a series resistor to the output pin. It should light dimmer then if the pin were at a constant state.
Here is a sample of the sound my Arduino made with a slightly modified version of the “Hello World” program above. I changed the code to generate 1000 cycles then delay for 1 second. The result is a beep beep beep forever. Try loading this sound sample into a sound editing program to see the waveform. The picture below shows the sound waveform in Audacity. Audacity is a great sound editor and also works well for recording and cutting samples from MP3 files. I highly recommend it for sound experiments. If you know of another program that should be considered please share it in the comments.
You can also try filtering the square wave a bit to get a different sound quality. Try placing a small capacitor such as a 0.1uF or 0.01uF across the resistor to ground. Also play with the code delays to generate other tones. Maybe you want to generate a simple sequence of tones to make some music.
Try to do the following on your own. These exercises will prepare you for the next steps. If you have trouble try posting a comment asking for help.
- Change the frequency of the tone
- Make your version do the beep beep as I did above
- Create a function to generate the tones
I recommend that you create a function that takes the desired frequency or cycle time, the duration to play the sound for, and possibly the pin to drive. If you want to get the function done fast, use Paul Badger’s “freqout” function.
- Install a sound editing program and take a look at some recorded sounds from your project.
- Use an oscilloscope to see the signals while you play with the frequency or filter capacitors.
One great way to learn is to look at the signals. If you don’t have an oscilloscope on your bench there are programs that work with the sound card input on your PC. I have tried a few programs and would welcome any suggestions. The one I like so far is Soundcard Oscilloscope by Christian Zeitnitz. Someone should do an article about these programs; hint.
Parts 2, 3, …
The next article will work on creating nice sin wave outputs. I have played around with a few options and have settled on an R2R network. I also reconfigured a timer to generate regular timed interrupts for an accurate sample update for the R2R DAC. I expect to cover this in detail with future articles. I may break the timer interrupt and R2R DAC up into their own articles. I want to keep these short and too the point.
I would like to hear your thoughts on this article and sound generation in general. If you do something interesting or create a music sequence please tell us in the comments. Have any of you used software that turns the sound card input into an O-Scope? Another sound editor program perhaps? What do you recommend?