Combining Wave Sheild with Neopixels

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
zara2355
 
Posts: 107
Joined: Tue Jun 18, 2013 6:43 pm

Combining Wave Sheild with Neopixels

Post by zara2355 »

Not entirely sure if this is the right area or if the Neopixel forum would be better, so my apologies if i posted in the wrong area....

What i am trying to do is combine two "starter sketches" as it were, (the strand test for the neoPixels and the "4. Play the wave file only when the button is held down and only once (kind of like a musical keyboard") and have them both come on simultaneously when a momentary button is released and go off when the button is What happens is that on the initial pass the sketch kinda works a little (nothing comes on until i release the button), but if i push it again to try to stop it, no go. I'm going to include the code, but it's probably nothing new to anyone (like i said, basic starter code,) but if anyone has any idea how i can solve this issue, i would be forever grateful. Thanks in advance!

Code: Select all

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

#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(15, 6, NEO_GRB + NEO_KHZ800);


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[] = {14, 15, 16, 17, 18, 19};
// 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() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  
  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
  }
}


void loop() {
  byte i;

  if (justpressed[0]) {
    justpressed[0] = 0;
    
    playfile("elvis.WAV");
    while (wave.isplaying && pressed[0]) {
      //Serial.print(".");
      rainbowCycle(20);
      delay(500);
    }
    wave.stop();  
//strip.setBrightness(1);
  }
  strip.show(); // Initialize all pixels to 'off'
}



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


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if(WheelPos < 170) {
    WheelPos -= 85;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Combining Wave Sheild with Neopixels

Post by adafruit_support_mike »

Your "when to play the file" logic is a little unclear.

If you want the music silent while the button is pressed and playing while the button is released, you can simplify the logic to this:

Code: Select all

    if (( ! wave.isplaying ) && ( pressed[ 0 ] )) {
        playfile("elvis.WAV");
    }
    if (( wave.isplaying ) && ( ! pressed[ 0 ] )) {
        wave.stop();
    }
If you want the music to start playing when the button is released but stop playing on a momentary press, there's a hole in your logic.

In terms of button states, the start condition is a falling edge (the moment 'pressed' changes to 'not pressed'). The stop condition, a momentary push, is a rising edge followed by a falling edge ('not pressed' changes to 'pressed' then changes to 'not pressed' again).

The start condition ends with the button 'not pressed' and the stop condition begins with the button 'not pressed', so those form a logical sequence. The stop condition also ends with the button 'not pressed' though, and you don't have any rules for getting from 'not pressed' back to the start condition.

If you chop the falling edge off the stop condition and just use the rising edge, the logic forms a complete loop. The start condition begins with the button 'pressed' and ends with it 'not pressed', the stop condition starts with the button 'not pressed' and ends with it 'pressed'. Each one begins where the other one ends.

That won't allow you to stop the music with a momentary press though. The music will stop as long as the button is down, but will start up again as soon as the button is released.

You can also normalize the start and stop conditions by renaming them "start at the end of a long press" and "stop at the end of a short press". Start counting time on every rising edge and decide what to do on every falling edge. If the duration of the press was less than some time limit, call it a 'stop' signal. If the duration was longer than the limit, call it a 'start' signal. Then you can compare the start/stop signal to 'wave.isplaying' to decide what to do.

User avatar
zara2355
 
Posts: 107
Joined: Tue Jun 18, 2013 6:43 pm

Re: Combining Wave Sheild with Neopixels

Post by zara2355 »

The music will stop as long as the button is down, but will start up again as soon as the button is released.
Actually, that is exactly what i want it do do. Im making a box where if you open the doors, a button is released and the wave and neopixels start. If you close the door, i want all operations to stop. (Not sure if that clarifies why my code is as messy as it is)

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Combining Wave Sheild with Neopixels

Post by adafruit_support_mike »

In that case, the code above should do what you want.

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

Return to “Arduino Shields from Adafruit”