Using several buttons to map to different routines

Well, just when you think you start to get a grasp, things seem to continue to slip through your fingers. I have been 2 weeks at this, trying dozens of code snippets trying to stack something together that works. By the end, I need to run some LED strips that will change on button inputs, but for now, I just want to work out the logic. I have a working code of a loop, but I need to break that up into smaller segments. First I was using FastLED, but I never really had any break through once I started to integrate portions together. Then I switched to NeoPixel, to see if it was more forgiving. I can introduce my loop later, but for now, let me post 2 codes and see if you can see if I am anywhere close to making these work. Bear in mind, I want to run animated loops later if I can jump in and out of these. I'll post the codes separately:

// Libraries:
//--------------------------------------------------------------------------------
#include <Adafruit_NeoPixel.h>
#define PIN 2
#define NUM_LEDS 144
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

//--------------------------------------------------------------------------------

//Global Constants:

const int in46 = 46;
const int in48 = 48;
const int in50 = 50;
const int in52 = 52;

//--------------------------------------------------------------------------------

//Global Variables:

int in46Val = 0;
int in48Val = 0;
int in50Val = 0;
int in52Val = 0;

int signalState = 0;
int signalAnim = 2;
int delaySignalAnim = 1;
int delaySignalOff = 250;
unsigned long currentMillis = 0; 
unsigned long previousMillis = 0;

//--------------------------------------------------------------------------------

// Setup Code, to run once:

void setup() {

  pinMode(in46, INPUT_PULLUP);
  pinMode(in48, INPUT_PULLUP);
  pinMode(in50, INPUT_PULLUP);
  pinMode(in52, INPUT_PULLUP);          // Simply pull to ground

  strip.begin();
  strip.show();                         // Initialize all pixels to 'off'
  strip.setBrightness(255);              // Set BRIGHTNESS (max = 255)
}

//--------------------------------------------------------------------------------

//Main Code, to run repeatedly:

void loop() {
  in46Val = digitalRead(in46);
  in48Val = digitalRead(in48);
  in50Val = digitalRead(in50);
  in52Val = digitalRead(in52);

  if ( (digitalRead (in46) == HIGH) && 
       (digitalRead (in48) == HIGH) && 
       (digitalRead (in50) == HIGH) &&
       (digitalRead (in52) == HIGH))               //condition 0
     {
       program0();
     }
     
  if ( (digitalRead (in46) == LOW) && 
       (digitalRead (in48) == HIGH) && 
       (digitalRead (in50) == HIGH) &&
       (digitalRead (in52) == HIGH))               //condition 1
     {
       program1();
     }

  if ( (digitalRead (in46) == HIGH) && 
       (digitalRead (in48) == LOW) && 
       (digitalRead (in50) == HIGH) &&
       (digitalRead (in52) == HIGH))               //condition 2
     {
       program2();
     }

  if ( (digitalRead (in46) == HIGH) && 
       (digitalRead (in48) == HIGH) && 
       (digitalRead (in50) == LOW) &&
       (digitalRead (in52) == HIGH))               //condition 3
     {
       program3();
     }

  if ( (digitalRead (in46) == HIGH) && 
       (digitalRead (in48) == HIGH) && 
       (digitalRead (in50) == HIGH) &&
       (digitalRead (in52) == LOW))              //condition 4
     {
       program4();
     }
}

//--------------------------------------------------------------------------------

//Sub Routines:

//----------------------------------------0----------------------------------------

void program1() {

  strip.begin();                                     // Off
  strip.show();
  }
  
//----------------------------------------1----------------------------------------

void program1() {

  colorWipe(strip.Color(255,   0,   0), 50);        // Red
  strip.show();
  }

//----------------------------------------2----------------------------------------

void program2() {

  colorWipe(strip.Color(255,   255,   0), 50);       // Yellow
  strip.show();
  }

//----------------------------------------1----------------------------------------

void program3() {

  colorWipe(strip.Color(  0, 255,   0), 50);        // Green
  strip.show();
  }

//----------------------------------------2----------------------------------------

void program4() {

  colorWipe(strip.Color(  0,   0, 255), 50);        // Blue
  strip.show();
  }

//--------------------------------------------------------------------------------
// The End
// Libraries:
//--------------------------------------------------------------------------------
#include <Adafruit_NeoPixel.h>
#define PIN 2
#define NUM_LEDS 144
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

//--------------------------------------------------------------------------------

//Global Constants:

const int in46 = 46;
const int in48 = 48;
const int in50 = 50;
const int in52 = 52;

//--------------------------------------------------------------------------------

//Global Variables:

int in46Val = 0;
int in48Val = 0;
int in50Val = 0;
int in52Val = 0;

int signalState = 0;
int signalAnim = 2;
int delaySignalAnim = 1;
int delaySignalOff = 250;
unsigned long currentMillis = 0; 
unsigned long previousMillis = 0;

//--------------------------------------------------------------------------------

// Setup Code, to run once:

void setup() {

  pinMode(in46, INPUT_PULLUP);
  pinMode(in48, INPUT_PULLUP);
  pinMode(in50, INPUT_PULLUP);
  pinMode(in52, INPUT_PULLUP);          // Simply pull to ground

  strip.begin();
  strip.show();                         // Initialize all pixels to 'off'
  strip.setBrightness(255);              // Set BRIGHTNESS (max = 255)
}

//--------------------------------------------------------------------------------

//Main Code, to run repeatedly:

void loop() {
  in46Val = digitalRead(in46);
  in48Val = digitalRead(in48);
  in50Val = digitalRead(in50);
  in52Val = digitalRead(in52);

  program0();
  program1();
  program2();
  program3();
  program4();
  
}

//--------------------------------------------------------------------------------

//Sub Routines:

//----------------------------------------0----------------------------------------

void program0() {

  if ( (digitalRead (in46) == HIGH) && 
       (digitalRead (in48) == HIGH) && 
       (digitalRead (in50) == HIGH) &&
       (digitalRead (in52) == HIGH))               //condition 0

  strip.begin();                                     // Off
  strip.show();
  }
  
//----------------------------------------1----------------------------------------

void program1() {

  if ( (digitalRead (in46) == LOW) && 
       (digitalRead (in48) == HIGH) && 
       (digitalRead (in50) == HIGH) &&
       (digitalRead (in52) == HIGH))               //condition 1
       
  colorWipe(strip.Color(255,   0,   0), 50);        // Red
  strip.show();
  }

//----------------------------------------2----------------------------------------

void program2() {

  if ( (digitalRead (in46) == HIGH) && 
       (digitalRead (in48) == LOW) && 
       (digitalRead (in50) == HIGH) &&
       (digitalRead (in52) == HIGH))               //condition 2
  
  colorWipe(strip.Color(255,   255,   0), 50);       // Yellow
  strip.show();
  }

//----------------------------------------3----------------------------------------

void program3() {

  if ( (digitalRead (in46) == HIGH) && 
       (digitalRead (in48) == HIGH) && 
       (digitalRead (in50) == LOW) &&
       (digitalRead (in52) == HIGH))               //condition 3
     {
       program3();
       
  colorWipe(strip.Color(  0, 255,   0), 50);        // Green
  strip.show();
  }

//----------------------------------------4----------------------------------------

void program4() {

  if ( (digitalRead (in46) == HIGH) && 
       (digitalRead (in48) == HIGH) && 
       (digitalRead (in50) == HIGH) &&
       (digitalRead (in52) == LOW))              //condition 4
  
  colorWipe(strip.Color(  0,   0, 255), 50);        // Blue
  strip.show();
  }

//--------------------------------------------------------------------------------
// The End

If you want to react to button inputs whilst running an LED effect then the code must not block the free running of the loop() function. For instance, what does the colorWipe() function do ? If it uses delay() then during the wipe you will not be able to read inputs whilst it runs

I have read 100 posts about millis, and I think it should suffice when the time comes.

101
:smile:

1 Like

Where are you starting your millis() timer? I don't see it. Shouldn't the last line of setup or the first line of loop have something like

unsigned long currentMillis = millis();

I would like to focus on the current code for now. I don't think the current one needs it... or does it?

void program1() {

  strip.begin();                                     // Off
  strip.show();
  }
  
//----------------------------------------1----------------------------------------

void program1() {

  colorWipe(strip.Color(255,   0,   0), 50);        // Red
  strip.show();
  }

Two functions with identical names. Not good.

And here you get the input states into variables but then don't use those variables. ??

in46Val = digitalRead(in46);
  in48Val = digitalRead(in48);
  in50Val = digitalRead(in50);
  in52Val = digitalRead(in52);

  if ( (digitalRead (in46) == HIGH) && 
       (digitalRead (in48) == HIGH) && 
       (digitalRead (in50) == HIGH) &&
       (digitalRead (in52) == HIGH))

Hello digital-id
This is a small example for a button-to-task manager that I´ve found in my box for used sketches. Try it and modify it to your project needs.

/* BLOCK COMMENT
  ATTENTION: This Sketch contains elements of C++.
  https://www.learncpp.com/cpp-tutorial/
  Many thanks to LarryD
  https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
  https://forum.arduino.cc/t/using-several-buttons-to-map-to-different-routines/1003192
  Tested with Arduino: Mega[X] - UNO [ ] - Nano [ ]
*/
#define ProjectName "Using several buttons to map to different routines"
constexpr unsigned long ForTestingOnly {1000}; 
struct BUTTONTASK {
  byte  pin;                 // port pin
  bool  statusQuo;           // current state
  bool  exec;                // execute flag
  void  (*task)();            // pointer to task
};
// extend with forward declaration for  programs 
void test0();
void test1();
// extend this to the project needs buttons vs tasks 
BUTTONTASK buttonTasks[] {
  {A0, false, false, test0},
  {A1, false, false, test1},
};

// --------------- section for serval tasks 
void test0() {
  Serial.println(__func__);
}
void test1() {
  Serial.println(__func__);
}

// -------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  Serial.println(F("."));
  Serial.print(F("File   : ")), Serial.println(__FILE__);
  Serial.print(F("Date   : ")), Serial.println(__DATE__);
  Serial.print(F("Project: ")), Serial.println(ProjectName);
  pinMode (LED_BUILTIN, OUTPUT);  // used as heartbeat indicator
  //  https://www.learncpp.com/cpp-tutorial/for-each-loops/
  for (auto buttonTask : buttonTasks) pinMode(buttonTask.pin, INPUT_PULLUP);
}
void loop () {
  unsigned long currentTime = millis();
  digitalWrite(LED_BUILTIN, (currentTime / 500) % 2);
  for (auto &buttonTask : buttonTasks) {
    int stateNew = !digitalRead(buttonTask.pin);
    if (buttonTask.statusQuo != stateNew) {
      buttonTask.statusQuo = stateNew;
      for (auto &buttonTask : buttonTasks) buttonTask.exec = false;
      buttonTask.exec = true;
    }
    if ( buttonTask.exec)  buttonTask.task(), delay(ForTestingOnly);
  }
}

Have a nice day and enjoy programming in C++ and learning.
Дайте миру шанс!

This will kill your program eventually.

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