Multiple level sound trigger

How would I break out of one loop at the push of a momentary button, and go into another loop?

You don't break out of any loop? What makes you think you have to.

Your loop function will read each push button in turn and when it sees one pressed plays that sample.

The loop would be;

Play introduction audio clip 1 Delay 30 seconds Play intro clip 2 Delay 30 seconds Play intro clip 3 Delay 30 seconds Play intro clip 4 Delay 30 seconds

And start over

There can only be one start button and I need to the Arduino to know at what point in the loop it is pressed – if it’s between playing intro 3 and the delay before intro 4 is played then the sequence is run with the same character that read intro 3

If that is what you want to do you need to remove all those delays an implement your code as a state machine.

See my http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html Or Robin2's several things at once http://forum.arduino.cc/index.php?topic=223286.0

And the blink without delay example in the IDE.

What changes the character?

Thanks for your help Mike,

I will look through those links today and hopefully come up with something.

What changes the character?

This is just done by which audio clips are played back to the user, different scripts read by different people, the program will still go through the same sequence of events, just the clips played back to the user will be unique, they will match the voice of which ever character happens to be reading the 'intro' clip when that particular user pushes the 'start' button.

I’m hoping this all makes sense. Just a little background as to what this is all for – I work for a special effects / model making company for film and TV, I specialise in engineering and physical effects, our normal guy that we would get to do our electronics has recently left, so in my ultimate wisdom I thought I’d give it a go! So we’ve got this interactive vending machine to get working which will be taken around London for people to come and have a go at getting it to vend them a free yogurt while they are secretly filmed for a TV advert.

I'm really stuck on this now and I’m running out of time, help would be greatly appreciated. I’ve read lots on state machines but it’s not clicking in my mind as to how this can help me? Is what I’m trying to achieve doable?

• Intro 1 is played --> user pushes start --> sequence happens with set 1 of audio clips OR

• No user input

• Intro 2 is played --> user pushes start --> same sequence happens with set 2 of audio clips OR

• No user input

• Intro 3 is played --> user pushes start --> same sequence happens with set 3 of audio clips OR

• No user input

• Intro 4 is played --> user pushes start --> same sequence happens with set 4 of audio clips OR

• No user input

• Loop starts over

There can only be one start button, it needs to change what it does depending on when it is pushed. i.e. if its pushed while intro 3 is playing it will take you to the code where the sequence contains set 3 audio clips.

I need a little more direct guidance to help me finish this, hopefully you guys can give me that

I'm really stuck on this now and i'm running out of time, help would be greatly appreciated

Each one of those lines is a state. Number them. Have a variable that holds that number.

The loop function looks at that number and sees if the state should move on. Two things change that state:-

  1. The time for the state has been met, you then go and increment that state variable and do the next thing on the list. That is your “no user input state”.
  2. The user has pressed a button - in which case the state changes to what you have in the “user pushes start” condition.

ust a little background as to what this is all for…

Oddly enough I just watched the “Inside Number 9” the “Seance” episode on BBC iPlayer which is not a million miles from what you are doing. You might want to watch it.

Here’s my code so far;

I’ve been playing around trying to make a state machine, unsure of layout though. I’ve got it looping through my introductions but it doesn’t seem to detect a button press and move into the appropriate state.

I have my ‘start’ button on a 555 timing relay so that whenever it is pushed during each introduction it will stay latched ‘HIGH’ long enough for the Arduino to read its state.

#include <SoftwareSerial.h>
#include <MP3Trigger.h>

SoftwareSerial trigSerial = SoftwareSerial(4, 3);
MP3Trigger trigger;

#define PIN_GATE_IN 2
#define IRQ_GATE_IN  0
#define PIN_LED_OUT 13
#define PIN_ANALOG_IN A0
#define PIN_RELAY_OUT 10
#define PIN_buttonPin 5

void soundISR()
{
  int pin_val;

  pin_val = digitalRead(PIN_GATE_IN);
  digitalWrite(PIN_LED_OUT, pin_val);   
}
int Relay = 10;
int stateRelay = LOW;
const int buttonPin = 5;
int buttonState = 0;
void setup()
{
  pinMode(buttonPin, INPUT);
  pinMode(Relay, OUTPUT);
  Serial.begin(38400);

  //  Configure LED pin as output
  pinMode(PIN_LED_OUT, OUTPUT);

  // configure input to interrupt
  pinMode(PIN_GATE_IN, INPUT);
  attachInterrupt(IRQ_GATE_IN, soundISR, CHANGE);
}
void loop() 
  {
  static int state = 1; // initial state is 1, the "idle" state.
  static unsigned long ts;  // To store the "current" time in for delays.
  
  switch(state)
  {
    
case 1:

{trigger.setup(&trigSerial);
  trigSerial.begin( MP3Trigger::serialRate() );
trigger.update();
  trigger.play(1);
  Serial.println("play track 1");
  delay(7500);
  buttonState = digitalRead(buttonPin);}

if (buttonState == HIGH) state = 2;
else if (buttonState == LOW);  
    
    {trigger.setup(&trigSerial);
  trigSerial.begin( MP3Trigger::serialRate() );
trigger.update();
  trigger.play(2);
  Serial.println("play track 2");
  delay(4500);
buttonState = digitalRead(buttonPin);}

if (buttonState == HIGH) {state = 3;}
else if (buttonState == LOW);
      
      {trigger.setup(&trigSerial);
  trigSerial.begin( MP3Trigger::serialRate() );
trigger.update();
  trigger.play(3);
  Serial.println("play track 3");
  delay(6500);
buttonState = digitalRead(buttonPin);}
if (buttonState == HIGH) {state = 4;}
  
      break;
  
case 2:

  {int value;

  // Check the envelope input
  value = analogRead(PIN_ANALOG_IN);

  // Convert envelope value into a message
  Serial.print("Status: ");
  if(value <= 60)
  {
    Serial.println("Quiet.");
  }
  else if( (value > 60) && ( value <= 200) )
  {
    Serial.println("Moderate.");
  trigger.setup(&trigSerial);
  trigSerial.begin( MP3Trigger::serialRate() );
trigger.update();
  trigger.play(4);
   delay(2500);
  }
  else if(value > 200)
  {
    Serial.println("Loud.");
     trigger.setup(&trigSerial);
  trigSerial.begin( MP3Trigger::serialRate() );
trigger.update();
     trigger.play(7);
      delay(3000);
 digitalWrite(Relay,HIGH);
 delay(17000);
 digitalWrite(Relay,LOW);
}

  // pause for 1 second
  delay(500);
  }
 
      break;
    
case 3:
     
     break;
     
case 4:  


default:
  
state = 1;
      break;
      }
  }

Sorry but that is nowhere even close to being what I told you to do.

What is the soundISR function supposed to do and why have you got it. I never said anything about ISRs.

A state machine checks the button and if it is pressed changes the state. Then it goes on to execute the code associated with that state.

THERE ARE NO DELAYS PERMITTED

Delays totally defeat the whole purpose of a state machine. If you want to delay while still looking at the push button you have a millis() time like in the blink without delay sketch.

You keep putting this in your code:-

  // pause for 1 second
  delay(500);

Which do you want to do? the 500 in the delay will pause for half a second. During a delay nothing else can be done, so you don't use them.