Noob: Toggle Switch for LED and .WAV (Cursed Loop!)

Edit:
New Plea:

If anyone else knows how to do this, please chime in. I am sure there is one man or woman in the world (at least!) who has used a toggle switch to switch between two program loops (that only execute once at the time of the state change). I will try to simplify my goals as much as possible to make a solution easy to achieve.

Mode 1 - Switched ON
execute playcomplete();
digitalWrite(LED, HIGH);
wait until mode 2 activated
x1

Mode 2 - Switched OFF
execute playcomplete();
digitalWrite(LED, LOW);
wait until mode 1 activated
x1


Variable Progression

PIN - HIGH; VAR - LOW (State 1)
Mode 1 Init

PIN - HIGH; VAR - HIGH (Middle State, nothing happens)
While Mode 1

PIN - LOW; VAR - HIGH (State 2)
Mode 2 Init

PIN - LOW; VAR - LOW (Middle State, nothing happens)
While Mode 2

Here is what I have thus far:

    int buttonState = LOW;
    int newbuttonState = HIGH; 

void setup() {
    pinMode(6, INPUT);
    pinMode(7, OUTPUT);


void loop() {
        buttonState = digitalRead(6);                                     // Checks the switch for it's current position
        if (buttonState == HIGH && newbuttonState == LOW) {  // Requires switch to be ON, and it's previous position to be OFF.
        digitalWrite(7, HIGH);                                               // LED on
        playcomplete("act.wav");                                           // Play .WAV file
        newbuttonState = HIGH;                                            // Sets the variable into it's ON position
      }
    
      else if (buttonState == LOW && newbuttonState== HIGH) { // Requires switch to be off, and it's previous position to be ON.
        digitalWrite(7, LOW);                                                  // LED off
        playcomplete("deact.wav");                                          // Play .Wav file
        newbuttonState = LOW;                                              // Sets the variable into it's OFF position 
      }
    
  }

Please feel free to edit and add to my code and repaste up here. This is driving me nuts as It's so simple and I need to get past it to progress with my project. :c Please... pleasee cry for help

Anyone brilliant around here?
-Blake

Greetings,

I dearly hope this is in the right section... I have searched these forums and the google several times and due to my silly distraught mind can not find the solution to my problem...

I am attempting to use a toggle switch to engage one of two modes. When the switch is turned on, mode 1 is engaged and an led turns on complimented by an activation message (wave shield). When the switch is turned off, mode 2 is engaged and an led turns off comp'd by a deactivation message.

I am sure this is truly a simple thing, but for the life of me I am stuck and in dire need of support.

Here is my current sketch, as you may immediately notice, I am either caught in a constant loop of block 1 and block 2, or only block 2, depending on the switch state.

Pleaseth helpeth me,
-Blake

    #include <FatReader.h>
    #include <SdReader.h>
    #include <avr/pgmspace.h>
    #include "WaveUtil.h"
    #include "WaveHC.h"
    
    int buttonState = 0;  
     
     
    SdReader card; // This object holds the information for the card
    FatVolume vol; // This holds the information for the partition on the card
    FatReader root; // This holds the information for the filesystem on the card
    FatReader f; // This holds the information for the file we're play
     
    WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time
     
    #define DEBOUNCE 100 // button debouncer
     
    // 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() {
    // set up serial port
    Serial.begin(9600);
    putstring_nl("WaveHC with 6 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(6, INPUT);
    pinMode(7, OUTPUT);
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    // pin13 LED
    pinMode(13, OUTPUT);
    // enable pull-up resistors on switch pins (analog inputs)
    digitalWrite(14, HIGH);
    digitalWrite(15, HIGH);
    digitalWrite(16, HIGH);
    digitalWrite(17, HIGH);
    digitalWrite(18, HIGH);
    digitalWrite(19, 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!");
    }
     
    void loop() {
      buttonState = digitalRead(6);
    
    if (buttonState == HIGH) {
      digitalWrite(7, HIGH);
      playcomplete("act.wav");
    }
    
    else {
      digitalWrite(7, LOW);
      playcomplete("deact.wav");
    }
    
  }
   

    
     
    byte check_switches()
    {
    static byte previous[6];
    static long time[6];
    byte reading;
    byte pressed;
    byte index;
    pressed = 0;
     
    for (byte index = 0; index < 6; ++index) {
    reading = digitalRead(14 + index);
    if (reading == LOW && previous[index] == HIGH && millis() - time[index] > DEBOUNCE)
    {
    // switch pressed
    time[index] = millis();
    pressed = index + 1;
    break;
    }
    previous[index] = reading;
    }
    // return switch number (1 - 6)
    return (pressed);
    }
     
     
    // 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();
    }

Easy. Your sketch is detecting the current state of the switch. What you want it to do is to pick up when that state changes, and only do anything when it sees a change. The line "buttonState = digitalRead (6);" is loosing the previous state by over-writing it with the new one before any checks can be done. Change that line to "int newButtonState = digitalRead (6);". Then, in your if statement, change "HIGH" to "LOW" and add in a second condition "&& newButtonState == HIGH". In the else statement, check for "if (newButtonState== LOW)". Don't forget to update the buttonState afterwards.

Paul

I will be posting the revised code incase anyone is silly and down on their fortune enough to come across this issue.
Is this correct good sir? Do note by changing the var name I no longer have a declared var for buttonState.

      int newbuttonState = digitalRead(6);

void loop() {
    
      if ([color=red]buttonState[/color] == LOW && newButtonState == HIGH) {
        digitalWrite(7, HIGH);
        playcomplete("act.wav");
      }
    
      else if (newButtonState== LOW){
        digitalWrite(7, LOW);
        playcomplete("deact.wav");
      }
    
  }

Ygad, no, I do not think that will work. Hast thou tested it? I did not say to change the name of the var. Why has the digitalRead() moved outside loop ()? What does init () look like now? Recommend you step back to your original and give my suggestion another try, err... forsooth.

Paul.

P.S. I missed something: The else if should also test && buttonState == HIGH

I hath not tested it, no, for I felt there was too much amiss within me. Here is a second attempt, wherefore I be not sure where thee saw digitalRead outside the loop.

Original Code (some snips removed for space constraints):

#include <FatReader.h>
    #include <SdReader.h>
    #include <avr/pgmspace.h>
    #include "WaveUtil.h"
    #include "WaveHC.h"
    
    int buttonState = 0;  
     
     
    SdReader card; // This object holds the information for the card
    FatVolume vol; // This holds the information for the partition on the card
    FatReader root; // This holds the information for the filesystem on the card
    FatReader f; // This holds the information for the file we're play
     
    WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time
     
    #define DEBOUNCE 100 // button debouncer
 
     
     
    void setup() {
    // set up serial port
    Serial.begin(9600);
    putstring_nl("WaveHC with 6 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(6, INPUT);
    pinMode(7, OUTPUT);
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    // pin13 LED
    pinMode(13, OUTPUT);
    // enable pull-up resistors on switch pins (analog inputs)
    digitalWrite(14, HIGH);
    digitalWrite(15, HIGH);
    digitalWrite(16, HIGH);
    digitalWrite(17, HIGH);
    digitalWrite(18, HIGH);
    digitalWrite(19, 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!
    }
     
    void loop() {
      buttonState = digitalRead(6);
    
    if (buttonState == HIGH) {
      digitalWrite(7, HIGH);
      playcomplete("act.wav");
    }
    
    else {
      digitalWrite(7, LOW);
      playcomplete("deact.wav");
    }
   }

Revised(?) Code:

#include <FatReader.h>
    #include <SdReader.h>
    #include <avr/pgmspace.h>
    #include "WaveUtil.h"
    #include "WaveHC.h"
    
    int buttonState = 0;
    int newbuttonState = digitalRead(6);  
     
     
    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 100 // button debouncer
     
    // 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() {
    // set up serial port
    Serial.begin(9600);
    putstring_nl("WaveHC with 6 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(6, INPUT);
    pinMode(7, OUTPUT);
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    // pin13 LED
    pinMode(13, OUTPUT);
    // enable pull-up resistors on switch pins (analog inputs)
    digitalWrite(14, HIGH);
    digitalWrite(15, HIGH);
    digitalWrite(16, HIGH);
    digitalWrite(17, HIGH);
    digitalWrite(18, HIGH);
    digitalWrite(19, 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!");
    }
     

   void loop() {
    
      if (buttonState == LOW && newButtonState == HIGH) {
        digitalWrite(7, HIGH);
        playcomplete("act.wav");
      }
    
      else if (newButtonState== LOW && buttonState == HIGH){
        digitalWrite(7, LOW);
        playcomplete("deact.wav");
      }
    
  }
   

    
     
    byte check_switches()
    {
    static byte previous[6];
    static long time[6];
    byte reading;
    byte pressed;
    byte index;
    pressed = 0;
     
    for (byte index = 0; index < 6; ++index) {
    reading = digitalRead(14 + index);
    if (reading == LOW && previous[index] == HIGH && millis() - time[index] > DEBOUNCE)
    {
    // switch pressed
    time[index] = millis();
    pressed = index + 1;
    break;
    }
    previous[index] = reading;
    }
    // return switch number (1 - 6)
    return (pressed);
    }
     
     
    // 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();
    }

A little better, but still no cigar. There is still no digitalRead () anywhere in loop (), and you forgot the thing I said not to forget.

Old Message:

I completely forgot how to refresh a variable (the thing you told me not to forget). Now do I put the digitalRead at the beginning of the loop to do this?

Edit: I remember now. You digitalRead it and store it with '='

New Plea:

If anyone else knows how to do this, please chime in. I am sure there is one man or woman in the world (at least!) who has used a toggle switch to switch between two program loops (that only execute once at the time of the state change). I will try to simplify my goals as much as possible to make a solution easy to achieve.

Mode 1 - Switched ON
execute playcomplete();
digitalWrite(LED, HIGH);
wait until mode 2 activated
x1

Mode 2 - Switched OFF
execute playcomplete();
digitalWrite(LED, LOW);
wait until mode 1 activated
x1


Variable Progression

PIN - HIGH; VAR - LOW (State 1)
Mode 1 Init

PIN - HIGH; VAR - HIGH (Middle State, nothing happens)
While Mode 1

PIN - LOW; VAR - HIGH (State 2)
Mode 2 Init

PIN - LOW; VAR - LOW (Middle State, nothing happens)
While Mode 2

Here is what I have thus far:

    int buttonState = LOW;
    int newbuttonState = HIGH; 

void setup() {
    pinMode(6, INPUT);
    pinMode(7, OUTPUT);


void loop() {
        buttonState = digitalRead(6);                                     // Checks the switch for it's current position
        if (buttonState == HIGH && newbuttonState == LOW) {  // Requires switch to be ON, and it's previous position to be OFF.
        digitalWrite(7, HIGH);                                               // LED on
        playcomplete("act.wav");                                           // Play .WAV file
        newbuttonState = HIGH;                                            // Sets the variable into it's ON position
      }
    
      else if (buttonState == LOW && newbuttonState== HIGH) { // Requires switch to be off, and it's previous position to be ON.
        digitalWrite(7, LOW);                                                  // LED off
        playcomplete("deact.wav");                                          // Play .Wav file
        newbuttonState = LOW;                                              // Sets the variable into it's OFF position 
      }
    
  }

Please feel free to edit and add to my code and repaste up here. This is driving me nuts as It's so simple and I need to get past it to progress with my project. :c Please... pleasee cry for help

Anyone brilliant around here?
-Blake

No one? Not one soul who dares assist a newb? Maychance even giving him a snippet of code? No one? Truly? :frowning:

Shall wait

I think you are a few tiny changes away from having it working now. You can figure this out! These are important programming/debugging skills you are learning now, don't miss out by letting someone give you the answer on a plate.

Focus on your two button state variables. Where are they first set, and where to they change. Mentally follow the route through the sketch when it executes.

Paul

P.S. thanks for dropping the Shakespere.

Haha, sure thing Paul. When I get stressed out I start speaking in ye olde tongue-

While I agree this shall certainly help me gain a few XP I learn best by example. With this said, however, I too believe I am very close! Perhaps you can give me a small hint? :slight_smile:

I'm getting stuck in one of the if loops when what I really want it to do is exit the loop to check the state of the switch once more such that it can enter a new if loop depending on the change.

Edit:
I can confirm this code works perfectly for the task at hand, if only I had caught the loose connection between the switch and the wave shield (I soldered myself) sooner. Thank you greatly for your aid Paul. I shall leave this code up should anyone new stumble along and hope to find a similar solution. Perhaps I should spoiler wrap it for those trying to learn it on their own. ^^

int Led = 9;
int Switch = 6;
int SwitchState = LOW;
int prevSwitchState = HIGH;

void setup(){
  pinMode(Led, OUTPUT);
  pinMode(Switch, INPUT);
  Serial.begin(9600); 
}

void loop() {
  
  SwitchState = digitalRead(Switch);
  
  while (SwitchState == HIGH && prevSwitchState == LOW) {
    digitalWrite (Led, HIGH);
    delay(1000);
    Serial.println("Mode 1 Activated");
    prevSwitchState = HIGH;

  }
  
  while (SwitchState == LOW && prevSwitchState == HIGH) {
    digitalWrite (Led, LOW);
    delay(1000);
    Serial.println("Mode 2 Activated");
    prevSwitchState = LOW;
  }
  
  while (SwitchState == LOW && prevSwitchState == LOW) {
    digitalWrite (Led, LOW);
    delay(1000);
    Serial.println("Mode 2");
    SwitchState = digitalRead(Switch);
    break;
  }
  
  while (SwitchState == HIGH && prevSwitchState == HIGH) {
    digitalWrite (Led, HIGH);
    delay(1000);
    Serial.println("Mode 1");
    break;
  }
}

Well done, you cracked it!

If you want some tips making it slick and efficient, just ask.

Paul