Go Down

Topic: Need help with audio player and lights for son's star wars (Read 66 times) previous topic - next topic

ike9090

Hello and thank you for taking the time to help. I build models for my son to hang in his room. I have gotten bored with model kits and I started adding lights in engines, added motors to run propellers and I am moving on to scratch builds. I am trying to make something new for my 7 year old son and I am running into some problems.

The set up:
Build a turbo laser tower that plays an audio file and blinks some LEDs. For those of us who are star wars nerds, we have all seen the Tony Agustin turbolaser tower.
http://www.starshipmodeler.com/starwars/ta_tower.htm

Well my son liked it so I started building my own. I want the tower to play a WAV file (about 15 seconds long) and the (2) LEDs in the gun barrels to flash when the lasers fire in the audio clip. This seemed simple enough when I was thinking about his toys that play a sound and light up different ways when you push a button. So I got a microcontroller and an audio recorder. arduino uno and VMA02 audio shield.


My problem:
I cannot get my light sequence to run when I play the audio clip.

What I have done:
I know the light sequence runs independent of playing the audio, tested and works. Although, the pin outputs don't really put out the amps I was expecting. I read the output was 5 volts at 40 mA, but my leds are 4 volts at 30 mA and it barely lights up. I will wire an external battery with a relay off the pin out for this.

I know the code works for the audio shield as I have recorded and played multiple times.

I have tried writing the code to do the light sequence under the play switch case and I have tried writing it to play in the light sequence. I can't initialize both and wondering if someone could tell me why.
Here is the code for the light:

const int buttonPin = 2;
const int ledPin = 13;
int buttonState = 0;
pinMode(ledPin, OUTPUT);
  pinMode(buttonPin,INPUT);

  buttonState = digitalRead(buttonPin);
  if(buttonState==HIGH){
    chip.play();
    digitalWrite(ledPin, HIGH);
    delay(4000);
    digitalWrite(ledPin, LOW);
    delay(500);
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(300);

   etc...


The code for the audio player is:
void loop()
{
  char c;
 
  if(Serial.available())
  {
    /* Power Up */
    chip.pu();
    c = Serial.read();
    switch(c)
    {
       case 'A':
       break;       
       case 'Y':
         chip.play();
       case 'y':
         chip.set_play(startAddr,endAddr);
         Serial.println("PLAYING2");
         break;

The printline "playing2" is an example of where I tried putting the light code. I started simplifying it to just print lines and watching on the serial monitor to see if I could figure out what was initializing the chip to play, but I couldn't figure it out.

Please help...
Oh and once this is said and done, it will only not have to record and play any other sounds.

AMPS-N

send us complete code in ZIp file.So we can test out. also share from where you download the library
AMPS

ike9090

There is really nothing to zip together. I wrote the code for the LED first and verified its working. Then I independently loaded the sample code for the audio shield and verified it is working. Then I just changed some things in the audio shield code to see if I could find a trigger. My understanding is that the switch case is similar to the IF statements and tried adding code under the chip.play and chip.set_play cases. I didn't make much progress.

The spec sheet on the velleman audio shield is here
http://pdf1.alldatasheet.com/datasheet-pdf/view/211087/WINBOND/ISD1760PY.html

The library for the shield I got from here
http://www.vellemanusa.com/support/downloads/?code=VMA02

ISP1700 code can be found here
http://www.open-electronics.org/a-voice-shield-for-arduino-give-voice-to-your-ideas/


And my LED code is


const int buttonPin = 2;     
const int ledPin =  12;     
int buttonState = 0;       
void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
}

void loop() {
  buttonState = digitalRead(buttonPin);


  if (buttonState == HIGH) {
    digitalWrite(ledPin, HIGH);
    delay(4000);
    digitalWrite(ledPin, LOW);
    delay(500);
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(300);
    digitalWrite(ledPin, HIGH);
    delay(800);
    digitalWrite(ledPin, LOW);
    delay(500);
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(4000);
    digitalWrite(ledPin, HIGH);
    delay(300);
    digitalWrite(ledPin, LOW);
    delay(500);
   
  }
  else {
    digitalWrite(ledPin, LOW);
  }
}

AMPS-N

use the code tags properly. you need to save last button state. That i have included here

Code: [Select]

const int buttonPin = 2;     
const int ledPin =  12;     
int buttonState = 0;   
int buttonPushCounter = 0;   // counter for the number of button presses
int lastButtonState = 0;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
}

void loop() {
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState)
  {

    if (buttonState == HIGH) {
      digitalWrite(ledPin, HIGH);
      delay(4000);
      digitalWrite(ledPin, LOW);
      delay(500);
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
      delay(300);
      digitalWrite(ledPin, HIGH);
      delay(800);
      digitalWrite(ledPin, LOW);
      delay(500);
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
      delay(4000);
      digitalWrite(ledPin, HIGH);
      delay(300);
      digitalWrite(ledPin, LOW);
      delay(500);

    }
    else {
      digitalWrite(ledPin, LOW);
    }
  }
  lastButtonState = buttonState;

}



AMPS

GoForSmoke

You've been doing real simple single-action projects so far?
The delays in your led code are blind spots. That kind of code causes problems when mixed with other code.

See if you can learn this led blink sketch. There are tutorials to help, I link to the best most common sense tutorial I know of in the sketch comments, Nick tells the whys as well as the what and how.

If you're ever played RTS games and turn-based games, this lesson will get you writing Real Time Code as opposed to Turn Based Code. The results can be incredible and the base idea is actually simple. For a lot of coders, the hard part is breaking from old habits. New people have an edge there!

It is set up to run on an UNO with 1 jumper, instead of feeding my button pin 5V, I make it work when it is grounded. You can change the code or you can change your wiring to go from the switch to ground instead of 5V.

This sketch is tested and works. It gives serial output that lets you watch what's going on.

Code: [Select]

// this sketch is adjusted to run on an UNO with a jumper for switch
// stick a male:male jumper in pin 2.
// To "press the button", ground the free end, I use the UNO USB box.
// Change the pins and other code to suit your needs.

// You can follow the debug text with Serial Monitor set to 115200 baud.

// If you learn how this works, you will be better able to add other
// code and have it all work. My goal here is that you learn.
// Forum post notifications are not always working, you can send me a
// PM (private message) if I don't reply to the thread. GoForSmoke.
// A VERY GOOD TUTORIAL on the subject (as in look here first!) is:
// http://www.gammon.com.au/blink
// Nick gives a very clear and full explanation of the subject.
// Honest -- what this shows will let you run MANY THINGS at once.

const byte buttonPin = 2;     
const byte ledPin =  13;     

void setup()
{
  Serial.begin( 115200 );
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // my switch wires direct to ground
}

byte laserGun( byte runstate )
{
  static unsigned long gunStartMillis, gunWaitMillis;
 
  static int waitTime[ 10 ] = // this is where you adjust timing
  {
    4000, 500, 500, 300, 800, 500, 500, 4000, 300, 500
  };

  if ( millis() - gunStartMillis < gunWaitMillis )
  {
    return runstate; // time to change is not up yet
  }

  if ( runstate > 10 ) // finally finished the last wait
  {
    gunWaitMillis = 0;
    return 0; // turn it off!
  }

  digitalWrite(ledPin, ( runstate & 1 )); // HIGH on odd, LOW on even

  gunStartMillis = millis();
  gunWaitMillis = waitTime[ runstate - 1 ]; // array starts at [0]

  Serial.print( "lasergun " );
  Serial.print( runstate );
  Serial.print( " " );
  Serial.println( gunWaitMillis );

  runstate++;

  return runstate;
}

void loop()
{
  static byte buttonState = 0;
  static byte laserGunState = 0;

  if (laserGunState == 0) // true when not in gun sequence
  {
    buttonState = digitalRead(buttonPin);
   
    if (buttonState == LOW) // this to make 1 press trigger 1 event 
    {
      laserGunState = 1;
    }
  }


  if (laserGunState > 0)
  {
    laserGunState = laserGun( laserGunState );
  }

  // you can add what you want now and
  // it will get frequent cycles if it doesn't block execution
}
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

GoForSmoke

BTW, this looks like a good project to put on a stand-alone ATtiny chip instead of a whole Arduino board.

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

ike9090

Thank you. I will work on the LEDs without the delay function. Remember that I am not having trouble getting the LEDs to work properly, I can't find what initiates the audio play back. I need to join them together.

GoForSmoke

When you see how the leds work, you should also see how to add the MP3 and some servos for the turret and guns and still you probably won't be pushing the processor anywhere near limits.

This kind of code allows you to add new pieces straight from test code loop() to project loop().
It's about how at 16 MIPS, if none of your tasks (buttons, leds, music, etc) makes the code wait, you can automate hundreds of simple things together a piece at a time.
As long as response doesn't lag noticeably, there might be room to add some more. If you need more flash or RAM there's generally a bigger chip for less than lunch money.

How many models do you have 'active' now? You could probably run them all from one AVR.

I'll put up a version with more debug info to show the time scale that code runs at. It may open your eyes.
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

GoForSmoke

This version has debug info concerning speed as well as execution.

As you can see from the output, only running the leds (and debug prints) consistently gets over 100 time checks per millisecond response. You could run 100 more tasks like it and get them all attention 1000 times per second when you can't see much better than 30.

Code: [Select]

// LaserGunBlink2 -- the Debug Deepens -- public domain by GoForSmoke
// this sketch is adjusted to run on an UNO with a jumper for switch
// stick a male:male jumper in pin 2.
// To "press the button", ground the free end, I use the UNO USB box.
// Change the pins and other code to suit your needs.

// You can follow the debug text with Serial Monitor set to 115200 baud.

// If you learn how this works, you will be better able to add other
// code and have it all work. My goal here is that you learn.
// Forum post notifications are not always working, you can send me a
// PM (private message) if I don't reply to the thread. GoForSmoke.
// A VERY GOOD TUTORIAL on the subject (as in look here first!) is:
// http://www.gammon.com.au/blink
// Nick gives a very clear and full explanation of the subject.
// Honest -- what this shows will let you run MANY THINGS at once.

const byte buttonPin = 2;     
const byte ledPin =  13;     

void setup()
{
  Serial.begin( 115200 );
  Serial.println( F("\n ** Push The Button! **\n" ));
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP); // my switch wires direct to ground
}

byte laserGun( byte runstate )
{
  static unsigned long gunStartMillis, gunWaitMillis;
  static long callsTillTimeout;

  static int waitTime[ 10 ] = // this is where you adjust timing
  {
    4000, 500, 500, 300, 800, 500, 500, 4000, 300, 500
  };

  if ( millis() - gunStartMillis < gunWaitMillis )
  {
    callsTillTimeout++;
    return runstate; // time to change is not up yet
  }

  if ( gunWaitMillis > 0 )
  {
    Serial.print( F( "Called laserGun() " ));
    Serial.print( callsTillTimeout );
    Serial.print( F( " times in " ));
    Serial.print( gunWaitMillis );
    Serial.print( F( " milliseconds, " ));
    Serial.print( callsTillTimeout / gunWaitMillis );
    Serial.println( F( " checks per millisecond." ));
  }

  callsTillTimeout = 0;

  if ( runstate > 10 ) // finally finished the last wait
  {
    Serial.println( F( "\n ** Push The Button! **\n" ));
    return 0; // turn it off!
  }

  digitalWrite(ledPin, ( runstate & 1 )); // HIGH on odd, LOW on even

  gunStartMillis = millis();
  gunWaitMillis = waitTime[ runstate - 1 ]; // array starts at [0], runstate at 1

  Serial.print( F( "lasergun state " ));
  Serial.print( runstate );
  Serial.print( F( " wait milliseconds = " ));
  Serial.println( gunWaitMillis );

  runstate++;

  return runstate;
}

void loop()
{
  static byte buttonState = 0;
  static byte laserGunState = 0;

  if (laserGunState == 0) // true when not in gun sequence
  {
    buttonState = digitalRead(buttonPin);

    if (buttonState == LOW) // this to make 1 press trigger 1 event 
    {
      laserGunState = 1;
    }
  }


  if (laserGunState > 0)
  {
    laserGunState = laserGun( laserGunState );
  }

  // you can add what you want now and
  // it will get frequent cycles if it doesn't block execution
}



Quote
** Push The Button! **

lasergun state 1 wait milliseconds = 4000
Called laserGun() 421225 times in 4000 milliseconds, 105 checks per millisecond.
lasergun state 2 wait milliseconds = 500
Called laserGun() 52173 times in 500 milliseconds, 104 checks per millisecond.
lasergun state 3 wait milliseconds = 500
Called laserGun() 52191 times in 500 milliseconds, 104 checks per millisecond.
lasergun state 4 wait milliseconds = 300
Called laserGun() 31159 times in 300 milliseconds, 103 checks per millisecond.
lasergun state 5 wait milliseconds = 800
Called laserGun() 83792 times in 800 milliseconds, 104 checks per millisecond.
lasergun state 6 wait milliseconds = 500
Called laserGun() 52299 times in 500 milliseconds, 104 checks per millisecond.
lasergun state 7 wait milliseconds = 500
Called laserGun() 52191 times in 500 milliseconds, 104 checks per millisecond.
lasergun state 8 wait milliseconds = 4000
Called laserGun() 420825 times in 4000 milliseconds, 105 checks per millisecond.
lasergun state 9 wait milliseconds = 300
Called laserGun() 31141 times in 300 milliseconds, 103 checks per millisecond.
lasergun state 10 wait milliseconds = 500
Called laserGun() 52182 times in 500 milliseconds, 104 checks per millisecond.

 ** Push The Button! **

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy