Play a note depending on input

Hi,

I’m a beginner to Arduino, so I’ve been trying hard to break apart and understand the tutorial code for making sound with the Arduino and a piezo speaker.

MY GOAL: When I press a certain key on the keyboard, it will light up a specific LED and play a specific note.

MY PROBLEM: I can’t seem to discern from the tutorial code what the actual command is to play a note. I tried cutting and pasting the essential elements from the tutorial into my LED code. But it doesn’t seem to work. I think my understanding of how a note is played and how to tell it WHAT note to play isn’t good enough. My code is turning on the lights correctly, but no sound is coming out. (the speaker is functioning well) My code is clearly wrong, but I need help on fixing it.

PLEASE HELP!

here’s my best attempt code:

// TONES ==========================================
// Start by defining the relationship between
// note, period, & frequency.
#define c 3830 // 261 Hz
#define d 3400 // 294 Hz
#define e 3038 // 329 Hz
#define f 2864 // 349 Hz
#define g 2550 // 392 Hz
#define a 2272 // 440 Hz
#define b 2028 // 493 Hz
#define C 1912 // 523 Hz
// Define a special note, ‘R’, to represent a rest
#define R 0

int outputPin1 = 13;
int outputPin2 = 12;
int outputPin3 = 11;
int val;
int speakerOut = 9;

void setup()
{
Serial.begin(9600);
pinMode(outputPin1, OUTPUT);
pinMode(outputPin2, OUTPUT);
pinMode(outputPin3, OUTPUT);
pinMode(speakerOut, OUTPUT);
}

// Loop variable to increase Rest length
int rest_count = 100; //<-BLETCHEROUS HACK; See NOTES

// Initialize core variables
int tone = 0;
int beat = 0;
long duration = 0;

// PLAY TONE ==============================================
// Pulse the speaker to play a tone for a particular duration
void playTone() {
long elapsed_time = 0;
if (tone > 0) { // if this isn’t a Rest beat, while the tone has
// played less long than ‘duration’, pulse speaker HIGH and LOW
while (elapsed_time < duration) {

digitalWrite(speakerOut,HIGH);
delayMicroseconds(tone / 2);

// DOWN
digitalWrite(speakerOut, LOW);
delayMicroseconds(tone / 2);

// Keep track of how long we pulsed
elapsed_time += (tone);
}
}
else { // Rest beat; loop times delay
for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count
delayMicroseconds(duration);
}
}
}

void loop()
{
if (Serial.available()) {
val = Serial.read();
if (val == ‘a’) {
digitalWrite(outputPin1, HIGH);
tone = a;
playTone();
delay(500);
digitalWrite(outputPin1, LOW);
}
if (val == ‘b’) {
digitalWrite(outputPin2, HIGH);
tone = b;
playTone();
delay(500);
digitalWrite(outputPin2, LOW);
}
if (val == ‘c’) {
digitalWrite(outputPin3, HIGH);
tone = c;
playTone();
delay(500);
digitalWrite(outputPin3, LOW);
}
}
}

the execution in the code above starts in the void loop() section: - the program waits for an "a", "b" or "c" to come in on the serial line. - if it gets an "a", for example, it sets the variable "tone" to value "a", which is actually the number 2272 from the define statements at the top. - next, the program tells the function "play tone()" to make the sound. You can probably see how this is done by looking at that code, and substituting 2272 for the word tone.

If you want to play a tone on your own from a command, just remove the serial code in void loop() and use this code instead:

 tone = XXXXX;          // where XXXXX is the frequency in numbers  
 playTone();              // this plays the tone at XXXX frequency.

D

Hi Daniel,

Thanks for replying.

I'm not sure though what changes you are suggesting to my code. Your explanation is definitely what I was intending on doing with my code. But it doesn't seem to work.

If I substitute the serial code for the code at the bottom of your reply, I assume it will play the tone I have preset. But it still won't allow me to ask for an input and then produce the appropriate tone associated with that input.

Do you know why something might be wrong with my code that isn't allowing it to make a sound? Any suggestions on how to debug?

OK I am going to give you the answer, but in exchange, why don't you take the time to write up your working code in the Playground? That is the way it works around here: get something, and then give back, just like P2P :)

In my first reply, I sort of misread what you wanted to do. Now I get it.

You are sending a tone value to the tone function, but no duration. Duration is always 0, so elapsed time will never be less than 0, and you'll never get a tone. Paste this in. You'll need different durations for each key, or you can just use to duration= 100000 at the beginning of the tone function. (seems to be 100 milliseconds).

D

 if (val == 'a') {
     digitalWrite(outputPin1, HIGH);
     tone = a;
     duration= 100000;
     playTone();
     delay(500);
     digitalWrite(outputPin1, LOW);
    }

THANKS Daniel!

I'll try it out and see if it works.

If it does, i'd be glad to post it up onto the playground!

thanks again for your speedy assistance.

-David

it works, I tried it.

D

Hi Daniel,

I'm having trouble figuring out how to upload my code to the playground.

hi

in the bottom right corner, click "request contributor access" and then set up an account.

Login and go to the sand box to set up your page. When you;re ready, copy the sandbox code and make a new page for it with a new name.

D