help with button switches for a ws2812b project

Hi open source cronies,

I am looking for some help! I am working on a project that uses the fastled Library, with an array of 6 ws2812b strips and an uno R3.

Please bear in mind, I am very new to Arduino projects and code but I am also a very curious person, with high hopes of developing my own lighting projects. In the meantime, I am using others code as I am a visual learner, while attempting to investigate and learn as much as I can by going through project code. I am running into a bump in the road, where I cant figure something out!

what I have done thus far, is I have 4 C batteries connected to power on all 6 strips, and the ground connected to the ground on all 6 strips. I have pins 4,5,6,7,8,9 on the duino going to the digital in on each led strip as well. so far so good, but my biggest issue is, I have a lack of understanding how the buttons are connected from this code.

I know that it defines input 1 as pin13 and input 2 as pin 12, but I cant seem to figure out how to connect a button to these pins and get the desired outcome from the code as the buttons I have, seem to have 4 connectors on them.

I am wondering, if anyone has any time to help me with this, can you help review the code and maybe provide me with a pointer on how I can get the buttons connected to this and actually put the code to use with this led array?

also one other thing i dont understand is, the mention of pin3 for the ISR- does something need to be connected to pin 3 as well besides pin12 and pin 13? i appreciate any help of course- Included some of the code below right before the main iteration loop.

#include <Adafruit_NeoPixel.h>
 
 
 
#define COUNT 52
#define TAIL 13
#define INPUT1 13
#define INPUT2 12
 
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip)
Adafruit_NeoPixel strip0 = Adafruit_NeoPixel(COUNT, 4, NEO_GRB + NEO_KHZ400);
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(COUNT, 5, NEO_GRB + NEO_KHZ400);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(COUNT, 6, NEO_GRB + NEO_KHZ400);
Adafruit_NeoPixel strip3 = Adafruit_NeoPixel(COUNT, 7, NEO_GRB + NEO_KHZ400);
Adafruit_NeoPixel strip4 = Adafruit_NeoPixel(COUNT, 8, NEO_GRB + NEO_KHZ400);
Adafruit_NeoPixel strip5 = Adafruit_NeoPixel(COUNT, 9, NEO_GRB + NEO_KHZ400);
 
volatile int mode;
volatile int erased=0;
int lastpos = 0;
int ringarray[5] = {0,0,0,0,0} ;
uint32_t ringcolor[5];
int ringdirection[5]= {0,0,0,0,0};
 
Adafruit_NeoPixel strips[6] = {strip0, strip1, strip2, strip3, strip4, strip5} ;
 
//------------------------------------------
// Setup - initialize ALL THE THINGS...
//------------------------------------------
 
void setup() {
  // Initialize the strips...
  for (int i=0; i<6; i++) {
     strips[i].begin();
  }
  randomSeed(analogRead(0));
  pinMode(INPUT1, INPUT);
  pinMode(INPUT2, INPUT);
  digitalWrite(INPUT1, HIGH);       // turn on pullup resistors
  digitalWrite(INPUT2, HIGH);       // turn on pullup resistors
  Serial.begin(9600);
  attachInterrupt(0, userbutton, RISING);
  mode=6;
}
 
//------------------------------------------
// userbutton - this is an ISR - Interrupt Service Routine - it's called
// whenever someone transitions int.0 RISING (see setup() for the def).  On
// the Uno R3, this must be pin 3.
//------------------------------------------
 
void userbutton() {
  // This debounce routine snarfed from http://forum.arduino.cc/index.php/topic,45000.0.html
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200) {
      mode = mode + 1;
      erased=0;
      if ( mode > 6 ) {
        mode = 0;
      }
     
      // Conditionals based on button input...
      // If button 1 is held down, go right back to idle mode
      // If button 2 is held down, do ${something}
      // If both buttons are held down, do the FLASH animation, then go to the sparkly.
      if (digitalRead(INPUT1) == LOW && digitalRead(INPUT2) == LOW) {
        mode=7;
      } else {
        if (digitalRead(INPUT1) == LOW && digitalRead(INPUT2) == HIGH) {
          mode = 6;
        }
      }
//      Serial.println("Reading values from INPUT1 and INPUT2....");
//      Serial.println(digitalRead(INPUT1));
//      Serial.println(digitalRead(INPUT2));
  }
  last_interrupt_time = interrupt_time;
}

Shawhin:
I have pins 4,5,6,7,8,9 on the duino going to the digital in on each led strip as well.

I hope you have a resistor in line with each data input? Otherwise you run the risk of blowing the first led. +-470Ω will do.

Next time post code here (like told in "How to use the forum"). If it's to big, try to make a MCVE.

And/Or if you found the code somewhere, at least link to it. But on a note, copy pasting code is a terrible way of learning. Bette to read through it, understand every line, and use the concept in your own code.

And if found code uses interrupt (ISR) fo buttons, drop it :wink: ISR is not the right tool for a button. Just read the button and don't use delay's.

So try to make it your project, get straight what YOU want to do. Break it up in as small as possible pieces.

Thanks so much. Appreciate the pointers while I
Am still learning. But I’m really trying to figure out is how to actually connect the two buttons to pens 12 and 13 in terms of connectivity on the board. Here Is the code below Where i Am getting confused- Basically how to get those buttons physically connected to the board and where they connect to

//------------------------------------------
// Setup - initialize ALL THE THINGS...
//------------------------------------------

void setup() {
 // Initialize the strips...
 for (int i=0; i<6; i++) {
    strips[i].begin();
 }
 randomSeed(analogRead(0));
 pinMode(INPUT1, INPUT);
 pinMode(INPUT2, INPUT);
 digitalWrite(INPUT1, HIGH);       // turn on pullup resistors
 digitalWrite(INPUT2, HIGH);       // turn on pullup resistors
 Serial.begin(9600);
 attachInterrupt(0, userbutton, RISING);
 mode=6;
}

//------------------------------------------
// userbutton - this is an ISR - Interrupt Service Routine - it's called
// whenever someone transitions int.0 RISING (see setup() for the def).  On
// the Uno R3, this must be pin 3.
//------------------------------------------

void userbutton() {
 // This debounce routine snarfed from http://forum.arduino.cc/index.php/topic,45000.0.html
 static unsigned long last_interrupt_time = 0;
 unsigned long interrupt_time = millis();
 // If interrupts come faster than 200ms, assume it's a bounce and ignore
 if (interrupt_time - last_interrupt_time > 200) {
     mode = mode + 1;
     erased=0;
     if ( mode > 6 ) {
       mode = 0;
     }
    
     // Conditionals based on button input...
     // If button 1 is held down, go right back to idle mode
     // If button 2 is held down, do ${something}
     // If both buttons are held down, do the FLASH animation, then go to the sparkly.
     if (digitalRead(INPUT1) == LOW && digitalRead(INPUT2) == LOW) {
       mode=7;
     } else {
       if (digitalRead(INPUT1) == LOW && digitalRead(INPUT2) == HIGH) {
         mode = 6;
       }
     }
//      Serial.println("Reading values from INPUT1 and INPUT2....");
//      Serial.println(digitalRead(INPUT1));
//      Serial.println(digitalRead(INPUT2));
 }
 last_interrupt_time = interrupt_time;
}

Two things.

  1. You need to go and read the forum instructions so that you can go back and modify your original post (not re-post it) - using the "More -> Modify" option below the right hand corner of your post - to mark up your code as such using the "</>" icon in the posting window. Just highlight each section of code (or output if you need to post that) from the IDE and click the icon.

In fact, the IDE has a "copy for forum" link to put these markings on a highlighted block for you so you then just paste it here in a posting window. But even before doing that, don't forget to use the "Auto-Format" (Ctrl-T) option first to make it easy to read. If you do not post it as "code" it can as you now see, be quite garbled and is always more difficult to read.

  1. This code uses interrupts. Is is useless for your purpose. You will need proper code. For example:
// Radio Buttons!
const int led1Pin =  3;    // LED pin number
const int button1 =  2;
const int led2Pin =  5; 
const int button2 =  4;
const int led3Pin =  6;
const int button3 =  7;
const int led4Pin =  9;
const int button4 =  8;
char bstate1 = 0;
char bstate2 = 0;
char bstate3 = 0;
char bstate4 = 0;
unsigned long bcount1 = 0; // button debounce timer.  Replicate as necessary.
unsigned long bcount2 = 0;
unsigned long bcount3 = 0;
unsigned long bcount4 = 0;


// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check
// Routines by Paul__B of Arduino Forum
boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) { 
    *marker += interval;    // move on ready for next interval
    return true;       
  } 
  else return false;
}

// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
// Routines by Paul__B of Arduino Forum
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               // Odd states if was pressed, >= 2 if debounce in progress
  case 0: // Button up so far, 
    if (button == HIGH) return false; // Nothing happening!
    else { 
      *butnstate = 2;                 // record that is now pressed
      *marker = millis();             // note when was pressed
      return false;                   // and move on
    }

  case 1: // Button down so far, 
    if (button == LOW) return false; // Nothing happening!
    else { 
      *butnstate = 3;                 // record that is now released
      *marker = millis();             // note when was released
      return false;                   // and move on
    }

  case 2: // Button was up, now down.
    if (button == HIGH) {
      *butnstate = 0;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 1;               // jackpot!  update the state
        return true;                  // because we have the desired event!
      }
      else 
        return false;                 // not done yet; just move on
    }

  case 3: // Button was down, now up.
    if (button == LOW) {
      *butnstate = 1;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 0;               // Debounced; update the state
        return false;                 // but it is not the event we want
      }
      else 
        return false;                 // not done yet; just move on
    }
  default:                            // Error; recover anyway
    {  
      *butnstate = 0;
      return false;                   // Definitely false!
    }
  }
}

void setup() {
  pinMode(led1Pin, OUTPUT);      
  pinMode(button1, INPUT_PULLUP); 
  pinMode(led2Pin, OUTPUT);      
  pinMode(button2, INPUT_PULLUP);      
  pinMode(led3Pin, OUTPUT);      
  pinMode(button3, INPUT_PULLUP);      
  pinMode(led4Pin, OUTPUT);      
  pinMode(button4, INPUT_PULLUP);        
  digitalWrite (led1Pin, LOW);
  digitalWrite (led2Pin, LOW);
  digitalWrite (led3Pin, LOW);
  digitalWrite (led4Pin, LOW);
}

void loop() {
  // Select LED if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
    digitalWrite (led1Pin, HIGH);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, LOW);
    delay(500);
  } 
  // Select LED if button debounced
  if (butndown(digitalRead(button2), &bcount2, &bstate2, 10UL )) {
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, HIGH);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, LOW);
    delay(500);
  } 
  // Select LED if button debounced
  if (butndown(digitalRead(button3), &bcount3, &bstate3, 10UL )) {
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, HIGH);
    digitalWrite (led4Pin, LOW);
    delay(500);
  } 
  if (butndown(digitalRead(button4), &bcount4, &bstate4, 10UL )) {
    // Select LED if button debounced
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, HIGH);
    delay(500);      
  } 
}

Buttons connect between the pin defined for that button, and ground.

thank you Paul for your help and guidance, I have modified my posts to better display the code in rhe correct fashion.

Since my buttons have 4 connectors on the back, I am still having a hard time understanding where the other two connectors would go after I connect 1 of the 4 to ground, and 2/4 to to the pin assigned for the button. where would the third and fourth connectors go from the button?

also, I keep hearing about how interrupts are useless but i dont understand why?

Since my buttons have 4 connectors on the back,

Those buttons have pairs of pins shorting out. The simplest way to use them is just to use two diagonal pins and ignore the other diagonal.

I keep hearing about how interrupts are useless but i dont understand why?

Because an interrupt will call a routine where you have to set a flag to say a button has been pressed. Your code then has at some time to read this flag to see if the button has been pressed. For something as glacially slow as a push button you might just as well read the button pin as read a flag. Where they are useful is if you get a fast pulse that might be over before you get the chance to read the digital pin. So they are useful but not in the context you want to use them in.

Shawhin:
also, I keep hearing about how interrupts are useless but i dont understand why?

A common "newbie" misunderstanding is that an interrupt is a mechanism for altering the flow of a program - to execute an alternate function. Nothing could be further from the truth! :astonished:

An interrupt is a mechanism for performing an action which can be executed in "no time at all" with an urgency that it must be performed immediately or else data - information - will be lost or some harm will occur. It then returns to the main task without disturbing that task in any way though the main task may well check at the appropriate point for a "flag" set by the interrupt.

Now these criteria are in a microprocessor time scale - microseconds. This must not be confused with a human time scale of tens or hundreds of milliseconds or indeed, a couple of seconds. A switch operation is in this latter category and a mechanical operation perhaps several milliseconds; the period of a 6000 RPM shaft rotation is ten milliseconds.

Unless it is a very complex procedure, you would expect the loop() to cycle many times per millisecond. If it does not, there is most likely an error in code planning; while the delay() function is provided for testing purposes, its action goes strictly against effective programming methods. The loop() will be successively testing a number of contingencies as to whether each requires action, only one of which may be whether a particular timing criteria has expired. Unless an action must be executed in the order of microseconds, it will be handled in the loop().

So what sort of actions do require such immediate attention? Well, generally those which result from the computer hardware itself, such as high speed transfer of data in UARTs(, USARTs) or disk controllers.

An alternate use of interrupts, for context switching in RTOSs, is rarely relevant to this category of microprocessors as it is more efficient to write cooperative code as described above.