Wave Shield + Buttons
Moderators: adafruit_support_bill, adafruit

Re: Wave Shield + Buttons

by bob500000 on Thu Nov 22, 2012 6:43 pm

ok well as described i am after a simple music player

but i want it to cycle, currently there are 3 buttons but the idea is to have 4 buttons.

a play/pause, stop, next and previous. Im not using seek as i just want to change tracks not rewind them.

I have cracked most of the problems but the play pause eludes me, if you can point me in the right direction, would be much appreciated.

Cheers
bob500000
 
Posts: 54
Joined: Tue Nov 20, 2012 11:16 am

Re: Wave Shield + Buttons

by xl97 on Thu Nov 22, 2012 9:41 pm

Well I posted about the pause stuff... still didnt work? (I havent tried myself)..

and I guess my use of FF/RWD was wrong.. I meant NEXT/PREV buttons to be more accurate

Is that now working for you? (the PREVIOUS button?)
xl97
 
Posts: 144
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave Shield + Buttons

by bob500000 on Fri Nov 23, 2012 7:58 am

OK, well getting further on thanks for the assistance.

As you can see from the screenshots included I am able to view wav 1-4 but then when I reverse the order thats when it doesn't work and starts putting minus numbers in there, Also on the final shot you'll see that there is a 0 in there which is like a pause it stops play back for one button press.

Any Ideas on this.


cheers
Attachments
Screen 3.jpg
Screen 3.jpg (96.71 KiB) Viewed 846 times
Screen 2.jpg
Screen 2.jpg (91.95 KiB) Viewed 846 times
Screen 1.jpg
Screen 1.jpg (95.16 KiB) Viewed 846 times
bob500000
 
Posts: 54
Joined: Tue Nov 20, 2012 11:16 am

Re: Wave Shield + Buttons

by xl97 on Mon Nov 26, 2012 12:56 pm

sorry, been busy with the holidays...

are you still having trouble with this? :)

I can probably take a peek today if you like?
xl97
 
Posts: 144
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave Shield + Buttons

by xl97 on Mon Nov 26, 2012 1:24 pm

ok..well form the code you last posted.. I dont even see any PAUSE/RESUME..etc code in there? (nor any buttons enabled for it?)

these seems like a similar thread posted only a few days ago.. (except he wanted to have another button play the same sample over and over added into the mix..but otherwise a audio track player)

some suggestions,

1.) use a case/switch statement to check the condition of 1 var/value with many possible outcomes/paths. (not a bunch of if/else if statements..

2.) you can increment/decrease a var/value like so:

someValue++;
or
someValue--;

maybe your way is throwing an error?



anyways.. here is a different (but similar) approach if you wanna give it a shot.. (at work, not hardware to load/test it on) :(

but you need 4 momentary buttons:
const int prevButton = 16;
const int nextButton = 17;
const int prButton = 18;
const int stopButton = 12;

connected to those pins.

sample code:

Code: Select all | TOGGLE FULL SIZE
// Solution sketch for this adafruit post:
// http://forums.adafruit.com/viewtopic.php?f=31&t=34510
// 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 prevButton =  16;
const int nextButton =  17;
const int prButton =  18;
const int stopButton =  12;

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

//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[] = {prevButton, nextButton, prButton, stopButton};
// 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(){
  //NEXT button (plays next track)
  if(justpressed[0]){
    justpressed[0] = 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++;
    }
  }
 
  //PREV 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 == 0){
      trackCounter = totalTracks;
    }
    else{
      trackCounter--;
    }
  }
 
  //PAUSE/RESUME button
  if (justpressed[2]){
    justpressed[2] = 0;
    if (wave.isplaying) {
      wave.pause();
      Serial.println("paused.....");
    }else{
      wave.resume();
      Serial.println("resumed.....");
    }     
  }
 
  //STOP button
  if (justpressed[3]){
    justpressed[3] = 0;
    if (wave.isplaying) {
      wave.stop();
    }
  }
}


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();
}



xl97
 
Posts: 144
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave Shield + Buttons

by bob500000 on Tue Nov 27, 2012 9:22 am

Cheers mate, I too are at work, so will give it a try when I get in

Sorry we don't have holidays like you over in uk!

Whilst putting a case switch in it kept just playing one song not cycling through them, I will try your solution and also post my switch case code if I can't get it to work!
bob500000
 
Posts: 54
Joined: Tue Nov 20, 2012 11:16 am

Re: Wave Shield + Buttons

by xl97 on Tue Nov 27, 2012 10:35 am

? I'm not located in the UK?

Im located in the US


(but they dont have Thanksgiving where you are?) :)
xl97
 
Posts: 144
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave Shield + Buttons

by bob500000 on Tue Nov 27, 2012 11:23 am

Yeah sorry that's what I meant!

No we don't we only have Christmas and new year!

How long does thanks giving last then?
bob500000
 
Posts: 54
Joined: Tue Nov 20, 2012 11:16 am

Re: Wave Shield + Buttons

by xl97 on Tue Nov 27, 2012 11:44 am

bob500000 wrote:Yeah sorry that's what I meant!

No we don't we only have Christmas and new year!

How long does thanks giving last then?



as long as we can stretch it out for!

usually 1-2 day off of work.. (depending on your job and the day it falls on)
xl97
 
Posts: 144
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave Shield + Buttons

by bob500000 on Wed Nov 28, 2012 5:36 am

Ok, so I tried your code and for some reason it failed to run, no compile errors, just didnt work on the board.

I set it up as you suggested but still no joy, used your example of using four buttons with my code and seems to be working however, im still confused as to where the 0 is coming from, do you have any ideas on that one.

cheers
bob500000
 
Posts: 54
Joined: Tue Nov 20, 2012 11:16 am

Re: Wave Shield + Buttons

by xl97 on Wed Nov 28, 2012 9:01 am

I dont understand what you mean by where '0' is coming from?


Do you have the switches on the correct pins?

//custom defined variables
const int prevButton = 16;
const int nextButton = 17;
const int prButton = 18;
const int stopButton = 12;
xl97
 
Posts: 144
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave Shield + Buttons

by xl97 on Wed Nov 28, 2012 11:05 am

ahh..ok, looking back I see what you mean about the zero...

well in my code example..

we take the total number of 'tracks' you want to 'loop/cycle' through.. (in this instance its 5.. totalTracks = 5)

now, in most/many programming languages, they are 'zero-index' based..

meaning when they start counting.. they start at/with 0 (zero)..

In an array the first index is index[0] (ie: someArray[0] = 7, someArray[1] = 3...etc..etc..)
and in most loops, I start with 0 (zero) as my init value

example:
Code: Select all | TOGGLE FULL SIZE
for(i=0; i < totalTracks; i++){
     // do something while i is less than totaltracks
}


so here.. the code is looking to play 0:

0.wav
1.wav
2.wav
3.wav
4.wav

and then repeat... or go back 'down' in the count..

if you count.. that is '5' wav files... and matches the totalTracks variable we set..

I an MOT sure how many buttons or what you have in your project.. but the code is set up for only the 4 'player' buttons you mentioned..


//custom defined variables
const int prevButton = 16;
const int nextButton = 17;
const int prButton = 18; // play/resume button
const int stopButton = 12;

edit it to match your set-up if not correct...
xl97
 
Posts: 144
Joined: Mon Jul 27, 2009 12:51 pm

Re: Wave Shield + Buttons

by bob500000 on Wed Nov 28, 2012 2:17 pm

Ok, an update I got it working below is the code that I have used to get all the buttons to play ball.

Thanks xl97 for your assistance.

Code: Select all | TOGGLE FULL SIZE
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"


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

int currentSongcount = 0;    // Keeps track of which song to play each time the button is pressed
    int maxSongcount = 4;        // Total number of songs on the SD card
int minSongcount = 1;
int paused = 0;
#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[] = {16, 17, 18, 15};
// 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);

  // 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;


}

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] == LOW) && (currentstate[index] == LOW)) {
          // just pressed
          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
    }
    //Serial.println(pressed[index], DEC);
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons
  }
}

/////////////////////////////////////////////////////
 //This is Button 1 Press
 /////////////////////////////////////////////////////
void loop() {
  byte i;
  static byte playing = 0;
 
  if (justpressed[0]) {
             
       
        if (currentSongcount != maxSongcount)
        {
          currentSongcount == currentSongcount ++;
        } else
        if (currentSongcount == maxSongcount){
          currentSongcount = 1;
        }
       
       
        Serial.println(currentSongcount);

    if (currentSongcount == 1) {
    playfile("1.wav");
    }
    else if (currentSongcount == 2)  {
    playfile("2.wav");
    }
    else if (currentSongcount == 3)  {
    playfile("3.wav");
    }
    else if (currentSongcount == 4)  {
    playfile("4.wav");
    }
      if (! wave.isplaying) {
        playing = 1;
      }
        if (currentSongcount == maxSongcount)
          currentSongcount = 4;
      justpressed[0] = 0;
        }
 /////////////////////////////////////////////////////
 //This is Button 2 Press
 /////////////////////////////////////////////////////
 if (justpressed[1]) {
             
       
        if (currentSongcount != minSongcount)
        {
          currentSongcount == currentSongcount --;
        } else
        if (currentSongcount == minSongcount){
          currentSongcount = 1;
        }
       
       
        Serial.println(currentSongcount);

    if (currentSongcount == 1) {
    playfile("1.wav");
    }
    else if (currentSongcount == 2)  {
    playfile("2.wav");
    }
    else if (currentSongcount == 3)  {
    playfile("3.wav");
    }
    else if (currentSongcount == 4)  {
    playfile("4.wav");
    }
      if (! wave.isplaying) {
        playing = 1;
      }
        if (currentSongcount == minSongcount)
          currentSongcount = 5;
      justpressed[1] = 0;
        }       
 /////////////////////////////////////////////////////
 //This is Button 3 Press
 /////////////////////////////////////////////////////
 if (justpressed[2] && wave.isplaying){
          justpressed[2] = 0;
           wave.pause();
           paused = 1;
           Serial.println("Paused");
        }
 /////////////////////////////////////////////////////
 //This is Button 4 Press
 /////////////////////////////////////////////////////
 if (justpressed[3] && paused ==1){
          justpressed[3] = 0;
          wave.resume();
          paused = 0;
          Serial.println("Resume");
        }
}
   

// 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
  Serial.println("Wave is 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
    Serial.println("Wave Stopped");
  }
  // 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();
  Serial.println("Next Wave is playing");
}

bob500000
 
Posts: 54
Joined: Tue Nov 20, 2012 11:16 am