Sound Effects with an Arduino

One of the first robots I built did not look all that cool but you could definitely hear it coming!  I had programmed it to go through a routine of sound effect loops.  One for going forward, one for when it detected an obstacle close by (“uh oh”), and occasionally it would send out a cat call and beep out the Ariel theme from the Little Mermaid (My daughter’s favorite).

Click here for a sample recording of these sound effects

This robot has since been dismantled for parts in new projects, but I found the code the other day and wanted to share how I created the sound effects. By the way, an excellent source for speakers are those musical greeting cards. If you have one of those laying around, you can dismantle it and use the low profile 8 ohm speaker.

This method I used is a  programmatic switching of the speaker on/of or High/Low.  Also known as the “bit banging” method.  There are other methods for creating sound effect using the Atmega328’s timers.  If you don’t need to operate motors or servos or anything else that requires the use of a timer, you may prefer to use that method.

Creating a tone

This illustration shows how a tone is generated by switching from high to low (on to off) at the specified frequency.
This illustration shows how a tone is generated by switching from high to low (on to off) at the specified frequency.

Musical notes occur in nature as nice, smooth and rolling sine waves.  In this project, we will be trying to mimic this wave.  But instead of smooth sine waves, we will be producing sound with square waves.  Square waves produce a tone but it is more crisp, metallic, and well….robotic than a normal sine wave.  But, we are limited to this kind of sound wave for this project, anyway.

I found an excellent resource on musical note frequency.  I used the chart from this site to create some constant variables in the header file.  There are actually 100 of them but for the sake of keeping this tutorial small, I’m only showing a sample here.  You can download the full project code at the bottom of this post.

...
const float note_C0 = 16.35; //C0
const float note_Db0 = 17.32; //C#0/Db0
const float note_D0 = 18.35; //D0
const float note_Eb0 = 19.45; //D#0/Eb0
const float note_E0 = 20.6; //E0
const float note_F0 = 21.83; //F0
const float note_Gb0 = 23.12; //F#0/Gb0
...

These constants assign a frequency value to the note. note_Db0 is actually D flat from the 0 octave.

So let’s move on to the Arduino code and see how this note is generated.

This is the actual function that creates a square wave tone. We send this function the frequency duration in milliseconds.

void beep (int speakerPin, float noteFrequency, long noteDuration)
{
int x;
// Convert the frequency to microseconds
float microsecondsPerWave = 1000000/noteFrequency;
// Calculate how many milliseconds there are per HIGH/LOW cycles.
float millisecondsPerCycle = 1000/(microsecondsPerWave * 2);
// Multiply noteDuration * number or cycles per millisecond
float loopTime = noteDuration * millisecondsPerCycle;
// Play the note for the calculated loopTime.
for (x=0;x<loopTime;x++)
{
digitalWrite(speakerPin,HIGH);
delayMicroseconds(microsecondsPerWave);
digitalWrite(speakerPin,LOW);
delayMicroseconds(microsecondsPerWave);
}
}

Since many of the frequencies we want to obtain are more granular than a millisecond, we need to first convert the frequency to microseconds. We then calculate how many milliseconds there are between high/low cycles and multiply it times the duration we passed the function. Finally, we loop through this revised duration or loop Time and create the square wave at the desired frequency.

 Composing the Sound Effects – Musical Notes

Creating the sound effects took some experimentation and a piano app to figure out what tones I was looking for.  I then had to experiment with durations.  Here are a couple of functions that call the beep function:

void r2D2(){
beep(speakerPin, note_A7,100); //A
beep(speakerPin, note_G7,100); //G
beep(speakerPin, note_E7,100); //E
beep(speakerPin, note_C7,100); //C
beep(speakerPin, note_D7,100); //D
beep(speakerPin, note_B7,100); //B
beep(speakerPin, note_F7,100); //F
beep(speakerPin, note_C8,100); //C
beep(speakerPin, note_A7,100); //A
beep(speakerPin, note_G7,100); //G
beep(speakerPin, note_E7,100); //E
beep(speakerPin, note_C7,100); //C
beep(speakerPin, note_D7,100); //D
beep(speakerPin, note_B7,100); //B
beep(speakerPin, note_F7,100); //F
beep(speakerPin, note_C8,100); //C
}


void closeEncounters() {
beep(speakerPin, note_Bb5,300); //B b
delay(50);
beep(speakerPin, note_C6,300); //C
delay(50);
beep(speakerPin, note_Ab5,300); //A b
delay(50);
beep(speakerPin, note_Ab4,300); //A b
delay(50);
beep(speakerPin, note_Eb5,500); //E b
delay(500);
beep(speakerPin, note_Bb4,300); //B b
delay(100);
beep(speakerPin, note_C5,300); //C
delay(100);
beep(speakerPin, note_Ab4,300); //A b
delay(100);
beep(speakerPin, note_Ab3,300); //A b
delay(100);
beep(speakerPin, note_Eb4,500); //E b
delay(500);
beep(speakerPin, note_Bb3,300); //B b
delay(200);
beep(speakerPin, note_C4,300); //C
delay(200);
beep(speakerPin, note_Ab3,300); //A b
delay(500);
beep(speakerPin, note_Ab2,300); //A b
delay(550);
beep(speakerPin, note_Eb3,500); //E b
}

As you can see, these can be pretty verbose since we are essentially writing out each note.

Composing Sound Effects – Programmatic Method

There are more programmatic methods of obtaining these sound effects using loops and these are actually quite neat to hear!

In these functions, we are setting the frequency min and max and then using ratios (1.01, 0.99, etc) to change the pitch of the tone as it loops up or down the range.

void ohhh() {
for (int i=1000; i<2000; i=i*1.02) { beep(speakerPin,i,10); } for (int i=2000; i>1000; i=i*.98) {
beep(speakerPin,i,10);
}
}


void uhoh() {
for (int i=1000; i<1244; i=i*1.01) { beep(speakerPin,i,30); } delay(200); for (int i=1244; i>1108; i=i*.99) {
beep(speakerPin,i,30);
}
}

With the programmatic method, the sky is the limit for what kind of effects you can create. One idea is to create a completely random routine that will beep and squeak and whine and never get old!

That does it for now. Feel free to add comments or questions. And don’t forget to download the project files with some sample sound effect routines!

7 Comments


  1. Thanks for this very interesting read. I’m currently playing around with an Arduino and speaker setup but I find trying to get the melody I want both a fun & challenging experience.

    It would be most useful if there are any freeware utilities that can analyse music and then convert it to the pitches and durations used by the Arduino. Do you know if any such software exists?

    Thanks

    Reply


  2. Thanks for the great info. I see mention of downloading the source files, but can’t find a link anywhere on this page. I am particularly interested in the R2D2 sound effects. Thanks!

    Reply

  3. Hello! Thanks for the sound sketch! You did an AWESOME job with this. One question: Do you have the sketch where you put this into the movement of your robot? I’d like to add this to my sketch for my obstacle avoidance robot (and I’m still learning Arduino programming).

    Thanks again!

    Mike

    Reply

    1. Mike,

      Sorry for the late reply! I didn’t see your comment until today. I have added that sketch to the download section here…https://www.mycontraption.com/download/arduino-robot-using-sound-effects/

      But essentially, if the robot detects an object that is too close (Left sensor and right sensor), it stops and the “Bonk” sound effect is emitted:

      if(sleft <= 20 && sright <= 20) { // Stop Motors hard_stop(); delay(1000); bonk(); // This is the sound effect drive_backward(); delay(500); }

      Reply


Leave a Reply

Your email address will not be published. Required fields are marked *