Noob needs help with buttons

So I have this installation run on an Arduino MKR Zero that has 5 pressure pads (right now I'm simply using push buttons) in a circle, each of which is responsible for the light effects of a LED. The idea is that based on which pad you step on, or on how many pads for that matter, you trigger different effects. My problem is that I have managed to make the program trigger a special effect when two buttons are triggered at the same time but I can't seem to figure out why it doesn't want to work with 3 and 4 (it just triggers the two buttons effect and the third strip is just left in a very confused state). In the 2 button effects, I make sure to check that this only happens when 2 specific buttons are HIGH and all the others LOW, and I have been bumping my head against the wall with this whole multiple things at the same time/no delay state machine way of doing it but I think I need some help.

I am a bit new to this so hope there is anyone that can help. Thank you in advance :slight_smile:

Here is an example of the code for 2 buttons at the same time triggering a 2 button effect:

 // Pad 0 and 1
  if (reading[0] == HIGH && reading[1] == HIGH && reading[2] == LOW && reading[3] == LOW && reading[4] == LOW ) {
    Serial.println("button [0] and [1] pressed");
    twoColors(strip.Color(random(180, 255), 0, random(10, 55)), strip.Color(0, random(180, 255), random(10, 65)));
    twoColors1(strip1.Color(0, random(180, 255), random(10, 65)), strip1.Color(random(180, 255), 0, random(10, 55)));
  }

And here is my attempt at trying to implement the same with 3 buttons:

if (reading[2] == HIGH && reading[3] == HIGH && reading[4] == HIGH && reading[1] == LOW && reading[0] == LOW ) { 
threeColorsA();
}

The only advice till you post your full sketch is to print the values of the elements of the reading array and check the values.

Hi,
Try reading all the buttons at the start of the loop, assigning each button a binary base value to variables.
Then use the variables in switch.. case function.

We need your full code to see how you have setup your buttons.
A schematic would also help.

Tom.. :slight_smile:

So this is the main sketch where I check whether either one of the 5 buttons is pressed. Depending on the combination then it either calls an effect function right away or changes the pattern switch case. It is more or less repeating everything for each pad so I only left out 2 examples per category just to get an idea. I haven't included the sketches for the effects, hope that makes it clearer.

#include <Adafruit_NeoPixel.h>

#define LED0_PIN 2
#define LED1_PIN 3
#define LED2_PIN 5
#define LED3_PIN 6
#define LED4_PIN 7



#define CLOCK_PIN 13
#define BUTTON_NUM 5
//#define STRIPS_NUM 2 

// button 0 -> RED
// button 1 -> GREEN
// button 2 -> BLUE
// button 3 -> YELLOW
// button 4 -> WHITE


int buttonPIN[] = {8, 9, 11, 12, 10}; // also change the number of elements in #define BUTTON_NUM
int reading[BUTTON_NUM];
static int lastReading[BUTTON_NUM];

unsigned long patternInterval = 20 ; // time between steps in the pattern
unsigned long lastUpdate = 0 ; // for millis() when last update occoured
unsigned long intervals [] = { 20, 20, 50, 100 } ; // speed for each pattern
int counter, counter1, counter2, counter3, counter4 = 0;
unsigned long buttonPress, buttonPress1, buttonPress2, buttonPress3, buttonPress4;
unsigned long startButton, startButton1, startButton2, startButton3, startButton4;
unsigned long woohoo;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(180, LED0_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(180, LED1_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(180, LED2_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip3 = Adafruit_NeoPixel(180, LED3_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip4 = Adafruit_NeoPixel(180, LED4_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  // sanity check delay - allows reprogramming if accidently blowing power w/leds
  //delay(2000);

#ifdef _AVR_ATtiny85_
  // This is for Trinket 5V 16MHz
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  // End of trinket special code
#endif

  wipe();
  wipe1();
  wipe2();
  wipe3();
  wipe4();

  for (int i = 0; i < BUTTON_NUM; i++) {
    pinMode(buttonPIN[i], INPUT_PULLUP);
  }

  Serial.begin(9600);
}

void loop() {
  static int pattern, pattern1, pattern2, pattern3, pattern4 = 0;

  for (int i = 0; i < BUTTON_NUM; i++) {
    reading[i] = digitalRead(buttonPIN[i]);
  }
  printReadings();  //prints all readings




  //  ---------------------------------------------------------   3 BUTTONS   ---------------------------------------------

  if (reading[2] == HIGH && lastReading[2] == LOW && reading[3] == HIGH && lastReading[3] == LOW && reading[4] == HIGH && lastReading [4] == LOW ) {
    threeColorsA();
  }

  //  ----------------------------------------------  CHECK COMBINATIONS OF TWO BUTTONS   ------------------------------------


  // Pad 0 and 1
  if (reading[0] == HIGH && reading[1] == HIGH && reading[3] == LOW && reading[4] == LOW && reading[2] == LOW ) {
    Serial.println("button [0] and [1] pressed");
    //    pattern = 4;
    twoColors(strip.Color(random(180, 255), 0, random(10, 55)), strip.Color(0, random(180, 255), random(10, 65)));
    twoColors1(strip1.Color(0, random(180, 255), random(10, 65)), strip1.Color(random(180, 255), 0, random(10, 55)));

  }


  // Pad 1 and 2
  else if (reading[1] == HIGH && reading[2] == HIGH && reading[3] == LOW && reading[4] == LOW && reading[0] == LOW) {
    Serial.println("button [1] and [2] pressed");
    twoColors1(strip1.Color(0, random(180, 255), random(10, 65)), strip1.Color(0, random(10, 65), random(180, 255)));
    twoColors2(strip2.Color(0, random(10, 65), random(180, 255)), strip2.Color(0, random(180, 255), random(10, 65)));
  }



  //  --------------------------------------------  TWO PADS ACROSS  --------------------------------------

  // Pad 0 and 2 - red and blue
  else if (reading[0] == HIGH && reading[2] == HIGH) {
    Serial.println("button [0] and [2] pressed");

    twoColorsZeroTwo(strip.Color(random(180, 255), 0, random(10, 55)), strip.Color(random(10, 55), 0, random(180, 255)));
    twoColorsZeroTwo(strip2.Color(random(10, 55), 0, random(180, 255)), strip2.Color(random(180, 255), 0, random(10, 55)));


  }


  // Pad 0 and 3 - red and yellow
  else if (reading[0] == HIGH && reading[3] == HIGH && reading[2] == LOW && reading[1] == LOW && reading[4] == LOW) {
    Serial.println("button [0] and [3] pressed");

    twoColorsZeroThree(strip.Color(random(180, 255), 0, random(10, 55)), strip.Color(random(140, 255), random(140, 255), 0));
    twoColorsZeroThree( strip3.Color(random(140, 255), random(140, 255), 0), strip3.Color(random(180, 255), 0, random(10, 55)));

  }

  else singleButtonPress_check(); //check for buttons not pressed


  void singleButtonPress_check() {
  if (reading[0] == LOW) {
    // wipe(); //=clear
    blue();
    strip.begin();
    strip.setBrightness(250);
  }

  if (reading[1] == LOW) {
    // wipe1(); //=clear
    blue1();
    strip1.begin();
    strip1.setBrightness(250);

  }
  checkSingleButtonPress();
}

void printReadings() {
  Serial.print("reading[0] = ");
  Serial.print( reading[0]);
  Serial.print("   reading[1] = ");
  Serial.print( reading[1]);
  Serial.print("   lastRd[0] = ");
  Serial.print( lastReading[0]);
  Serial.print("   lastRd[1] = ");
  Serial.println( lastReading[1]);

}



  //          ---------------------------------------     STEPPING ON ONE PAD OR JUMPING   ----------------------------------

  //   if activated 3 times in the span of some seconds = jumping

  //          ---------------------------------------------------------   PAD0  ---------------------------------------------------------

  if (lastReading[0] == LOW && reading[0] == HIGH && reading[1] == LOW && reading[2] == LOW && reading[3] == LOW && reading[4] == LOW ) {

    static int lowTime = millis();
    blue();
    if (millis() - lowTime > 2000) {
      wipe();
      blue();
    }
    counter ++;
    buttonPress = millis();
    if (counter == 1) {
      // pattern = 0;
      startButton = millis();
      Serial.println("START");
    }
    // jumping
    if (counter >= 3 && buttonPress - startButton < counter * 200) {
      Serial.println("wohooo");
      pattern = 9;
    }
    if ( counter >= 3 && buttonPress - startButton > counter * 200 ) {
      Serial.println("END");
      counter = 0;
      wipe();
      blue();
      //pattern = 0;

    }
    wipe(); // clear out the buffer
    delay(50); // debounce delay
  }

  //    ---------------------------------------------------------   PAD1  ---------------------------------------------------------

  if (lastReading[1] == LOW && reading[1] == HIGH && reading[2] == LOW && reading[0] == LOW && reading[3] == LOW && reading[4] == LOW ) {

    static int lowTime = millis();
    blue1();
    if (millis() - lowTime > 2000) {
      wipe1();
      blue1();
    }

    counter1 ++;
    buttonPress1 = millis();
    //  pattern1 = 0;
    if (counter1 == 1) {
      startButton1 = millis();
      Serial.println("START1");
    }
    // jumping
    if (counter1 >= 3 && buttonPress1 - startButton1 < 2000 + counter1 * 250) {
      Serial.println("wohooo1");
      pattern1 = 10;
    }

    if ((counter1 >= 3 && buttonPress1 - startButton1 > 2000 + counter1 * 250 ) ) { // || millis() - woohoo > 2000
      Serial.println("END1");
      counter1 = 0;
      //  pattern1 = 0;

    }
    wipe1(); // clear out the buffer
    delay(50); // debounce delay
  }


  // stop flickering after some time (applies for all strips)
  if ((pattern == 9 || pattern == 10 || pattern == 11 || pattern == 12 || pattern == 13) && millis() - buttonPress >  1000  ) {
    Serial.println("georgei");
    // pattern = 0;
    counter = 0;
  }
  if ((pattern1 == 9 || pattern1 == 10 || pattern1 == 11 || pattern1 == 12 || pattern1 == 13) && millis() - buttonPress1 >  1000  ) {
    // pattern1 = 0;
    counter1 = 0;
  }

  for (int i = 0; i < BUTTON_NUM; i++) {
    lastReading[i] = reading[i]; // save for next time
  }


  if (lastReading[0] == HIGH || millis() - buttonPress > 50) updatePattern(pattern);
  if (lastReading[1] == HIGH || millis() - buttonPress1 > 50) updatePattern1(pattern1);

And this function, that is only used to switch between the effects for stepping on a pad vs jumping on it.

void  updatePattern(int pat) { // call the pattern currently being created
  switch (pat) {
    case 0: // Idle state
      colorWipe(strip.Color(200, 0, 0));
      break;

    // CASES FOR JUMPING
    case 9: // button 0
      Sparkle(255, 0, 0);
      Sparkle(random(180, 230), 0, random(10, 100));
      break;
  }
}


void  updatePattern1(int pat) { // call the pattern currently being created
  switch (pat) {
    case 0: // Idle state
      colorWipe1(strip1.Color(10, 125, 0));       // green
      break;

    // CASES FOR JUMPING
    case 10: // button 1
      Sparkle1(0, 255, 0);
      Sparkle1(random(10, 50), random(180, 230), random(80, 150));
      break;
  }
}

First indication of a problem is missing }. E.g. void singleButtonPress_check() { is inside loop().

This means that your code is incomplete (maybe just the }, maybe more). Post complete code; if over 9000 character, attach.

Hi,
Can I suggest you assign each button a value.
Button[0] = 1
Button[1] = 2
Button[2]= 4
Button[3] = 8
Button[4] =16.

Then you read all the buttons and add the vales of the ON buttons together.
This number will be unique to that button combination.
A value of "0" means no button pressed and the current "pressed" value is used.

Then use switch .. case with the value calculated to select the pattern required.

Tom... :slight_smile:

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