buzzer melody repeating over and over

This is my first time using this forum, so bear with me if I've made a mistake somewhere. I'm very new to Arduino and still trying to learn how it works.

Okay, so I'm working on a small project for a class, where I have a Zelda-style treasure chest. I want to hook up this Arduino Protosnap Mini to it. I'm going to put the LED on the lock of the chest, a light sensor on the inside of the chest, and the board on the back.

What I want it to do is detect when the chest is opened (using the light sensor), changing the LED from red (chest closed) to green (chest open) and playing the "da da da DAAAAA" from the Zelda games on the buzzer.

I've got most of the code working. It does detect light, and when it does, the LED changes from red to green and plays the tune. My problem is that it keeps playing the tune over and over, and I can't figure out how to get it to stop. I think the problem may be that the buzzer tone function is in void loop, but I'm not sure where else to put it. If someone could help me get this thing working I would really appreciate it.

Here's my code:

int buzzer = 2;
int light = A0;
int red = 3;
int blue = 6;
int green = 5;
int numTones = 10;
int tones[] = {260, 260, 300, 300, 340, 340, 390, 390, 390, 390};

void setup(){    
  pinMode(buzzer, OUTPUT);  
  pinMode(red, OUTPUT);  
  pinMode(green, OUTPUT);  
  pinMode(blue, OUTPUT);
}


void loop(){
  int temp = analogRead(light);
  if(temp > 100){
    digitalWrite(red, HIGH);
    digitalWrite(green, LOW);
    digitalWrite(blue, HIGH);
    for (int i = 0; i < numTones; i++){
      tone(buzzer, tones[i]);
      delay(150);
    }
    noTone(buzzer);
}
else {
  digitalWrite(red, LOW);
  digitalWrite(green, HIGH);
  digitalWrite(blue, HIGH);
}
}

The trick is to remember that you have played the tune. When you first play the tune set a variable to indicate so. (e.g. played = true). Before you play the tune check the variable value to see if you need to play. When the box closes, forget that you played the tune (e.g. played = false).

That makes sense. So would the code be something like...

if(buzzer = LOW){
    for (int i = 0; i < numTones; i++){
      tone(buzzer, tones[i]);
      delay(150);
    }
    noTone(buzzer);

or is the syntax wrong? Sorry for asking details, I'm not very familiar with the Arduino language. My knowledge is very limited.

if(buzzer = LOW){

is not what you want. buzzer holds the pin number that your buzzer is attached to. And buzzer = LOW will set it to LOW, if you wanted to test if buzzer were equal to LOW (and you don't) you would use buzzer == LOW.

Try something like this...

if (!tunePlayed) {
  tunePlayed = true;
// do whatever to play a tune
}

Declare tunePlayed as byte at the top of your sketch with your other variables. And set it to false in the setup() and when you detect the box is closed. Note that the '!' above is the logical negation operator so the meaning of the if statement is "if tune not played".

Okay, I got the code in, and everything is ALMOST working how I want it to. The last problem is that when it detects light, it plays the tune- again and again. How do I get it to play once, then wait to detect light again?

void loop() {
  int temp = analogRead(light);
  if(temp > 100){
    digitalWrite(red, HIGH);
    digitalWrite(green, LOW);
    digitalWrite(blue, HIGH);
    if(!tunePlayed){
      for (int i = 0; i < numTones; i++) {
        tone(buzzer, tones[i]);
        delay(150);
        int tunePlayed = true;
      }
    noTone(buzzer);
    }
}
else {
  int tunePlayed = false;
  digitalWrite(red, LOW);
  digitalWrite(green, HIGH);
  digitalWrite(blue, HIGH);
}
}

That should be..

tunePlayed = true;

not

int tunePlayed = true;

Same for setting it to false. When put an int in front of it, that creates a new variable with a scope that is local to the block where it appears.

Fixed! Okay now what's happening is it's playing the tune when it detects OR doesn't detect light. For example, when I upload the sketch, the Pro Mini is sitting on the table, in the light, so it plays the tune, with the LED being green. Then, when I put my hand over the light sensor, it plays the tune again, then the LED turns red.

How can I prevent it from playing the tune when it detects no light?

Sounds like you might need some hysteresis on your input. Choose two different sensor readings that you feel adequately represent light and dark. Consider the box open when the reading is at or above the light level and closed when at or below the dark level. For example if temp > 200 then the box is open and if temp < 20 then the box is closed.

Also, tunePlayed should be a boolean, not in int.

Thanks for the help, both of you! It's mostly working, just a few kinks to figure out.