Momentary vs. Non-Momentary Push Button

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
rjenn2
 
Posts: 8
Joined: Thu Sep 22, 2022 3:22 pm

Momentary vs. Non-Momentary Push Button

Post by rjenn2 »

I am trying to control multiple LED strips simultaneously with non-momentary buttons. I am basing this code off of the Adafruit neopixel button cycler code. The issue I'm having is either that the button does not respond immediately or that since the code is designed for a momentary button rather than a toggle, you have to switch from on-off-on rather than just off-on in order for the button to change the code. What needs to be changed to set this code up for a non-momentary switch?

I thought this would be simple, but I have not been able to figure it out. Thanks!




Code: Select all

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif


#define BUTTON_PIN1   8
#define BUTTON_PIN2  4

#define PIXEL_PIN1    2  // Digital IO pin connected to the NeoPixels.
#define PIXEL_PIN2   12  // Digital IO pin connected to the NeoPixels.

#define PIXEL_COUNT 4  // Number of NeoPixels

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip1(PIXEL_COUNT, PIXEL_PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(PIXEL_COUNT, PIXEL_PIN2, NEO_GRB + NEO_KHZ800);


boolean oldState1 = LOW;
boolean oldState2 = LOW;
int     mode1     = 0;    // Currently-active animation mode, 0-9
int     mode2     = 0;    // Currently-active animation mode, 0-9

void setup() {
  #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  pinMode(BUTTON_PIN1, INPUT_PULLUP);
  pinMode(BUTTON_PIN2, INPUT_PULLUP);
  strip1.begin(); // Initialize NeoPixel strip object (REQUIRED)
  strip1.show();  // Initialize all pixels to 'off'
  strip2.begin(); // Initialize NeoPixel strip object (REQUIRED)
  strip2.show();  // Initialize all pixels to 'off'
}

void loop() {
  // Get current button state.
  boolean newState1 = digitalRead(BUTTON_PIN1);
  boolean newState2 = digitalRead(BUTTON_PIN2);

   // Check if state changed from high to low (button press).
  if((newState1 == LOW) && (oldState1 == HIGH)) {
    // Short delay to debounce button.
    delay(20);
    // Check if button is still low after debounce.
    newState1 = digitalRead(BUTTON_PIN1);
    if(newState1 == LOW) {      // Yes, still low
      if(++mode1 > 8) mode2 = 0; // Advance to next mode, wrap around after #8
      switch(mode1) {           // Start the new animation...
        case 0:
          colorWipe1(strip1.Color(  0,   0,   0), 50);    // Black/off
          break;
        case 1:
          colorWipe1(strip1.Color(255,   0,   0), 50);    // Red
          break;
        case 2:
          colorWipe1(strip1.Color(  0, 255,   0), 50);    // Green
          break;
        case 3:
          colorWipe1(strip1.Color(  0,   0, 255), 50);    // Blue
          break;
        case 4:
          colorWipe1(strip1.Color(226, 245, 20), 50); // yellow
          break;
        case 5:
          colorWipe1(strip1.Color(29, 138, 42), 50); // darker green
          break;
        case 6:
          colorWipe1(strip1.Color(28, 240, 255), 50); // aqua?
          break;
        case 7:
          colorWipe1(strip1.Color(245, 20, 215), 50); // pink
          break;
        case 8:
          colorWipe1(strip1.Color(242, 174, 15), 50); // orange
          break;
      }
    }
  }

  if((newState2 == LOW) && (oldState2 == HIGH)) {
    // Short delay to debounce button.
    delay(20);

    newState2 = digitalRead(BUTTON_PIN2);
    if(newState2 == LOW) {      // Yes, still low
      if(++mode2 > 8) mode2 = 0; // Advance to next mode, wrap around after #8
      switch(mode2) {           // Start the new animation...
        case 0:
          colorWipe2(strip2.Color(  0,   0,   0), 50);    // Black/off
          break;
        case 1:
          colorWipe2(strip2.Color(255,   0,   0), 50);    // Red
          break;
        case 2:
          colorWipe2(strip2.Color(  0, 255,   0), 50);    // Green
          break;
        case 3:
          colorWipe2(strip2.Color(  0,   0, 255), 50);    // Blue
          break;
        case 4:
          colorWipe2(strip2.Color(226, 245, 20), 50); // yellow
          break;
        case 5:
          colorWipe2(strip2.Color(29, 138, 42), 50); // darker green
          break;
        case 6:
          colorWipe2(strip2.Color(28, 240, 255), 50); // aqua?
          break;
        case 7:
          colorWipe2(strip2.Color(245, 20, 215), 50); // pink
          break;
        case 8:
          colorWipe2(strip2.Color(242, 174, 15), 50); // orange
          break;
      }
    }
  }

  // Set the last-read button state to the old state.
  oldState1 = newState1;
  oldState2 = newState2;
}


void colorWipe1(uint32_t color, int wait) {
  for(int i=0; i<strip1.numPixels(); i++) { // For each pixel in strip...
    strip1.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip1.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

void colorWipe2(uint32_t color, int wait) {
  for(int i=0; i<strip2.numPixels(); i++) { // For each pixel in strip...
    strip2.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip2.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}
Last edited by dastels on Wed Sep 28, 2022 6:23 pm, edited 1 time in total.
Reason: Add code tags

User avatar
dastels
 
Posts: 15653
Joined: Tue Oct 20, 2015 3:22 pm

Re: Momentary vs. Non-Momentary Push Button

Post by dastels »

I don't see anything problematic. How are the buttons wired? One side should be to the pin and the other to ground.

Personally, I would use the debounce library instead of an arbitrary delay to try and debounce the switches, but that's a minor point. If interested see https://www.arduino.cc/reference/en/libraries/bounce2/.

Dave

User avatar
rjenn2
 
Posts: 8
Joined: Thu Sep 22, 2022 3:22 pm

Re: Momentary vs. Non-Momentary Push Button

Post by rjenn2 »

The code works, but since my pushbutton is not momentary, you have to click it twice to initiate a change. If possible, I would like to just have to click the button once instead, but I cannot seem to figure it out.

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

Re: Momentary vs. Non-Momentary Push Button

Post by adafruit_support_bill »

You want to capture any change in state. So change this line:

Code: Select all

  if((newState1 == LOW) && (oldState1 == HIGH))
to this:

Code: Select all

  if(newState1 != oldState1)
And eliminate this condition:

Code: Select all

    if(newState1 == LOW) 
Debouncing in this case is probably not necessary since the colorWipe will likely take longer than any contact bouncing will last.

User avatar
dastels
 
Posts: 15653
Joined: Tue Oct 20, 2015 3:22 pm

Re: Momentary vs. Non-Momentary Push Button

Post by dastels »

The debounce isn't handled by the time spent wiping, but rather the 20 mS delay near the top of the loop. Regardless I find using the Bounce2 library is most useful for the state change methods it provides (rose, fell, & changed) and how it simplifies the code.

Dave

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

Re: Momentary vs. Non-Momentary Push Button

Post by adafruit_support_bill »

The debounce isn't handled by the time spent wiping, but rather the 20 mS delay near the top of the loop.
Right. What I am saying is that the delay is not necessary since the colorWipe itself provides enough delay.

Contact debouncing is a useful (and often essential) technique. But in cases such as this one it is not really necessary.

User avatar
dastels
 
Posts: 15653
Joined: Tue Oct 20, 2015 3:22 pm

Re: Momentary vs. Non-Momentary Push Button

Post by dastels »

I see what you're saying.

Dave

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

Return to “Arduino”