Magnetic switch loop

there is a magnetic switch on a box to sense the voltage. When the box is open, the magnet move apart, and sound will be played. When it close, the music stop. The box will play sound when it open again. However, I just want to play the sound one time but I find that the follow code unable to stop the music, and it turn out that the music play again and again until i close the box. I therefore havev no choice but put a delay(10000) at the end. Can anyone give me some ideas to solve the problem...thx a lot!

int button = 2;
int theboxstatus = 0;

void setup(){....
}

void loop(){

digitalClockDisplay();
Alarm.delay(1000); // wait one second between clock display
if(digitalRead(button) == LOW){
if(theboxstatus==0){

{digitalWrite(SLAVESELECT,LOW);
spi_transfer(SET_PLAY); // clear interupt and eom bit
SPI.transfer(0x00);
SPI.transfer(30);
SPI.transfer(0x00);
SPI.transfer(46);
SPI.transfer(0x00);
SPI.transfer(0x00);
digitalWrite(SLAVESELECT,HIGH);}

theboxstatus =1;
delay(10000);}
}else{
theboxstatus = 0;
}
}

there is a magnetic switch on a box to sense the voltage.

On what box? To sense what voltage? A magnetic switch doesn't sense voltage.

When the box is open, the magnet move apart, and sound will be played.

That has nothing to do with sensing voltage. The sensor senses the change in the magnetic field as the magnet is moved.

However, I just want to play the sound one time

One time, each time the box is opened? Or one time, period?

Alarm.delay(1000); // wait one second between clock display

That's going to make the box unresponsive.

I therefore havev no choice but put a delay(10000) at the end.

Sure you do. You want to play the music when the sensor state BECOMES LOW, not IS LOW. Look at the state change detection example to see how to differentiate between BECOMES and IS.

Look at and study the example 02.Digital > StateChangeDetection

MarkT:
Look at and study the example 02.Digital > StateChangeDetection

Thank you very much Paul and Mark
I think i got meaning of BECOMES and IS LOW

For the part of playing music, when I open the box, I want the box just play the code in between once(the sound), and therefore I int theboxstatus =1 at the end to try to stop the loop. but seems I cannot stop the loop, so my box keep playing sound when it is open, why?

void loop(){
if(digitalRead(button) == LOW){
if(theboxstatus==0){

{digitalWrite(SLAVESELECT,LOW);
spi_transfer(SET_PLAY); // clear interupt and eom bit
SPI.transfer(0x00);
SPI.transfer(30);
SPI.transfer(0x00);
SPI.transfer(46);
SPI.transfer(0x00);
SPI.transfer(0x00);
digitalWrite(SLAVESELECT,HIGH);}

theboxstatus =1;
delay(10000);}
}else{
theboxstatus = 0;
}

I think i got meaning of BECOMES and IS LOW

Then implement it in your code.

but seems I cannot stop the loop

That is correct.

so my box keep playing sound when it is open, why?

Read through the code and you will see there is nothing you do to stop it.

While you are at it read the how to use the forum sticky so you can post your code correctly.

Read through the code and you will see there is nothing you do to stop it.

Put each { and each } on a new line. Then, use Tools + Auto Format to fix your atrocious indenting, and I think the situation will become a lot more obvious. If not, post the code again, and we'll help.

You might also consider whether all your curly braces are needed.

The whole point is that to detect a state change on a pin you must
remember the previous state on the pin to compare with the current state.

Code will always be like:

  now_state = digitalRead (...) ;
  if (now_state != previous_state)  // detect a change
  {
    if (now_state == ...)  // HIGH or LOW depending on which change
    {
      perform_action () ;
    }
    previous_state = now_state ;  // housekeeping for next time
  }

MarkT:
The whole point is that to detect a state change on a pin you must
remember the previous state on the pin to compare with the current state.

Thanks MarkT.
I tried your code with my magnet and it works.
but how to make the action perform one time only when the state doesn't change? Let say when the box open, it only play the action one time only, and when it close, it do nth.

int buttonPin = 2; 

void setup ()
{
  Serial.begin(9600);
  pinMode (buttonPin, INPUT);
}

int now_state = 0;
int pre_state = 7;
int box=0;
void loop()
{
   now_state = digitalRead(buttonPin);
   if (now_state != pre_state)
  { 
   if(now_state == LOW)
     {
      // A transition occurred...
         Serial.print('1');
         delay(1000);
         Serial.print('0');
         delay(1000);
         Serial.println("hey how are you");
        
     }
     pre_state = now_state;
  }
}

but how to make the action perform one time only when the state doesn't change?

This doesn't make sense. When would you perform this action if the state doesn't change?

In your case, there is a state change, too open, when the lid is opened, and a state change, to closed, when the lid is closed.

Play the music when the state changes to open. Do nothing when the state changes to closed.

PaulS:

but how to make the action perform one time only when the state doesn't change?

This doesn't make sense. When would you perform this action if the state doesn't change?

In your case, there is a state change, too open, when the lid is opened, and a state change, to closed, when the lid is closed.

Play the music when the state changes to open. Do nothing when the state changes to closed.

Sorry for my bad description.
What I mean is, I hope that when the box open(the state change), and the the music play one time only(run the action one time only), when the box is still open.

Now the code will make the box
Box open-->play music(keep playing until I close the box)--->Box then close--->box open---play music(keep playing until I close the box)

The whole thing i want to make is sth like
Box open-->play music(one time )-->Box then close--->box open--->play music(one time)

is it possible to achieve such a function?

is it possible to achieve such a function?

Yes and we have been telling you over and over what you need to do.

One more time:-
You need to detect the change between the box being open and it being closed and use that to trigger the code that makes the sounds.
The sound will not continually play if you actually do this.

tcjwm:

MarkT:
The whole point is that to detect a state change on a pin you must
remember the previous state on the pin to compare with the current state.

Thanks MarkT.
I tried your code with my magnet and it works.
but how to make the action perform one time only when the state doesn't change? Let say when the box open, it only play the action one time only, and when it close, it do nth.

int buttonPin = 2; 

void setup ()
{
  Serial.begin(9600);
  pinMode (buttonPin, INPUT);
}

int now_state = 0;
int pre_state = 7;
int box=0;
void loop()
{
   now_state = digitalRead(buttonPin);
   if (now_state != pre_state)
  {
   if(now_state == LOW)
     {
      // A transition occurred...
         Serial.print('1');
         delay(1000);
         Serial.print('0');
         delay(1000);
         Serial.println("hey how are you");
       
     }
     pre_state = now_state;
  }
}

This code that you posted that I quoted above will do just what you requested (difficult to tell because your indenting is a bit off, use CTRL-T in the IDE to clean that up) but instead of playing music it will print to the serial monitor just once when the digital signal at pin 2 goes low. (Did you actually try it out and see the effect?)

I just took a look at the code in your first posting (kindly go back and edit that post to add the code tags...) and I see a bunch of commands being sent out to another device via SPI where it looks like you want music to be played. You have not given us any description of what is on the receiving end of those commands (a link to a datasheet would be nice as well) that I presume is doing the job of playing the music. It might be as simple as sending a different command (one that means play once instead of one that means play repeatedly), or you need to know when to send an additional command to tell it to stop. Either after the appropriate amount of time, or when the lid closes (this is simple to add sending the command over SPI as an else clause to the inner nested if statement), or both.