Wav Trigger project questions

Hi, I am working on a project using a WavTrigger board with Arduino.
The project should do the follwoing:

When a button is pressed a audio file should be playing and continuing playing until finished. while the audio is playing an additional pressing of the button will not effect it.
A led should be ON to indicate that the audio file is playing. The led should go Off the moment the audio file is finished.
Total of 15 buttons and 15 LEDS.

Another thing I would like to do is to count how many tracks are playing in any given time and to change the volume of each track accordingly.
So if only 1 track is playing it will play at unity volume, if another track is playing the new track will play at half of volume and also the track that is already playing will fade over a few seconds (lets say 5 seconds ) to also half of the volume.

If another track will join each of the tracks will play at third of the volume etc etc.
so basically what I try to achieve is that no matter how much track are playing the total volume of all tracks will be unity so will not have any distortion.

I try to achieve it in the code I am sharing down below but without a success.

Regarding the electronics. Assuming a moment all 15 track are playing and therfore a 15 LEDs are ON - can I drive them all from Arduino Mega?

Is it better to use two multiplexer to read the button states and to output the LED states? is that possible?

So What am I asking is help with the code I have (That was used with Arduino Mega)
and to ask if you think I should use the Mega or is better to use 2 multiplexer?

Any other recommendation?

Thanks for Any help!

Code I used in the past:

#include <wavTrigger.h>

/* Arduino Mega Serial port to use: Serial Port 3:
Pin 14: TX
Pin 15: RX
*/

// Buttons //
const int buttonPins[] = {2,3,4,5,6,7,8,9,10,11,12,16,17,18,19,68,69,22,23,24,25,26,27,28}; //array of buttons pins
const int numOfButtons =  (sizeof(buttonPins) / sizeof(buttonPins[0])); // size of push buttons

// Leds //
const int ledPins[] ={30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53}; // array of leds pins
const int numOfLeds =  (sizeof(ledPins) / sizeof(ledPins[0])); // size of Leds

// Track Lengths //
// formula for milliseconds =  (minutes * 60 + seconds) * 1000 = milliseconds //
const unsigned long trackLength[] = {19000,66000,75000,104000,29000,49000,49000,107000,52000,97000,35000,57000,157000,82000,86000,104000,39000,37000,81000,103000,45000,96000,30000,115000};


// array to store the time when button is pressed //
unsigned long timeButtonPressed[numOfButtons] = {0}; 

//for first run code //
bool firstRun[numOfButtons] = {0};

//for accurate fading track //
bool preButtonState[numOfButtons] = {0};

bool buttonState[numOfButtons] = {0};

// to count how many track are currently playing //
int counter = 0;

const int fadeTime = 5000;


// WAV Trigger object //
wavTrigger wTrig;            

//track number//
int  gNumTracks;  

// firmware version//
char gWTrigVersion[VERSION_STRING_LEN]; 


//------------------------------------------//

 
void setup() {

  // starting a commuincation with the serial port //
  
  Serial.begin(9600);
  // setting up the digital pins for the buttons to be an input //
  for (int i = 0; i <  numOfButtons; i++)
  {
    pinMode(buttonPins[i], INPUT);
  }

  // setting up the digital pins for the leds to be an output //
  for (int j = 0; j < numOfLeds; j++)
  {
    pinMode(ledPins[j], OUTPUT);
  }

  delay(1000);

  // WAV Trigger startup at 57600
  wTrig.start();
  delay(10);
 
  // Send a stop-all command and reset the sample-rate offset, in case we have
  // reset while the WAV Trigger was already playing.
  wTrig.stopAllTracks();
  wTrig.samplerateOffset(0);
  
  // Enable track reporting from the WAV Trigger
  wTrig.setReporting(true);
  
  delay(1000);
  
   /* checking bi-directional communication. should be able
   to return the version of the board and number of tracks on the SD card.*/
   
  if (wTrig.getVersion(gWTrigVersion, VERSION_STRING_LEN))
  {
      Serial.print(gWTrigVersion);
      Serial.print("\n");
      gNumTracks = wTrig.getNumTracks();
      Serial.print("Number of tracks = ");
      Serial.print(gNumTracks);
      Serial.print("\n");
  }
  else
  Serial.print("WAV Trigger response not available\n");
    
  Serial.print("\n");  
  Serial.print("Num of Buttons: ");
  Serial.println(numOfButtons);
  Serial.print("\n");   
  Serial.print("Num of Leds: ");
  Serial.println(numOfLeds);
  Serial.print("\n");    


  // print the length of each track //
  for (int i = 0;i < numOfButtons; i++)
  {
    Serial.print("The Length of track number ");
    Serial.print(i+1);
    Serial.print(" is: ");
    Serial.print(trackLength[i]);
    Serial.println(" Milliseconds");
  }

  // set master gain to 0db;
  wTrig.masterGain(0);

}
  
//------ loop ------//
  
void loop()
{
  wTrig.update();
  
  for (int i = 0; i < numOfButtons; i++)
  {
    if (digitalRead(buttonPins[i]) == HIGH)
    {
      if(millis() - timeButtonPressed[i] >= trackLength[i] || firstRun[i] == 0)
      {
        timeButtonPressed[i] = millis(); //storing the time of button pressed
        wTrig.trackPlayPoly(i+1); //play track number i
        Serial.print("Track number ");
        Serial.print(i+1);
        Serial.println(" is playing");
        Serial.println("");
        digitalWrite(ledPins[i],HIGH); // turn on led corresponding to the track that is playing
        buttonState[i] = 1; // store 1 to indicate that the track number i  is currently playing
        counter++; // count how many track playing
        Serial.print("Number of tracks playing: ");
        Serial.print(counter);
        Serial.println("\n");
        firstRun[i] = 1;
        Serial.print("counter: ");
        Serial.println(counter);
      }
    }
    if (millis() > timeButtonPressed[i] + trackLength[i]) // check if the track number i is finished playing
    {
      digitalWrite(ledPins[i],LOW); // if so - turn off led
      if (millis() > timeButtonPressed[i] + trackLength[i] && buttonState[i] == 1) // check if track number i that finisihed was previusly on
      {
        counter--; // if so - reduce 1 from counting
        buttonState[i] = 0; //store 0 for that button state at track index i
           
        Serial.print("Track number ");
        Serial.print(i+1);
        Serial.println(" stopped");
        Serial.println("");
        Serial.print("Number of tracks playing: ");
        Serial.print(counter);
        Serial.println("\n");
      }
    }
    if(buttonState[i] != preButtonState[i])
    {
      for (int i = 0; i < numOfButtons; i++)
      {
    switch (counter)
    {
      case 1:
      wTrig.trackFade(i+1, 0, fadeTime, 0);
      break;
      case 2:
      wTrig.trackFade(i+1, -6, fadeTime, 0);
      break;
      case 3:
      wTrig.trackFade(i+1, -10, fadeTime, 0);
      break;
      case 4:
      wTrig.trackFade(i+1, -12, fadeTime, 0);
      break;
      case 5:
      wTrig.trackFade(i+1, -14, fadeTime, 0);
      break;
      case 6:
      wTrig.trackFade(i+1, -16, fadeTime, 0);
      break;
      case 7:
      wTrig.trackFade(i+1, -17, fadeTime, 0);
      break;
      case 8:
      wTrig.trackFade(i+1, -18, fadeTime, 0);
      break;
      case 9:
      wTrig.trackFade(i+1, -19, fadeTime, 0);
      break;
      case 10:
      wTrig.trackFade(i+1, -20, fadeTime, 0);
      break;
      case 11:
      wTrig.trackFade(i+1, -21, fadeTime, 0);
      break;
      case 12:
      wTrig.trackFade(i+1, -22, fadeTime, 0);
      break;
      case 13:
      wTrig.trackFade(i+1, -22, fadeTime, 0);  
      break;
      case 14:
      wTrig.trackFade(i+1, -24, fadeTime, 0);
      break;
    }
   preButtonState[i] = buttonState[i];
   }
  }
 }
}

Refarding the max I/O current for the Mega, check the datasheet.

The maximum current of the mega is 200 mA .
If each led will drew 20mA and all leds will be ON at the same time it will exceed the maximum current.

I could use a higher resistor value so each LED will not drew more then 10mA so the maximum current drew will be 150mA .

That's the proper way to go! Good!

Would you say drawing only 10mA per led is enough? or better use a led driver with a npn transistor and external power supply for the leds?

OK - I would like to simplify the project:

12 buttons in total. Each button will play an audio file. when pressing different button it will stop the current track that is playing and will play the new track that was pressed so only one track will play at the same time. Is it possible doing it with WavTrigger without arduino?

Ok sorry for being confused. Here is what I'm try to do:

total of 12 tracks.
one button -short press for next song and the long press for play previous song.
12 led - each led will correspond to the current playing track.
no tracks playing at the same time. so if track 1 is playing the rest are off. if the next track is playing the previous is off.

when first starting the arduino counter is 0 and no track are playing.
if track is finished to play the led should go off.

here is where I got:

#include <wavTrigger.h>

// WAV Trigger object //
wavTrigger wTrig; 

//Button//
uint8_t buttonPin = 2;       // uint8_t is an unsigned (positive) 8-bit integer.  Giving the compiler this detail rather than a generic 'byte' helps it treat it as you would expect, resulting in Serial.print not needing that 'DEC' argument.
uint8_t buttonPressCount = 0; // Note an uint8_t stores a number from 0-255, so after 255 the buttonPressCount will go back to 0 again.  If you want to store a larger integer, use uint16_t (0-65535), uint32_t (0-4294967295), or even uint64_t (0-18446744073709551615).
uint8_t PUSHED = 0;
unsigned long timePushed = 0;
uint8_t currentButtonState = HIGH;
uint8_t lastButtonState = HIGH;
uint32_t millisTimePress = 0; // unsigned longs are uint32_t, an unsigned 32 bit integer.


////Leds/////

const int ledPins[] ={4,5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15}; // array of leds pins
const int numOfLeds =  (sizeof(ledPins) / sizeof(ledPins[0])); // size of Leds

uint32_t currentMillis;


void setup() {
  
    pinMode(buttonPin, INPUT_PULLUP);
    
   // setting up the digital pins for the leds to be an output //
  for (int j = 0; j < numOfLeds; j++)
  {
    pinMode(ledPins[j], OUTPUT);
  }

  delay(1000);

  // WAV Trigger startup at 57600
  wTrig.start();
  delay(10);
 

}

void loop() {
  buttonPress ();
  LEDs();

}


void buttonPress ()
{
    byte currentButtonState = digitalRead (buttonPin);
    if (lastButtonState != currentButtonState)  {
        lastButtonState = currentButtonState;
         delay (35);             // debounce


        //******************
        //has the switch been pushed ?
        if (currentButtonState == PUSHED)
        {
           //record the time the switch closed
           timePushed = millis();
          
        }
        //******************
    //switch has been released
    else
    {
      //calculate the time the switch was closed
      timePushed = millis() - timePushed;
      
      if(timePushed < 1800)
      {
        buttonPressCount++;
      }
      
      else if (timePushed > 2000)
      {
        buttonPressCount--;

      }
      
    }
  }
}


void LEDs ()
{
  switch( buttonPressCount)
  case 0:
    for (int i = 0; i <numOfLeds; i++)
    {
      digitalWrite(ledPins[i], LOW);
    }
    break;
    case 1:
    digitalWrite(ledPin[0], HIGH);
    // how to turn all other leds off?
    
     wTrig.trackPlaySolo(1);

    break;
    case 2:
    digitalWrite(ledPin[1], HIGH);
    // how to turn all other leds off?

    wTrig.trackPlaySolo(2);

    break;
    case 3:
    digitalWrite(ledPin[0], HIGH);
    // how to turn all other leds off?

     wTrig.trackPlaySolo(3);
     break;
    case 4:
    digitalWrite(ledPin[1], HIGH);
    // how to turn all other leds off?

    wTrig.trackPlaySolo(4);
    break;
    
}
  
}

I'm not sure if using the case function is the right way?

what happen if song is finished? the counter is stay at position or going back to 0 ?

It depends on the LED and the surrounding light. Make a test with one LED!
Using a transistor, and an external power supply, will of course open for all kinds of light devices.

It looks rather good I think.

That depends on the function playing the song. Is it a blocking function or not?

What do you mean by blocking function?
Here is the wav trigger arduino manual

That is a function that returns once the action is completed. Other functions trigger the start of an action that then is completed in parallell with the execution.
Wav trigger Arduino? Please select the useful piece. It calls for too much time to find whatever You have in mind.

So I have got here:

I mange to fade in each track that is playing and to lit a led corresponding to the track number that is playing.

there is two things I don't manage to do:

  1. to turn off led when track is not playing -
    for the moment even if track x is finished his corresponding led is still ON. I would like that if track is finished the led will get off.

  2. to fade out a track -
    for the moment when I press the button and go to next track - the previous track will stop immediately and the next trac will fade in over x seconds. I would like that if a button was pressed to go to the next track - the currently playing track will fade out and only after that the new track will fade in.

How can I do the above two?
I'm not Sure if my switch case is the right way.

code until now:

#include <wavTrigger.h>
#include <AltSoftSerial.h>    // Arduino build environment requires this


// WAV Trigger object //
wavTrigger wTrig; 

//Button//
uint8_t buttonPin = 2;       // uint8_t is an unsigned (positive) 8-bit integer.  Giving the compiler this detail rather than a generic 'byte' helps it treat it as you would expect, resulting in Serial.print not needing that 'DEC' argument.
uint8_t buttonPressCount = 0;// Note an uint8_t stores a number from 0-255, so after 255 the buttonPressCount will go back to 0 again.  If you want to store a larger integer, use uint16_t (0-65535), uint32_t (0-4294967295), or even uint64_t (0-18446744073709551615).
uint8_t lstbuttonPressCount = 0;
uint8_t PUSHED = 0;
const uint8_t MINBTNCOUNT = 0;
const uint8_t MAXBTNCOUNT = 4;
unsigned long timePushed = 0;
uint8_t currentButtonState = HIGH;
uint8_t lastButtonState = HIGH;
uint32_t millisTimePress = 0; // unsigned longs are uint32_t, an unsigned 32 bit integer.


////Leds/////

const int ledPins[] ={4,5,6,7}; // array of leds pins
const int numOfLeds =  (sizeof(ledPins) / sizeof(ledPins[0])); // size of Leds

uint32_t currentMillis;

int  gNumTracks;              // Number of tracks on SD card

char gWTrigVersion[VERSION_STRING_LEN];    // WAV Trigger version string

void setup() {
  Serial.begin(115200);
  
    pinMode(buttonPin, INPUT_PULLUP);
    
   // setting up the digital pins for the leds to be an output //
  for (int j = 0; j < numOfLeds; j++)
  {
    pinMode(ledPins[j], OUTPUT);
  }

  delay(1000);

  // WAV Trigger startup at 57600
  wTrig.start();
  delay(10);
  
  // Send a stop-all command and reset the sample-rate offset, in case we have
  //  reset while the WAV Trigger was already playing.
  wTrig.stopAllTracks();
  wTrig.samplerateOffset(0);
  
  // Enable track reporting from the WAV Trigger
  wTrig.setReporting(true);
  
  // Allow time for the WAV Trigger to respond with the version string and
  //  number of tracks.
  delay(100); 
  
  // If bi-directional communication is wired up, then we should by now be able
  //  to fetch the version string and number of tracks on the SD card.
  if (wTrig.getVersion(gWTrigVersion, VERSION_STRING_LEN)) {
      Serial.print(gWTrigVersion);
      Serial.print("\n");
      delay(1000);
      gNumTracks = wTrig.getNumTracks();
      Serial.print("Number of tracks = ");
      Serial.print(gNumTracks);
      Serial.print("\n");
  }
  else
      Serial.print("WAV Trigger response not available");
}


void loop() {
  buttonPress ();
  LEDs();

}


void buttonPress ()
{
    byte currentButtonState = digitalRead (buttonPin);
  
    if (lastButtonState != currentButtonState)  {
        lastButtonState = currentButtonState;
         delay (35);             // debounce


        //******************
        //has the switch been pushed ?
        if (currentButtonState == PUSHED)
        {
           //record the time the switch closed
           timePushed = millis();
          
        }
        //******************
    //switch has been released
    else
    {
      //calculate the time the switch was closed
      timePushed = millis() - timePushed;
      
      if(timePushed < 500)
      {
        buttonPressCount++;
        if( buttonPressCount == 0)
  {
    buttonPressCount = 4;
  }
  if( buttonPressCount == 5)
  {
    buttonPressCount = 1;
  }
        Serial.print("button count: ");
        Serial.println(buttonPressCount);
      }
      
      else if (timePushed > 600)
      {
        buttonPressCount--;
        if( buttonPressCount == MINBTNCOUNT)
  {
    buttonPressCount = 4;
  }
  if( buttonPressCount > MAXBTNCOUNT )
  {
    buttonPressCount = 0;
  }
        Serial.print("button count: ");
  Serial.println(buttonPressCount);

      }
      
    }
  }
}


void LEDs ()
{
  if(buttonPressCount != lstbuttonPressCount)
  {
  lstbuttonPressCount = buttonPressCount;
  switch( buttonPressCount)
  {
  case 0:
    digitalWrite(ledPins[0], LOW);
    digitalWrite(ledPins[1], LOW);
    digitalWrite(ledPins[2], LOW);
    digitalWrite(ledPins[3], LOW);
    
    
    break;
    case 1:
    digitalWrite(ledPins[0], HIGH);
    digitalWrite(ledPins[1], LOW);
    digitalWrite(ledPins[2], LOW);
    digitalWrite(ledPins[3], LOW);
    
     wTrig.trackGain(1, -40);  
     wTrig.trackPlaySolo(1);
     wTrig.trackFade(1, -6, 3000, false);

    break;
    case 2:
    digitalWrite(ledPins[0], LOW);
    digitalWrite(ledPins[1], HIGH);
    digitalWrite(ledPins[2], LOW);
    digitalWrite(ledPins[3], LOW);
    // how to turn all other leds off?

     wTrig.trackGain(2, -40);  
     wTrig.trackPlaySolo(2);
     wTrig.trackFade(2, -6, 3000, false);

    break;
    case 3:
      digitalWrite(ledPins[0], LOW);
    digitalWrite(ledPins[1], LOW);
    digitalWrite(ledPins[2], HIGH);
    digitalWrite(ledPins[3], LOW);
    // how to turn all other leds off?

     wTrig.trackGain(3, -40);  
     wTrig.trackPlaySolo(3);
     wTrig.trackFade(3, -6, 3000, false);
     break;
    case 4:
    digitalWrite(ledPins[0], LOW);
    digitalWrite(ledPins[1], LOW);
    digitalWrite(ledPins[2], LOW);
    digitalWrite(ledPins[3], HIGH);
    // how to turn all other leds off?

     wTrig.trackGain(4, -40);  
     wTrig.trackPlaySolo(4);
     wTrig.trackFade(4, -6, 3000, false);
    break;
    
}
  }
  
}

I made an array of variables with trackLengths :


//time translating//
#define sec * 1000
#define min * 60000
#define ms * 1

// Track Lengths //
const unsigned long trackLength[] = {10 sec, 8 sec, 9 sec, 7 sec};

I try to do - turn led on when track is playing - when millis is pass the time of the track the led will be off or if we press the button to go to a different track the led will be also off.

void isPlaying()
{
  if(buttonPressCount != lstbuttonPressCount)
  {
  lstbuttonPressCount = buttonPressCount;
  switch( buttonPressCount)
  {
  case 1:
  if(millis() - timeButtonPressed[0] >= trackLength[0])
  {
  timeButtonPressed[0] = millis();
  wTrig.trackGain(1, -40);  
  wTrig.trackPlaySolo(1);
  wTrig.trackFade(1, -6, 3000, false);
  digitalWrite(ledPins[0],HIGH);
  if (millis() > timeButtonPressed[0] + trackLength[0]) // check if the track number i is finished playing
    {
      digitalWrite(ledPins[0],LOW); // if so - turn off led
    }
    break;
  
  }
}
  }
}

The above isn't working

For a controller to run, code is used like the C language. To describe the flow of the execution, giving the overwiew, certain methods are used. One is Flow Charts. Such should be written befor writing any code. Coding directly with the keyboard is a lot more difficult and calls for a lot of experience. For large projects Flow Charts are neede for future maintenence.
You pile up words, words, words.
I don't take on the time consuming work to penetrate Your code in the near future.

So I try to make it work without the case switch function rather a if statements.

void isPlaying()
{
  if(counter != lstcounter)
  {
    lstcounter = counter;
    if(counter == 1)
    timeButtonPressed[0] = millis();
    Serial.println(timeButtonPressed[0]);
     
    if(millis() - timeButtonPressed[0] <= trackLength[0])
    {
      Serial.print(trackLength[0]);
      digitalWrite(ledPins[0], HIGH);
      wTrig.trackGain(1, -40);  
     wTrig.trackPlaySolo(1);
     wTrig.trackFade(1, -6, 3000, false);
    }
 
  }
   if(millis() > timeButtonPressed[0] +  trackLength[0] || counter != 1 )
    {
     digitalWrite(ledPins[0], LOW);   
    }
}

the above function is working for 1 track. I tried to make it work for more than 1 track without success. Can someone help me to make it work with more than 1 track?

Sure. Produce documentation for the idea, like a car road map but for the flow of the execution.

I'm not sure what is car road map. I will try to explain how I want the system to behave :

I have a 5 audio track. Each with a different length I'm storing in a variable
I also have 5 leds (same as audio tracks number)
I have one button that count presses (short press count up and long press count down)

if button press == 1 :
play track 1;
led 1 is on;
if track 1 is finished and button press is still 1 ( meaning no other presses was detected)
led 1 is off;

if button press != 1 and track 1 is not finished (button was press before track end time) :
led 1 is off;

if button press == 2 :
play track 2;
led 2 is on;
if track 1 is finished and button press is still 2 ( no other presses was detected)
led 2 is off;

etc

edit:
Here is my latest try:


void isPlaying()
{
  for(int i = 0; i < MAXBTNCOUNT; i++)
  {
  if(counter != lstcounter)
  {
    Serial.print("counter:");
    Serial.println(counter);
    lstcounter = counter;
    timeButtonPressed = millis();
    Serial.print("timeButtonPressed:");
    Serial.println(timeButtonPressed);
     
    if(millis() - timeButtonPressed <= trackLength[i])
    {
      Serial.print(trackLength[i]);
      digitalWrite(ledPins[i], HIGH);
      wTrig.trackGain(i+1, -40);  
     wTrig.trackPlaySolo(i+1);
     wTrig.trackFade(i+1, -6, 3000, false);
    }
 
  }
   if(millis() > timeButtonPressed +  trackLength[i] || counter != i+1 )
    {
     digitalWrite(ledPins[i], LOW);   
    }
}
}

I think I'm getting close and yet so far away... :frowning:

That's not the engineering way, adding more and more words. They don't connect at all to the present code. It doesn't help helpers navigate in the code! That's were the "map" thinking comes in. How will anyone get an overview of that code?
Also learn to use comments in the code telling what the intention is. Suppose You want to change Your code, or use it for another purpose some year, or years later. You will not know Your own code.
I'm not prepared to spend time diving into a spagetti of code lines. There are better ways to use free time.
Sorry but I pull down the curtain now.

to be honest we can forget about the above spaghetti. I will organized it.
If simplify the idea what I'm actually try to achieve is

if (counter == 1){ led 1 is on for 10 seconds, all other led are off }
if (counter == 2 ){led 2 is on for 20 seconds, all other led are off }
if (counter == 3 ){led 3 is on for 30 seconds, all other led are off }

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.