Inserting a 2nd button into a sketch

Hello everyone,
I have an Arduino sketch from Youtube, for running ws2812b Stripes. These are soundcontrolled and the various scenes can be switched by a button: a short press switches scene by scene, a long press activates an automatic switching through mode.
Everything is working well.
However, I'm looking for a way to switch from the party mode to a cozy mode (discreet warm white light, without sound control)
Maybe ther're two ways for doing this:

  1. a specific scene is activated by a second button or
  2. a specific scene (preferably the first) is excluded from automatic mode.

My question is what is the easiest way to do this? Can anyone help?
I basically understand what the program does, but until I get a detailed understanding of c++ to do this little manipulation, I already have a gray beard I think.
Here's the code from: Arduino sound reactive VU meter WS2812B LEDs

// --------------------------------
// -- VU Meter - Scott's version --
// --------------------------------

#include <FastLED.h>
#include <EEPROM.h>
#include <JC_Button.h>

# define LEFT_OUT_PIN 6             // Left channel data out pin to LEDs [6]
# define RIGHT_OUT_PIN 5            // Right channel data out pin to LEDs [5]
# define LEFT_IN_PIN A5             // Left aux in signal [A5]
# define RIGHT_IN_PIN A4            // Right aux in signal [A4]
# define BRIGHTNESS_PIN A2          // Brightness potentiometer in [A2]
# define SENSITIVITY_PIN A1         // Sensitivity potentiometer in [A1]
# define BTN_PIN 3                  // Push button on this pin [3]
# define DEBOUNCE_MS 20             // Number of ms to debounce the button [20]
# define LONG_PRESS 500             // Number of ms to hold the button to count as long press [500]
# define N_PIXELS 18                // Number of pixels in each string [18]
# define MAX_MILLIAMPS 500          // Maximum current to draw [500]
# define COLOR_ORDER GRB            // Colour order of LED strip [GRB]
# define LED_TYPE WS2812B           // LED string type [WS2812B]
# define DC_OFFSET 0                // DC offset in aux signal [0]
# define NOISE 0                    // Noise/hum/interference in aux signal [0]
# define SAMPLES 64                 // Length of buffer for dynamic level adjustment [64]
# define TOP (N_PIXELS + 2)         // Allow dot to go slightly off scale [(N_PIXELS + 2)]
# define PEAK_FALL 20               // Rate of peak falling dot [20]
# define N_PIXELS_HALF (N_PIXELS / 2)
# define PATTERN_TIME 10            // Seconds to show eaach pattern on auto [10]
# define STEREO true                // If true, L&R channels are independent. If false, both L&R outputs display same data from L audio channel [true]

uint8_t volCountLeft = 0;           // Frame counter for storing past volume data
uint16_t volLeft[SAMPLES];               // Collection of prior volume samples
uint16_t lvlLeft = 0;                    // Current "dampened" audio level
uint16_t minLvlAvgLeft = 0;              // For dynamic adjustment of graph low & high
uint16_t maxLvlAvgLeft = 512;

uint8_t volCountRight = 0;          // Frame counter for storing past volume data
uint16_t volRight[SAMPLES];              // Collection of prior volume samples
uint16_t lvlRight = 0;                   // Current "dampened" audio level
uint16_t minLvlAvgRight = 0;             // For dynamic adjustment of graph low & high
uint16_t maxLvlAvgRight = 512;

CRGB ledsLeft[N_PIXELS];
CRGB ledsRight[N_PIXELS];

uint8_t myhue = 0;

void vu4(bool is_centered, uint8_t channel);
void vu5(bool is_centered, uint8_t channel);
void vu6(bool is_centered, uint8_t channel);
void vu7(bool show_background);
void vu8();
void vu9();
void vu10();
void balls();
void fire();
void juggle();
void ripple(boolean show_background);
void sinelon();
void rainbow(uint8_t rate);

// --------------------
// --- Button Stuff ---
// --------------------
uint8_t state = 0;
int buttonPushCounter = 0;
bool autoChangeVisuals = false;
Button modeBtn(BTN_PIN, DEBOUNCE_MS);

void incrementButtonPushCounter() {
  buttonPushCounter = (buttonPushCounter + 1) %16;
  EEPROM.write(1, buttonPushCounter);
}

int sensitivity = 0;

void setup() {
  delay(1000); // power-up safety delay

  analogReference(INTERNAL);

  FastLED.addLeds < LED_TYPE, LEFT_OUT_PIN, COLOR_ORDER > (ledsLeft, N_PIXELS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds < LED_TYPE, RIGHT_OUT_PIN, COLOR_ORDER > (ledsRight, N_PIXELS).setCorrection(TypicalLEDStrip);
  FastLED.setMaxPowerInVoltsAndMilliamps(5, MAX_MILLIAMPS);

  modeBtn.begin();
  Serial.begin(57600);

  buttonPushCounter = 0;
  buttonPushCounter = (int)EEPROM.read(1); // load previous setting
  Serial.print("Starting pattern ");
  Serial.println(buttonPushCounter);
}

void loop() {

  // Read button
  modeBtn.read(); 
  switch (state) {
    case 0:                
      if (modeBtn.wasReleased()) {
        Serial.print("Short press, pattern ");
        Serial.println(buttonPushCounter);
        incrementButtonPushCounter();
        autoChangeVisuals = false;
      }
      else if (modeBtn.pressedFor(LONG_PRESS))
        state = 1;
      break;
    
    case 1:
      if (modeBtn.wasReleased()) {
        state = 0;
        Serial.print("Long press, auto, pattern ");
        Serial.println(buttonPushCounter);
        autoChangeVisuals = true;
      }
      break;
  }
  
  // Switch pattern if on auto
  if(autoChangeVisuals){
    EVERY_N_SECONDS(PATTERN_TIME) { 
      incrementButtonPushCounter();
      Serial.print("Auto, pattern ");
      Serial.println(buttonPushCounter); 
    }
  }

  // Run selected pattern
  switch (buttonPushCounter) {
    case 0:
      vu4(false, 0);
      if (STEREO) vu4(false, 1);
      else copyLeftToRight();
      break;
  
    case 1:
      vu4(true, 0);
      if (STEREO) vu4(true, 1);
      else copyLeftToRight();
      break;
  
    case 2:
      vu5(false, 0);
      if (STEREO) vu5(false, 1);
      else copyLeftToRight();
      break;
  
    case 3:
      vu5(true, 0);
      if (STEREO) vu5(true, 1);
      else copyLeftToRight();
      break;
  
    case 4:
      vu6(false, 0);
      if (STEREO) vu6(false, 1);
      else copyLeftToRight();
      break;
      
    case 5:
      vu7(true);
      copyLeftToRight();
      break;
  
    case 6:
      vu8();
      copyLeftToRight();
      break;
  
    case 7:
      vu9();
      break;
  
    case 8:
      vu10();
      break;
    
    case 9:
      vu7(false);
      copyLeftToRight();
      break;
  
    case 10:
      sinelon();
      break;
  
    case 11:
      balls();
      break;
  
    case 12:
      juggle();
      break;
  
    case 13:
      fire();
      break;
  
    case 14:
      ripple(true);
      break;
  
    case 15:
      rainbow(10);
      break;
  }
  sensitivity = analogRead(SENSITIVITY_PIN);
  FastLED.setBrightness(map(analogRead(BRIGHTNESS_PIN),0,1023,0,255));
  
}

// ------------------
// -- VU functions --
// ------------------

uint16_t auxReading(uint8_t channel) {

  uint16_t height = 0;

  if(channel == 0) {
    int n = analogRead(LEFT_IN_PIN); // Raw reading from left line in
    n = abs(n - 512 - DC_OFFSET); // Center on zero
    n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum
    lvlLeft = ((lvlLeft * 15) + n) >> 4; // "Dampened" reading else looks twitchy (>>3 is divide by 32)
    volLeft[volCountLeft] = n * ((float)(1023 - sensitivity) / 512);
    volCountLeft = (volCountLeft + 1) % SAMPLES;
    // Calculate bar height based on dynamic min/max levels (fixed point):
    height = TOP * (lvlLeft - minLvlAvgLeft) / (long)(maxLvlAvgLeft - minLvlAvgLeft);
  }
  
  else {
    int n = analogRead(RIGHT_IN_PIN); // Raw reading from mic
    n = abs(n - 512 - DC_OFFSET); // Center on zero
    n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum
    lvlRight = ((lvlRight * 15) + n) >> 4; // "Dampened" reading (else looks twitchy)
    volRight[volCountRight] = n * ((float)(1023 - sensitivity) / 512); // Save sample for dynamic leveling
    volCountRight = (volCountRight +1 ) % SAMPLES;
    // Calculate bar height based on dynamic min/max levels (fixed point):
    height = TOP * (lvlRight - minLvlAvgRight) / (long)(maxLvlAvgRight - minLvlAvgRight);
  }
  height = min(height, TOP);
  return height;
}

void copyLeftToRight() {
  for (uint8_t i = 0; i < N_PIXELS; i++) {
    ledsRight[i] = ledsLeft[i];
  }
}

/*
 * Function for dropping the peak
 */
uint8_t peakLeft, peakRight;
void dropPeak(uint8_t channel) {
  
  static uint8_t dotCountLeft, dotCountRight;
 
  if(channel == 0) {
    if(++dotCountLeft >= PEAK_FALL) { //fall rate 
      if(peakLeft > 0) peakLeft--;
      dotCountLeft = 0;
    }
  } else {
    if(++dotCountRight >= PEAK_FALL) { //fall rate 
      if(peakRight > 0) peakRight--;
      dotCountRight = 0;
    }
  }
}

/*
 * Function for averaging the sample readings
 */
void averageReadings(uint8_t channel) {

  uint16_t minLvl, maxLvl;

  // minLvl and maxLvl indicate the volume range over prior frames, used
  // for vertically scaling the output graph (so it looks interesting
  // regardless of volume level).  If they're too close together though
  // (e.g. at very low volume levels) the graph becomes super coarse
  // and 'jumpy'...so keep some minimum distance between them (this
  // also lets the graph go to zero when no sound is playing):
  if(channel == 0) {
    minLvl = maxLvl = volLeft[0];
    for (int i = 1; i < SAMPLES; i++) {
      if (volLeft[i] < minLvl) minLvl = volLeft[i];
      else if (volLeft[i] > maxLvl) maxLvl = volLeft[i];
    }
    if ((maxLvl - minLvl) < TOP) maxLvl = 10;
    
    minLvlAvgLeft = (minLvlAvgLeft * 63 + minLvl) >> 6; // Dampen min/max levels
    maxLvlAvgLeft = (maxLvlAvgLeft * 63 + maxLvl) >> 6; // (fake rolling average)
  }

  else {
    minLvl = maxLvl = volRight[0];
    for (int i = 1; i < SAMPLES; i++) {
      if (volRight[i] < minLvl) minLvl = volRight[i];
      else if (volRight[i] > maxLvl) maxLvl = volRight[i];
    }
    if ((maxLvl - minLvl) < TOP) maxLvl = 10;
    minLvlAvgRight = (minLvlAvgRight * 63 + minLvl) >> 6; // Dampen min/max levels
    maxLvlAvgRight = (maxLvlAvgRight * 63 + maxLvl) >> 6; // (fake rolling average)
  }
}

I'm explicitly not asking for a ready-made solution, but for good and helpful tips to find the right way.

Thanks al lot :slight_smile:

Here is my attempt to do this with a second button. But it doesn't work properly:

...
int run;
int buttonPin;

void setup()
{
....   
run = 0; //starts stopped
   buttonPin = 7; //whatever pin your button is plugged into

   pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
   
   if(digitalRead(buttonPin) == LOW) //funcitons based off of button pulling input pin LOW
   {
      if(run == 0)
      {
          run = 255;
      }
      else
      {
          run = 0;
      }
   }

   if(run > 0)
   {
      //code for only run if button was pressed, stops running when button pressed again, so forth...
   }
}

Your topic was MOVED to its current forum category as it is more suitable than the original

the code recognizing that it is being pressed occurs repeatedly unless the change is state is recognized

byte butState;

    byte but = digitalRead(buttonPin);

    if (butState != but)  {
        butState = but;
        delay (10);     // debounce

        if (LOW == but)
            run = !run;
    }

Many thanks for the quick response.
Today I will try to insert the suggestion sensibly and report later on the result
:slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.