Wave shield code, consecutive and non-consecutive sounds

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
toby
 
Posts: 32
Joined: Wed Aug 04, 2010 11:12 am

Re: Wave shield code, consecutive and non-consecutive sounds

Post by toby »

Also I forgot to mention.
For some reason when I use xl97's suggestion (see code below) it works okay except for the random 4-5 second delay after pushing button2. Unfortunately I can't have a random delay there. The odd thing is code has justpressed[2] in it! I know it should not though, it should just be justpressed[0] and justpressed[1] seeing as there are only two buttons.

Ohhh the confusion ......

Code: Select all

#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"

char filename[10]; // leave enough room here.
int button2Counter = 0;

SdReader card;    // This object holds the information for the card
FatVolume vol;    // This holds the information for the partition on the card
FatReader root;   // This holds the information for the filesystem on the card
FatReader f;      // This holds the information for the file we're play

WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

#define DEBOUNCE 5  // button debouncer

// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
byte buttons[] = {7, 8};
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)
// we will track if a button is just pressed, just released, or 'pressed' (the current state
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];

// this handy function will return the number of bytes currently free in RAM, great for debugging!   
int freeRam(void)
{
  extern int  __bss_end; 
  extern int  *__brkval; 
  int free_memory; 
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval); 
  }
  return free_memory; 
} 

void sdErrorCheck(void)
{
  if (!card.errorCode()) return;
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}

void setup() {
  byte i;
  
  // set up serial port
  Serial.begin(9600);
  putstring_nl("WaveHC with ");
  Serial.print(NUMBUTTONS, DEC);
  putstring_nl("buttons");
  
  putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
  Serial.println(freeRam());      // if this is under 150 bytes it may spell trouble!
  
  // Set the output pins for the DAC control. This pins are defined in the library
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
 
  // Make input & enable pull-up resistors on switch pins
  for (i=0; i< NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT);
    digitalWrite(buttons[i], LOW);
  }
  
  //  if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
  if (!card.init()) {         //play with 8 MHz spi (default faster!)  
    putstring_nl("Card init. failed!");  // Something went wrong, lets print out why
    sdErrorCheck();
    while(1);                            // then 'halt' - do nothing!
  }
  
  // enable optimize read - some cards may timeout. Disable if you're having problems
  card.partialBlockRead(true);
 
// Now we will look for a FAT partition!
  uint8_t part;
  for (part = 0; part < 5; part++) {     // we have up to 5 slots to look in
    if (vol.init(card, part)) 
      break;                             // we found one, lets bail
  }
  if (part == 5) {                       // if we ended up not finding one  :(
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();      // Something went wrong, lets print out why
    while(1);                            // then 'halt' - do nothing!
  }
  
  // Lets tell the user about what we found
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?
  
  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!"); // Something went wrong,
    while(1);                             // then 'halt' - do nothing!
  }
  
  // Whew! We got past the tough parts.
  putstring_nl("Ready!");
  
  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= 1<<TOIE2;


}

SIGNAL(TIMER2_OVF_vect) {
  check_switches();
}

void check_switches()
{
  static byte previousstate[NUMBUTTONS];
  static byte currentstate[NUMBUTTONS];
  byte index;

  for (index = 0; index < NUMBUTTONS; index++) {
    currentstate[index] = digitalRead(buttons[index]);   // read the button
    
    /*     
    Serial.print(index, DEC);
    Serial.print(": cstate=");
    Serial.print(currentstate[index], DEC);
    Serial.print(", pstate=");
    Serial.print(previousstate[index], DEC);
    Serial.print(", press=");
    */
    
    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
          // just pressed
          justpressed[index] = 1;
      }
      else if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
          // just released
          justreleased[index] = 1;
      }
      pressed[index] = !currentstate[index];  // remember, digital HIGH means NOT pressed
    }
    //Serial.println(pressed[index], DEC);
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons
  }
}


void loop() {
  byte i;


  if (justpressed[1]) {
    justpressed[1] = 0;  
    playcomplete("CHEER.WAV");
  } 
  if(justpressed[2]){
    justpressed[2] = 0;
    sprintf(filename,"%d.wav", button2Counter);
    playcomplete(filename);
    Serial.println(filename); 
    //check it at last file and reset if needed
    if(button2Counter == 4){
      button2Counter = 0;
    }
    else{
      button2Counter++;
    }
  }
}





// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
  // call our helper to find and play this name
  playfile(name);
  while (wave.isplaying) {
  // do nothing while its playing
  }
  // now its done playing
}

void playfile(char *name) {
  // see if the wave object is currently doing something
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  // look in the root directory and open the file
  if (!f.open(root, name)) {
    putstring("Couldn't open file "); Serial.print(name); return;
  }
  // OK read the file and turn it into a wave object
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV"); return;
  }
  
  // ok time to play! start playback
  wave.play();
}

User avatar
xl97
 
Posts: 201
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave shield code, consecutive and non-consecutive sounds

Post by xl97 »

Hi toby-

see if this sketch works for your solution..
1.) (check yoru buttons, and how they are PHYSICALLY wired to the Arduino.. are they correct?, do they match the code?)
2.) just for fun.. to eliminate anything odd for now.. use a momentary switch for you first switch too..(all momentary)
3.) The 'fix':

*It plays 'cheer.wav' when first button is pressed
* All other files need to be named 1.wav, 2.wav, 3.wav, 4.wav & 5.wav...(I just used 5 as the cap..but it can be set in the code to be whatever you want.

Code: Select all


// Solution sketch for this adafruit post:
// http://forums.adafruit.com/viewtopic.php?f=31&t=33737&sid=91be6ee3b73ff313c765f17ad1cec69d&p=170020#p170020
// created by: xl97
 
//import default/needed libraries
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"

//custom defined variables
const int mainButton =  18;
const int secondaryButton =  16;

char filename[10]; // leave enough room here.
int trackCounter = 0;
int totalTracks = 5;

//project variables
SdReader card;    // This object holds the information for the card
FatVolume vol;    // This holds the information for the partition on the card
FatReader root;   // This holds the information for the filesystem on the card
FatReader f;      // This holds the information for the file we're play
WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

#define DEBOUNCE 5  // button debouncer

//make button array for easy looping/checking
int buttons[] = {mainButton, secondaryButton};
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)

// we will track if a button is just pressed, just released, or 'pressed' (the current state)
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];

// this handy function will return the number of bytes currently free in RAM, great for debugging!   
int freeRam(void)
{
  extern int  __bss_end; 
  extern int  *__brkval; 
  int free_memory; 
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval); 
  }
  return free_memory; 
} 

void sdErrorCheck(void)
{
  if (!card.errorCode())
  {
    return;
  }
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}

   //------------------[end init code]---------------------//
   
   

void setup() {
  byte i;
  // Set up serial port
  Serial.begin(9600);
  
  putstring_nl("WaveHC with ");
  Serial.print(NUMBUTTONS, DEC);
  putstring_nl("buttons");

  putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
  Serial.println(freeRam()); 
  
  // Set-up pins not in button array
  // pin13 LED
  pinMode(13, OUTPUT);
  
  // Make input & enable pull-up resistors on switch pins
  for (i=0; i< NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT);
    digitalWrite(buttons[i], HIGH);
  }
  //  if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
  if (!card.init()) {         //play with 8 MHz spi (default faster!)  
    putstring_nl("Card init. failed!");  // Something went wrong, lets print out why
    sdErrorCheck();
    while(1);                            // then 'halt' - do nothing!
  }

  // enable optimize read - some cards may timeout. Disable if you're having problems
  card.partialBlockRead(true);

  // Now we will look for a FAT partition!
  uint8_t part;

  for (part = 0; part < 5; part++) {     // we have up to 5 slots to look in
    if (vol.init(card, part)) 
      break;                             // we found one, lets bail
  }
  if (part == 5) {                       // if we ended up not finding one  :(
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();      // Something went wrong, lets print out why
    while(1);                            // then 'halt' - do nothing!
  }

  // Lets tell the user about what we found
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?

  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!"); // Something went wrong,
    while(1);                             // then 'halt' - do nothing!
  }

  // Whew! We got past the tough parts.
  putstring_nl("Ready!");

  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= 1<<TOIE2;
}


//--------------------[end set-up code]-----------------------//

//Add function for timer to execute.
SIGNAL(TIMER2_OVF_vect) {
  check_switches();
}


//check switches function (watched by timer repeatedly)
void check_switches()
{
  //create vars to hold the states of the current button being checked
  static byte previousstate[NUMBUTTONS];
  static byte currentstate[NUMBUTTONS];
  byte index;

  //run through each button in the array to check if it is being pressed
  for (index = 0; index < NUMBUTTONS; index++) {
    currentstate[index] = digitalRead(buttons[index]);   // read each button/store its status
    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
        // just pressed
        //putstring("Button Pressed: ");
        //Serial.println(index,DEC); 
        justpressed[index] = 1;
      }
      else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
        // just released
        justreleased[index] = 1;
      }
      pressed[index] = !currentstate[index];  // remember, digital HIGH means NOT pressed //commenting out stops file while pressed
    }
    //Serial.println(pressed[index], DEC);
    //update previous status to the current status
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons
  }
}

void loop(){
  //main button
  if (justpressed[0]) {
    justpressed[0] = 0; 
    playfile("cheer.wav");
  }
  //second button (plays next track)
  if(justpressed[1]){
    justpressed[1] = 0;
    sprintf(filename,"%d.wav", trackCounter);
    Serial.println(filename);

    playfile(filename);    
    //check it at last file and reset if needed
    if(trackCounter == totalTracks){
      trackCounter = 0;
    }
    else{
      trackCounter++;
    }
  }
  
}


void playfile(char *name) {
  // look in the root directory and open the file
  if (!f.open(root, name)) {
    putstring("Couldn't open file "); 
    Serial.print(name); 
    return;
  }
  // OK read the file and turn it into a wave object
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV"); 
    return;
  }
  wave.play();  
}
   
make sure files are on SD card
make any changes noted above
upload new sketch, post back

:)
Last edited by xl97 on Thu Nov 15, 2012 1:57 pm, edited 1 time in total.

User avatar
adafruit_support_bill
 
Posts: 88092
Joined: Sat Feb 07, 2009 10:11 am

Re: Wave shield code, consecutive and non-consecutive sounds

Post by adafruit_support_bill »

The odd thing is code has justpressed[2] in it!
There is no bounds-checking on the arrays. Based on the way the arrays are declared, the justreleased[] array is next to justpressed[] in memory. So justpressed[2] is most likely really justreleased[0].

As xl97 suggested. We should verify how you have everything connected before attempting to debug any further. Post a photo showing all your connections.

User avatar
toby
 
Posts: 32
Joined: Wed Aug 04, 2010 11:12 am

Re: Wave shield code, consecutive and non-consecutive sounds

Post by toby »

Alright all.
I'm going to go over my connections and code with a fine tooth comb and try the code you posted xl97. THANK YOU

The 2 button pins on the arduino connected to the wav shield are being driven high and low from a second arduino. I'm going to go over EVERYTHING today.

Yes, I do feel kind of sick right now over this.

User avatar
xl97
 
Posts: 201
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave shield code, consecutive and non-consecutive sounds

Post by xl97 »

I updated my code a bit.. (above)

I was using your old code as base..etc..etc and copy/paste.. so I just used a known good sketch I had.. transplanted the data I posted for you to use/add..

and tested it.. seemed to work fine.

when I press the main button... it plays the cheers.wav file..

when I press the secondary button..

it plays 1.wav

when I press it again it plays: 2.wav

when I press it again.. plays: 3.wav..etc..

& when I press main button at any time.. it plays cheer.wav audio file.

User avatar
toby
 
Posts: 32
Joined: Wed Aug 04, 2010 11:12 am

Re: Wave shield code, consecutive and non-consecutive sounds

Post by toby »

I'm almost afraid to jinx this by saying everything is working but EVERYTHING IS WORKING!

I've yet to add the dozen of files I need to add for this project but the 4 test ones are playing perfectly.

I CAN'T THANK YOU BOTH ENOUGH.
SERIOUSLY.

If either of you find yourself in Pittsburgh, PA hit me up for a beer a coffee or both. :)

User avatar
xl97
 
Posts: 201
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave shield code, consecutive and non-consecutive sounds

Post by xl97 »

hi- :)

not sure what code you're using.. but if its mine or a variant based off min, to work with more than the 5 tracks the demo code does..

change this line:

int totalTracks = 5;


glad it all worked out. :)

User avatar
toby
 
Posts: 32
Joined: Wed Aug 04, 2010 11:12 am

Re: Wave shield code, consecutive and non-consecutive sounds

Post by toby »

wave.JPG
wave.JPG (134.46 KiB) Viewed 861 times
I did end up using yours xl97 and I did notice and take note of that "int totalTracks = 5;" Thanks for bringing it to my attention though.

I'm glad we didn't have to go over soldering jobs, correct wire routing, etc. because this is the mess I'm dealing with....

User avatar
xl97
 
Posts: 201
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave shield code, consecutive and non-consecutive sounds

Post by xl97 »

wow..

looks.. umm...... painful?

lol


glad everything is working out for you now!.


hooray Adafruit! :)

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”