Merging 2 sketches: WaveHC lib and LedControl lib

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

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
xl97
 
Posts: 201
Joined: Mon Jul 27, 2009 12:51 pm

Merging 2 sketches: WaveHC lib and LedControl lib

Post by xl97 »

Hi guys..
Figured this might be a good place to post this too since it deals with WaveShield/WaveHC lib..etc..

Pre-face: even though Im trying to use LedControl lib.. an thats not a supported or Adafruit lib.. it could really be ANYTHING.. just being able to do 'other stuff' while audio is playing..

.....................................


having some trouble getting two sketches merged into one.. outside of specific 'code'.... I am just having difficulty grasping all this 'control' (over memory, space, code/events..etc) in C++/micro controller programming still.. (spoiled from exposure to web programming languages..etc)

So outside any specific 'code' help/answers.. any (dumbed up) conversation, explanations are encourage/helpful as well..

ok.. onward. :)


Summary:
Working with WaveHC lib & LedControl library (MAX7219/7221).. separate, work fine.. when trying to merge.. the functions (obviously execute one after another.. instead of both separately/individually/asychronously)

Resources/links:

WaveHC Library: http://code.google.com/p/wavehc/
LedControl Library: http://www.arduino.cc/playground/Main/LedControl#Source


I have a Arduino/Waveshield that I am using to play audio with.... the problem(s) I am having, keep running into is that the audio (while taking a lot of resources/overhead..etc).. seems to keep the code 'busy/locked up'.... because (in the code) Im using 'stuck' inside one of the playAudio() functions.

(if that makes sense?)

From my understanding of how the WaveHC lib works..
I read it use Timer1 to keep things asynchronous... but from usage and looking at the code..etc.. I think the timer set-up and usage if just for constantly checking the array of buttons/switches states..and setting an appropriate 'flag' (variable).....

(I thought the actual audio playback was based on a timer..which allowed the Arduino to be free to run/execute other functions..etc..)

So my new understanding is that if your project calls for it (doesnt need it.. only 1 button for example..whatever).. you dont NEED to setup the timer to call the 'checkSwitches()' function constantly.......correct? (and hence not use Timer1, have no conflict with any Servo stuff?, not affect PWM pin(s)?....etc..etc... is my understanding of this correct?)

--or--

alternately, assign that 'timer' a different/new function (instead of the checkSwitches function it currently calls).. possibly one that handles/controls the LedControl library (MAX7219/7221) I'm trying to merge it?

if I load my sample LedControl sketch.. works fine..
if I load my sample WaveHC (looping audio attempt) sketch....works fine.

If I try to merge both sketches... Im not understanding how I can keep the audio looping (which more or less keep the code inside the

Code: Select all

if(wave.isPlaying){
  //code that executes while loop is playing
}
if I try to put my 'LedControl' code inside that loop.. it obviously only works when the audio is playing... but then is stuck inside the LedControl 'loop' (for animations on the Led Matrix..etc)..and the Aduio doesnt 'loop/start again' until the LedControl 'loop' is complete...

I know this 'makes' sense.. and is really just doing what the code is telling it to do.. Im looking for not only a solution to MY problem.. but general overview discussion on how more advanced coders/developers over come this type of obstacle? Im sure its a pretty common one that beginners like myself run into...

Maybe this is where more advanced knowledge/use of timers & interrupts come into play? My understanding of those is that you cant (shouldnt)really 'do' much inside those functions/routines.. just set some 'flags'.. and exit...let the MAIN loop (or sub routines) handle the newly set flags/variables and act accordingly..... right?

bottom line is .. Im looking to be able to play audio.. whether single sounds/slips.. 'or' looping an audio track.. and be able to do a few other things... change leds states..etc..etc.

hopefully it'll 'click' soon... haha..


**edit: please excuse my code.. and the TONS of comments.. I tend to 'over-do-it' as ithelps me follow along in my code where I am..what is executing.. where its stopping/breaking.. (as well trying new things I have no clue what it will return)


attached are the:
LedControl: breathing demo sketch
WaveHC: looping audio track sketch
Attempted Merge of both above sketches


if there is anything more I can provide.. let me know.

thanks everyone, appreciate all legit advice! :)

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

Re: Merging 2 sketches: WaveHC lib and LedControl lib

Post by adafruit_support_bill »

The programming model that works best for that type of application is an event-driven state machine. You can use timers & interrupts (and libraries based on them) to handle asynchronous events such as playing sounds, changing lights or monitoring input. In your main "void loop()" function, you continually evaluate the state (wave.isPlaying(), button.pressed(), led.on/off etc..) and react to accordingly.

User avatar
pburgess
 
Posts: 4161
Joined: Sun Oct 26, 2008 2:29 am

Re: Merging 2 sketches: WaveHC lib and LedControl lib

Post by pburgess »

WaveHC uses Timer1 for the audio playback (not just buttons), to ensure a steady stream of data to the DAC.

If you look at the PiSpeakHC example, in the playcomplete() function, you'll see this sits in a tight loop waiting for a sound to finish playing:

Code: Select all

  while (wave.isplaying);
...but one's own code is free to do other things, such as polling buttons and getting on with business. The pi code just happens to be written to "block" while there's sound playing.

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

Re: Merging 2 sketches: WaveHC lib and LedControl lib

Post by xl97 »

thanks.. I'll to try and do some searching for this: event-driven state machine

@pburgesss-

oh it IS used for the audio playback? and not just the button state 'watch dog'? (good to know)..

hmm..

I do see the: while(wave.isPlaying) portion..

but 'locking' myself into any sub-routine/loop, I dont think will 'work'..

scenario:

I am playing an audio file in an infinite audio loop.
this means I am '99%' (or whatever) stuck/running inside this while(wave.isPlaying) loop...

so I would have to stick most of my code in there.. (but thats not really feasible/working)..

while sticking code to watch for a button to STOP the aduio or something, might fly/work in there...

updating or looping any LED string animation does not.... Im either:

1.) playing any audio file when the animation loops 'stops'.. and wont loop again until the audio file stops/starts again..
or
2.) the audio file wont restart/loop until the led animation loop has finished/started over again

Im not sure if Im explaining this all correctly? enough to express what is happening, and what my goal/objective is??


if I call say: playFile() or playComplete()... (which has to happen for audio to be played/triggered).. Im stuck in that function/loop forever...

Im failing to understand how putting all my code inside these functions/loops will fix my problem/question.. if the code I need to execute inside these functions 'also' is a running loop (ie: a led strip that constantly breathes/pwm fade up/down? or lights up one after another consecutively?)

In my mind.. then Im stuck inside THAT loop.. which resides inside the parent loop/function...?? which stops the parent function from 'looping'?

crikey!! this is a sticky web we weave! =)

edit:
Does this look like an answer to my problem(s) perhaps?

http://digital-diy.com/general-programm ... hines.html

I havent read it yet.. but seems similar to that what 'support' was eluding to?


thanks

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

Re: Merging 2 sketches: WaveHC lib and LedControl lib

Post by adafruit_support_bill »

I am playing an audio file in an infinite audio loop.
this means I am '99%' (or whatever) stuck/running inside this while(wave.isPlaying) loop...

so I would have to stick most of my code in there.. (but thats not really feasible/working)..
No. You have to 'think outside the loop'. Your code does not have to be inside the 'isplaying' loop. The 'isplaying' test needs to be inside the main loop of your state machine.
Does this look like an answer to my problem(s) perhaps?
I didn't read the article in-depth, but yes, I am talking about a Finite State Machine.

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

Re: Merging 2 sketches: WaveHC lib and LedControl lib

Post by xl97 »

adafruit_support wrote: No. You have to 'think outside the loop'. Your code does not have to be inside the 'isplaying' loop. The 'isplaying' test needs to be inside the main loop of your state machine.
ahh... I see what your saying. (and what pburgess was saying now too).. geez. was I being 'narrow minded' there.. and not thinking out the box (loop)........ (ba dum tisch)

adafruit_support wrote: I didn't read the article in-depth, but yes, I am talking about a Finite State Machine.
thanks.. Im reading it now.. see if helps 'open my eyes'..

I think I need to trim the test/demo project down a bit..

I can 'work' on a FSM type approach and moving code into the MAIN loop using 1 LED on a PWM enabled pin..and fading it up/down.... while playing/looping an audio track.... just the same as lugging around this 60(120) led matrix (and all the extra power sources for everything) for it...


thanks

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

Re: Merging 2 sketches: WaveHC lib and LedControl lib

Post by xl97 »

here is a quick revision of the code.. removing any of the code that was getting me STUCK in the audio playing loop..

I see now that the original WaveHC example already make use of a FSM style approach with the timer/checkSwitches() function.. where it runs through buttons..sets a flag..etc..

I have not begun to implement any LED control into things yet.. (still gotta check out where/how on that)..but first step was to remove the junk getting me stuck... into a more 'proper' way of handling the same 'effect/results'.


suggestions always welcome.

thanks

Code:

Code: Select all


//FSM_attempt_v1.0
//created by: xl97 - [email protected]

/*
This sketch is an attempt to play .wav files usnig the WaveHC
library utilizing an FSM (Finite State Machine) approach
*/
 
 
//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 loopOne =  18;
const int breakLoop =  16;
boolean playLoop = 0;

#define S_IDLE 1
#define S_LEDON 2
#define S_WAITON 3
#define S_LEDOFF 4
#define S_WAITOFF 5
#define S_TURNOFF 6

//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[] = {loopOne, breakLoop};
// 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() {
  //Check loop status and restart if required
  if(playLoop == 1 && !wave.isplaying){ 
    f.rewind();     
    wave.create(f); 
    loopFile("hum3.wav");
  }
  if (justpressed[0]) {
    //reset button var/value to show not pressed
    justpressed[0] = 0;    
    playLoop = 1; //true
    loopFile("hum3.wav"); 
    //playfileLoop("hum2.wav"); 
    //playfileForever("hum2.wav"); 
  } 
  if(justpressed[1]){
    justpressed[1] = 0;
    playLoop = 0; //true
    //conditional check while playing to see if audio should stop.
    putstring_nl("MANUAL LOOP BREAK....."); 
    f.close();
    wave.stop();
  }
  
  //other conditional 'state' checks
  //C&P from FSM example...not implemented yet
  /*
  static int state = S_IDLE; // initial state is 1, the "idle" state.
  static unsigned long ts;  // To store the "current" time in for delays.
  switch(state)
  {
    case S_IDLE:
      // We don't need to do anything here, waiting for a forced state change.
      break;
    case S_LEDON:
      digitalWrite(13,HIGH);  // Turn on the light
      ts = millis();  // Remember the current time
      state = S_WAITON;  // Move to the next state
      break;
    case S_WAITON:
      // If one second has passed, then move on to the next state.
      if(millis() > ts + 1000)
      {
        state = S_LEDOFF;
      }
      break;
    case S_LEDOFF:
      digitalWrite(13,LOW);  // Turn off the light
      ts = millis();  // Remember the current time
      state = S_WAITOFF;
      break;
    case S_WAITOFF:
      // If one second has passed, then go back to state 2.
      if(millis() > ts + 1000)
      {
        state = S_LEDON;
      }
      break;
    case S_TURNOFF:
      // We only get here when forced from outside.
      digitalWrite(13,LOW);  // Turn off the light
      state = S_IDLE;  // Return to the "idle" state.
      break;
    default:
      state = S_IDLE;
      break;
  } 
  */ 
}


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

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

Re: Merging 2 sketches: WaveHC lib and LedControl lib

Post by xl97 »

bump on this.. :)

I didnt want to start a whole new thread..... but took another stab at implementing a simple WaveHC sketch and a LedControl sketch together..

I believe I have the FSM working appropriately...

when I look at serial monitor.. I 'see' the correct things being output/printed..

but the MAX72XX chip does 'nothing'.. (when integrated into the WaveHC sketch..)... where as if I change nothing hardware wise..and and upload a simple MAX722/LedControl sketch (using same pins)... it works fine?

at this point.. Im sorta left believing that there is something INSIDE one/both of these libraries that causes a conflict? (but I think thats a bit above me currently to track down? anyone have some experience with this? been down this road before?.... I'll do some searching for WaveHC & MAX chip projcts.. see if anyone has got them working together.. and how?

anyways.

merged code that plays audio.. does NOTHING when MAX chip is supposed to 'breathe' animation (simple intensity changes..up/down)

Code: Select all

//FSM_attempt_v1.0
//created by: xl97 - [email protected]
/*
This sketch is an attempt to play .wav files usnig the WaveHC
 library utilizing an FSM (Finite State Machine) approach
 */

//import default/needed libraries
#include "LedControl.h"
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"


#define S_IDLE 1
#define S_LEDON 2
#define S_WAITON 3
#define S_LEDOFF 4
#define S_WAITOFF 5

//custom defined variables
const int loopOne =  18;
const int breakLoop =  16;
boolean playLoop = 0;

int fadeValue = 0; //MAX intensity value variable
int animationDelay = 50;

//FSM init vars
static int state = S_IDLE; // initial state is 1, the "idle" state.
static unsigned long ts;  // To store the "current" time in for delays.

//led control
/*
 Now we need a LedControl to work with.
 ***** These pin numbers will probably not work with your hardware *****
 Arduino pin 3 is connected to the DataIn (MAX  pin:1)
 Arduino pin 6 is connected to the CLK (MAX  pin:13)
 Arduino pin 5 is connected to LOAD (MAX  pin:12)
 We have only a single MAX72XX.
 */
//LedControl lc=LedControl(12,11,10,1);
//LedControl lc=LedControl(3, 6, 5, 1);
LedControl lc=LedControl(14, 15, 19, 1);


//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[] = {loopOne, breakLoop};

// 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() {
  
  //MAX 72XX chip set-up
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,15);
  /* and clear the display */
  lc.clearDisplay(0);
  

  
  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
  }

  //sound loop watch dog
  if(playLoop == 1 && !wave.isplaying){ 
    f.rewind();     
    wave.create(f); 
    wave.play();
    //loopFile("hum2.wav");    
  }
}

void loop() {
  //Check loop status and restart if required
  //if(playLoop == 1 && !wave.isplaying){ 
  /*
  if(!wave.isplaying){ 
   f.rewind();     
   wave.create(f); 
   //loopFile("hum3.wav");
   //putstring_nl(".");
   wave.play();
   }
   */
  if (justpressed[0]) {
    //reset button var/value to show not pressed
    justpressed[0] = 0;
    //start led fade
    state = S_LEDON;  
    if(!wave.isplaying){
      playLoop = 1; //true
      loopFile("breath.wav"); 
      //playfileLoop("hum2.wav"); 
      //playfileForever("hum2.wav");      
    }
  } 
  if(justpressed[1]){
    justpressed[1] = 0;
    playLoop = 0; //true
    //conditional check while playing to see if audio should stop.
    putstring_nl("MANUAL LOOP BREAK....."); 
    f.close();
    wave.stop();
    
    //stop led fade
    state = S_IDLE;
  }


  //C&P from FSM example...not implemented yet
  //putstring("STATE STATE: ");
  //Serial.println(state);
  switch(state)
  {
  case S_IDLE:
    // We don't need to do anything here, waiting for a forced state change.
    break;
  case S_LEDON:
    putstring_nl("increase........."); 
    lc.setIntensity(0,fadeValue);
    //analogWrite(ledPin, fadeValue); 
    //digitalWrite(13,HIGH);  // Turn on the light
    ts = millis();  // Remember the current time
    state = S_WAITON;  // Move to the next state
    break;
  case S_WAITON:
    // If one second has passed, then move on to the next state.
    if(millis() > ts + animationDelay)
    {
      if(fadeValue < 15){
        fadeValue++;
        state = S_LEDON;        
      }else{
        state = S_LEDOFF;
      }
    }
    break;
  case S_LEDOFF:
    putstring_nl("decrease........."); 
    lc.setIntensity(0,fadeValue);
    //analogWrite(ledPin, fadeValue); 
    //digitalWrite(13,LOW);  // Turn off the light
    ts = millis();  // Remember the current time
    state = S_WAITOFF;
    break;
  case S_WAITOFF:
    // If one second has passed, then go back to state 2.
    if(millis() > ts + animationDelay)
    {
      if(fadeValue > 0){
        fadeValue--;
        state = S_LEDOFF;        
      }else{
        state = S_LEDON;
      }
    }
    break;
  default:
    state = S_IDLE;
    break;
  } 

}


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




and here is a simple MAX sketch that DOES work just fine.. no change in hardware.. just write different sketch (was testing the max and pins to see if a problem?)

Code: Select all

//We always have to include the library
#include "LedControl.h"

/*
 Now we need a LedControl to work with.
 ***** These pin numbers will probably not work with your hardware *****
 Arduino pin 12 is connected to the DataIn (MAX  pin:1)
 Arduino pin 11 is connected to the CLK (MAX  pin:13)
 Arduino pin 10 is connected to LOAD (MAX  pin:12)
 We have only a single MAX72XX.
 */
//LedControl lc=LedControl(12,11,10,1);
//LedControl lc=LedControl(3, 6, 5,1);
LedControl lc=LedControl(14, 15, 19, 1);


/* we always wait a bit between updates of the display */
unsigned long delaytime=50;
int intensityValue = 0;
boolean loopFade = 1;
void setup() {
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,15);
  /* and clear the display */
  lc.clearDisplay(0);

  //turn on all leds
  /*
  for(int row=0;row<8;row++) {
    lc.setRow(0,row,B11111111);
  }
  */
  //intensityFadeIn();

  //writeArduinoOnMatrix();
  //rows();
  //columns();
  single();
  intensityLoop();
}

/*
 This method will display the characters for the
 word "Arduino" one after the other on the matrix. 
 (you need at least 5x7 leds to see the whole chars)
 */
void writeArduinoOnMatrix() {
  /* here is the data for the characters */
  byte a[5]={
    B01111110,B10001000,B10001000,B10001000,B01111110      };
  byte r[5]={
    B00111110,B00010000,B00100000,B00100000,B00010000      };
  byte d[5]={
    B00011100,B00100010,B00100010,B00010010,B11111110      };
  byte u[5]={
    B00111100,B00000010,B00000010,B00000100,B00111110      };
  byte i[5]={
    B00000000,B00100010,B10111110,B00000010,B00000000      };
  byte n[5]={
    B00111110,B00010000,B00100000,B00100000,B00011110      };
  byte o[5]={
    B00011100,B00100010,B00100010,B00100010,B00011100      };

  /* now display them one by one with a small delay */
  lc.setRow(0,0,a[0]);
  lc.setRow(0,1,a[1]);
  lc.setRow(0,2,a[2]);
  lc.setRow(0,3,a[3]);
  lc.setRow(0,4,a[4]);
  delay(delaytime);
  lc.setRow(0,0,r[0]);
  lc.setRow(0,1,r[1]);
  lc.setRow(0,2,r[2]);
  lc.setRow(0,3,r[3]);
  lc.setRow(0,4,r[4]);
  delay(delaytime);
  lc.setRow(0,0,d[0]);
  lc.setRow(0,1,d[1]);
  lc.setRow(0,2,d[2]);
  lc.setRow(0,3,d[3]);
  lc.setRow(0,4,d[4]);
  delay(delaytime);
  lc.setRow(0,0,u[0]);
  lc.setRow(0,1,u[1]);
  lc.setRow(0,2,u[2]);
  lc.setRow(0,3,u[3]);
  lc.setRow(0,4,u[4]);
  delay(delaytime);
  lc.setRow(0,0,i[0]);
  lc.setRow(0,1,i[1]);
  lc.setRow(0,2,i[2]);
  lc.setRow(0,3,i[3]);
  lc.setRow(0,4,i[4]);
  delay(delaytime);
  lc.setRow(0,0,n[0]);
  lc.setRow(0,1,n[1]);
  lc.setRow(0,2,n[2]);
  lc.setRow(0,3,n[3]);
  lc.setRow(0,4,n[4]);
  delay(delaytime);
  lc.setRow(0,0,o[0]);
  lc.setRow(0,1,o[1]);
  lc.setRow(0,2,o[2]);
  lc.setRow(0,3,o[3]);
  lc.setRow(0,4,o[4]);
  delay(delaytime);
  lc.setRow(0,0,0);
  lc.setRow(0,1,0);
  lc.setRow(0,2,0);
  lc.setRow(0,3,0);
  lc.setRow(0,4,0);
  delay(delaytime);
}

/*
  This function lights up a some Leds in a row.
 The pattern will be repeated on every row.
 The pattern will blink along with the row-number.
 row number 4 (index==3) will blink 4 times etc.
 */
void rows() {
  for(int row=0;row<8;row++) {
    delay(delaytime);
    lc.setRow(0,row,B10100000);
    delay(delaytime);
    lc.setRow(0,row,(byte)0);
    for(int i=0;i<row;i++) {
      delay(delaytime);
      lc.setRow(0,row,B10100000);
      delay(delaytime);
      lc.setRow(0,row,(byte)0);
    }
  }
}

void intensityLoop(){
  while(loopFade == 1){
    //single();
    //for (int n=0; n<5; n++){
      for (int z=0; z<16; z++){
        lc.setIntensity(0,z);
        delay(50);
      }
      for (int z=15; z>-1; --z){
        lc.setIntensity(0,z);
        delay(50);
      }
    //}
  }
}


void intensityFadeIn(){
  byte i;
  while(intensityValue <= 15){
    lc.setIntensity(0,intensityValue);
    delay(delaytime);
    intensityValue++;
  }
  intensityFadeOut();
}
void intensityFadeOut(){
  byte i;
  while(intensityValue >= 15){
    lc.setIntensity(0,intensityValue);
    delay(delaytime);
    intensityValue--;
  }
  intensityFadeIn();
}

/*
  This function lights up a some Leds in a column.
 The pattern will be repeated on every column.
 The pattern will blink along with the column-number.
 column number 4 (index==3) will blink 4 times etc.
 */
void columns() {
  for(int col=0;col<8;col++) {
    delay(delaytime);
    lc.setColumn(0,col,B10100000);
    delay(delaytime);
    lc.setColumn(0,col,(byte)0);
    for(int i=0;i<col;i++) {
      delay(delaytime);
      lc.setColumn(0,col,B10100000);
      delay(delaytime);
      lc.setColumn(0,col,(byte)0);
    }
  }
}

/* 
 This function will light up every Led on the matrix.
 The led will blink along with the row-number.
 row number 4 (index==3) will blink 4 times etc.
 */
void single() {
  for(int row=0;row<8;row++) {
    for(int col=0;col<8;col++) {
      delay(delaytime);
      lc.setLed(0,row,col,true);
      delay(delaytime);
      /*
      for(int i=0;i<col;i++) {
       lc.setLed(0,row,col,false);
       delay(delaytime);
       lc.setLed(0,row,col,true);
       delay(delaytime);
       }
       */
    }
  }
}

void loop() { 
  //writeArduinoOnMatrix();
  //rows();
  //columns();
  //single();
}





Again.. if anyone knows or can point me to what is wrong? or what "I'm" doing wrong...

I appreciate it!.. thanks!!

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

Re: Merging 2 sketches: WaveHC lib and LedControl lib

Post by xl97 »

DUH..

well apparently.. I had 'forgot' to run trough and turn ON the leds first before trying to change the intensity...

QUESTION:

Does anyone know how to initialize all the leds in your 'matrix/strip', but keeping them OFF?

example scenario:

boot up sketch.. it initializes any/all MAX chips.. and all leds on their respected matrix/strips..(whatever).. but keeps them non-lighted.. waiting for an intensity 'loop' to fade them from 0-15..etc.??

it seems even if I start with intensity set at 0.. they are still 'on'.. and then fade from there?

anyways.. to have some sort fo code or solution to this thread..

here is 'working' code...

it loops an audio file (close to seamlessly)..as well as looping/running through the FSM system and updating the led strip..

outside of NOISE I am picking up through the speaker output.. (and Im not sure if thats due to my test/demo set-up? (on bread board..extra stuff.. connected to FTDI/serial for debugging..etc.)

its working as expected. :)

I think it can be trimmed down and the code cleaned up (alot).. but for now it is what it is. :)

//FSM_attempt_v1.0
//created by: xl97 - [email protected]
/*
This sketch is an attempt to play .wav files usnig the WaveHC
 library utilizing an FSM (Finite State Machine) approach
 */

//import default/needed libraries
#include "LedControl.h"
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"


#define S_IDLE 1
#define S_LEDON 2
#define S_WAITON 3
#define S_LEDOFF 4
#define S_WAITOFF 5

//custom defined variables
const int loopOne = 18;
const int breakLoop = 16;
boolean playLoop = 0;

unsigned long delaytime=50;
unsigned long initDelay = 2;
int intensityValue = 15;

//FSM init vars
static int state = S_IDLE; // initial state is 1, the "idle" state.
static unsigned long ts; // To store the "current" time in for delays.

//led control
/*
 Now we need a LedControl to work with.
 ***** These pin numbers will probably not work with your hardware *****
 Arduino pin 3 is connected to the DataIn (MAX  pin:1)
 Arduino pin 6 is connected to the CLK (MAX  pin:13)
 Arduino pin 5 is connected to LOAD (MAX  pin:12)
 We have only a single MAX72XX.
 */
//LedControl lc=LedControl(12,11,10,1);
//LedControl lc=LedControl(3, 6, 5, 1);
LedControl lc=LedControl(14, 15, 19, 1);


//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[] = {loopOne, breakLoop};

// 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() {
  
  //MAX 72XX chip set-up
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,0);
  /* and clear the display */
  //lc.clearDisplay(0);
  

  
  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, INPUT);
    digitalWrite(buttons, 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;
  
  //init leds
  initLeds();
    
}


//--------------------[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
  }

  //sound loop watch dog
  if(playLoop == 1 && !wave.isplaying){
    f.rewind();     
    wave.create(f); 
    wave.play();
    //loopFile("hum2.wav");
  }
}

void loop() {
  //Check loop status and restart if required
  //if(playLoop == 1 && !wave.isplaying){
  /*
  if(!wave.isplaying){ 
   f.rewind();     
   wave.create(f); 
   //loopFile("hum3.wav");
   //putstring_nl(".");
   wave.play();
   }
   */
  if (justpressed[0]) {
    //reset button var/value to show not pressed
    justpressed[0] = 0;
    //start led fade
    state = S_LEDON;  
    if(!wave.isplaying){
      playLoop = 1; //true
      loopFile("breath.wav");
      //playfileLoop("hum2.wav");
      //playfileForever("hum2.wav");
    }
  } 
  if(justpressed[1]){
    justpressed[1] = 0;
    playLoop = 0; //true
    //conditional check while playing to see if audio should stop.
    putstring_nl("MANUAL LOOP BREAK.....");
    f.close();
    wave.stop();
    
    //stop led fade
    state = S_IDLE;
  }


  //C&P from FSM example...not implemented yet
  //putstring("STATE STATE: ");
  //Serial.println(state);
  switch(state)
  {
  case S_IDLE:
    // We don't need to do anything here, waiting for a forced state change.
    break;
  case S_LEDON:
    Serial.println("increase........");
    lc.setIntensity(0,intensityValue);
    ts = millis(); // Remember the current time
    state = S_WAITON;  // Move to the next state
    break;
    
  case S_WAITON:
    // If one second has passed, then move on to the next state.
    if(millis() > ts + delaytime)
    {
      if(intensityValue < 15){
        intensityValue++;
        state = S_LEDON;        
      }else{
        state = S_LEDOFF;
      }
    }
    break;
    
  case S_LEDOFF:
    Serial.println("........decrease");
    lc.setIntensity(0,intensityValue);
    ts = millis(); // Remember the current time
    state = S_WAITOFF;
    break;
    
  case S_WAITOFF:
    // If one second has passed, then go back to state 2.
    if(millis() > ts + delaytime)
    {
      if(intensityValue > 0){
        intensityValue--;
        state = S_LEDOFF;        
      }else{
        state = S_LEDON;
      }
    }
    break;
    
  default:
    state = S_IDLE;
    break;
  }  

}

void initLeds() {
  for(int row=0;row<8;row++) {
    for(int col=0;col<8;col++) {
      lc.setLed(0,row,col,true);
      delay(initDelay);
    }
  }
  //start it off
  //state = S_LEDON;
}

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



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

Return to “Arduino Shields from Adafruit”