How to call functions with button combinations?

I've building a sort of signalling system for a bicycle - using an Arduino Uno to prototype, and a Pro Mini for the final installations. I'm having trouble getting the Arduino to register the button presses. There are two separate libraries being used for two separate applications.

Im using the FastLED library to drive Adafruit Dotstars.

  leds[0].setRGB( 255, 68, 221);
  FastLED.show();
  delay(500);

This works great. I'm able to display patterns fairly well. But Im having trouble with a system so that combinations of button presses call different functions.

For example.

I have 6 buttons - five with 2 states, one with 3states.

lets say when they are all unpressed, after first turning the arduino on, they display a default function. 000000
I have the function set up so that different button presses affect different sections of the image. So I dont have to program complete patterns separately for each combination of buttons (2x2x2x2x2x3)

I started by following a tutorial for button states, but I am unalbe to find a if-else or switch-case that gets the states read.

I will provide some snippets to show you the approach I used so far

  CheckButtonState (BTN_BLINK, BLINKbuttonPushCounter, BLINKbuttonState, BLINKlastButtonState, twostate);

  CheckButtonState (BTN_SIGNAL_LEFT, LSbuttonPushCounter, LSbuttonState, LSlastButtonState, twostate);

  CheckButtonState (BTN_SIGNAL_RIGHT, RSbuttonPushCounter, RSbuttonState, RSlastButtonState, twostate);
  char set_light_mode(int buttonPushCounter)
{

    if ((HLbuttonState       == 0) && 
        (BLINKbuttonState    == 0))
 
 {
        headlightOFF();     
        }   
        
    else if ((HLbuttonState       == 1) && 
        (BLINKbuttonState    == 0))
        {
        headlightLOW();  
        }

    else if ((HLbuttonState       == 2) && 
        (BLINKbuttonState    == 0)) {  
        headlightHIGH();  
        }
void CheckButtonState (int buttonPin, int &buttonPushCounter, int &buttonState, int &lastButtonState, int statenum)
{
  // read the pushbutton input pin:
      buttonState = digitalRead(buttonPin);

      // compare the buttonState to its previous state
      if (buttonState != lastButtonState) 
      {
      // if the state has changed, increment the counter
        if (buttonState == HIGH) 
          {
            // if the current state is HIGH then the button
            // wend from off to on:
            buttonPushCounter++;

            if (buttonPin == BTN_SIGNAL_LEFT)
            {
              CheckSignal(RSbuttonPushCounter);
            }
            if (buttonPin == BTN_SIGNAL_RIGHT)
            {
              CheckSignal(LSbuttonPushCounter);
            }

            //this resets the counter to 0 after the count reaches the number of different modes
            if (buttonPushCounter == statenum)
            {
              buttonPushCounter = 0;
            }
          }
      }
}

Any help would be really really appreciated. Thanks very much!

Hi and welcome.

Could we trouble you for a schematic and the full sketch please?

So far your questions just make me want to ask more questions!

Paul

Absolutely:

#include "FastLED.h"

// How many leds in your strip?
#define NUM_LEDS 24

// For led chips like Neopixels, which have a data line, ground, and power, you just
// need to define DATA_PIN.  For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
#define DATA_PIN 7
#define CLOCK_PIN 6

// Define the array of leds
CRGB leds[NUM_LEDS];

//BRAKE/SIGNAL/HEADLAMP BUTTON STATES

//CONSTANTS://///////////////////////////////////////////////////////////////////////

const int BTN_BLINK = 13;
const int BTN_SIGNAL_LEFT = 12;
const int BTN_SIGNAL_RIGHT = 11;
const int BTN_BRAKE_RIGHT = 10;
const int BTN_BRAKE_LEFT = 9;
const int BTN_LIGHT_ON_DIM_OFF = 8;

const int twostate = 2;
const int threestate = 3;

//VARIABLES:////////////////////////////////////////////////////////////////////////

//HEADLAMP
int HLbuttonPushCounter = 0;   // counter for the number of button presses
int HLbuttonState = 0;         // current state of the button
int HLlastButtonState = 0;     // previous state of the button

//BLINKER
int BLINKbuttonPushCounter = 0;   // counter for the number of button presses
int BLINKbuttonState = 0;         // current state of the button
int BLINKlastButtonState = 0;     // previous state of the button

//LEFT SIGNAL
int LSbuttonPushCounter = 0;   // counter for the number of button presses
int LSbuttonState = 0;         // current state of the button
int LSlastButtonState = 0;     // previous state of the button

//RIGHT SIGNAL
int RSbuttonPushCounter = 0;   // counter for the number of button presses
int RSbuttonState = 0;         // current state of the button
int RSlastButtonState = 0;     // previous state of the button

//BRAKES
int BRAKEstate = 0;

//FUNCTION//PROTOTYPES//////////////////////////////////////////////////////////////////

bool switch_state(int);

void CheckButtonState(int buttonPin, int &buttonPushCounter, int &buttonState, int &lastButtonState, int statenum);

void CheckSignal (int &othersignal);

//SETUP/////////////////////////////////////////////////////////////////////////////////

void setup() {
    
  FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(leds, NUM_LEDS);

  pinMode(BTN_BRAKE_LEFT, INPUT);
  pinMode(BTN_BRAKE_RIGHT, INPUT);
  pinMode(BTN_SIGNAL_RIGHT, INPUT);
  pinMode(BTN_SIGNAL_LEFT, INPUT);
  pinMode(BTN_BLINK, INPUT);
  pinMode(BTN_LIGHT_ON_DIM_OFF, INPUT);
  
  Serial.begin(9600);
  Serial.println("The current button states are as follows:");
  Serial.println("-HL-Bi-LS-RS-BR-");
}

//LOOP//////////////////////////////////////////////////////////////////////////////////

void loop() {
  // put your main code here, to run repeatedly:


  CheckButtonState (BTN_LIGHT_ON_DIM_OFF, HLbuttonPushCounter, HLbuttonState, HLlastButtonState, threestate);

  CheckButtonState (BTN_BLINK, BLINKbuttonPushCounter, BLINKbuttonState, BLINKlastButtonState, twostate);

  CheckButtonState (BTN_SIGNAL_LEFT, LSbuttonPushCounter, LSbuttonState, LSlastButtonState, twostate);

  CheckButtonState (BTN_SIGNAL_RIGHT, RSbuttonPushCounter, RSbuttonState, RSlastButtonState, twostate);

  if ((switch_state(BTN_BRAKE_RIGHT) == true)||(switch_state(BTN_BRAKE_LEFT) == true))
  {
    BRAKEstate = 1;
  }

  else
  {
    BRAKEstate = 0;
  }
  
  
  Serial.print("--");
  Serial.print(HLbuttonPushCounter);
  Serial.print("--");
  Serial.print(BLINKbuttonPushCounter);
  Serial.print("--");
  Serial.print(LSbuttonPushCounter);
  Serial.print("--");
  Serial.print(RSbuttonPushCounter);
  Serial.print("--");
  Serial.print(BRAKEstate);
  Serial.print("--");
  Serial.println(" ");
  
  if ((switch_state(BTN_BLINK) == true)||(switch_state(BTN_BLINK) == true))
  {
    BLINKbuttonState = 1;
  }

  else
  {
    BLINKbuttonState = 0;
  }
  
  
  if(BLINKbuttonState = 1) {
        brakes();
        } 
    else  {   
          foo(); 
          }
          
          
  }
  

}

//FUNCTIONS////////////////////////////////////////////////////////////////////////////
void brakes() {
  // Turn the LED on, then pause
  leds[0] = CRGB::Red;
  FastLED.show();
  delay(500);
  // Now turn the LED off, then pause
  leds[0] = CRGB::Black;
  FastLED.show();
  delay(500);
}

void foo() {
  // Turn the LED on, then pause
  leds[0] = CRGB::Green;
  FastLED.show();
  delay(500);
  // Now turn the LED off, then pause
  leds[0] = CRGB::Black;
  FastLED.show();
  delay(500);
}

//check if power switch is ON, returns true of false
boolean switch_state(int switch_pin)
{
  if (digitalRead(switch_pin) == HIGH)
  {
    return true;
  }
  if (digitalRead(switch_pin) == LOW)
  {
  return false;
  }
  else return false;
}

void CheckButtonState (int buttonPin, int &buttonPushCounter, int &buttonState, int &lastButtonState, int statenum)
{
  // read the pushbutton input pin:
      buttonState = digitalRead(buttonPin);

      // compare the buttonState to its previous state
      if (buttonState != lastButtonState) 
      {
      // if the state has changed, increment the counter
        if (buttonState == HIGH) 
          {
            // if the current state is HIGH then the button
            // wend from off to on:
            buttonPushCounter++;

            if (buttonPin == BTN_SIGNAL_LEFT)
            {
              CheckSignal(RSbuttonPushCounter);
            }
            if (buttonPin == BTN_SIGNAL_RIGHT)
            {
              CheckSignal(LSbuttonPushCounter);
            }

            //this resets the counter to 0 after the count reaches the number of different modes
            if (buttonPushCounter == statenum)
            {
              buttonPushCounter = 0;
            }
          }
      }
}

void CheckSignal (int &othersignal)
{
  if (othersignal == 1)
  {
    othersignal = 0;
  }
}

LetThisNightExplode:
I have 6 buttons - five with 2 states, one with 3 states.

That requires clarification.

You also illustrate a link from Gnd to DO on the LED strip. That is clearly wrong. Why would you do that?

Paul__B:

LetThisNightExplode:
I have 6 buttons - five with 2 states, one with 3states.

That requires clarification.

Okay sure,

The 6 buttons are signal lights like for a car/bike.

Buttons 1, and 2 -> Brakes, 2 states, either on or off.
Buttons 3-5; also are either just on or off. (left signal, right signal, flash headlights)

The last buttons has 3 states - off, LOW, or HIGH. THe flash button only affects the headlights, etc.

The idea was to write it so that it would call the functions based on what states the system was in

So if
headlightSelectButonn=2, and flashHeadlights-0, then; only display highHeadlights();
headlightSelectButonn=1, and flashHeadlights-1, then; return headlightsLowBlinking();

Paul__B:
You also illustrate a link from Gnd to DO on the LED strip. That is clearly wrong. Why would you do that?

Uh, because it was suggested to me by those who wrote the FastLED library? In their Documentation section, under Power Notes its the first bullet under "Tips". shrugs "At the 'far' end of long LED strips, connect the Data line to Ground." I guess my 24 LED section is not 'long' but I was having problems with earlier circuits lighting everything. There are 24 APA102 "Dotstars" in the led matrix.

Try changing

pinMode(BTN_BRAKE_LEFT, INPUT);

to

pinMode(BTN_BRAKE_LEFT, INPUT_PULLUP);

and so on.

PaulRB:
Try changing

pinMode(BTN_BRAKE_LEFT, INPUT);

to

pinMode(BTN_BRAKE_LEFT, INPUT_PULLUP);

and so on.

it didnt make a difference.

Can I used #define for button pins?

void loop() {
    
    buttonState = digitalRead(buttonPin);
    
    if (buttonState != lastButtonState) {
        if (buttonState == HIGH) {
            buttonPushCounter++;
            turnLeft();
            headlightBlinkHIGH();
            Serial.println("ONE");
            Serial.print("The Current Button state is:  ");
            Serial.println(buttonPushCounter);
        } 
        else {
            Serial.println("off"); 
            turnLeft();
            brakes();
        }
        lastButtonState = buttonState;
    }
}

LetThisNightExplode:
it didnt make a difference.

It should have done, if your Fritzing "cartoon" truly represents your circuit. Look at the way you have those switches wired. Without INPUT_PULLUP, why would the Arduino inputs ever read HIGH? Perhaps a picture would help.

Using #define x y instead of const int x = y; should make no difference in your sketch.

PaulRB:
why would the Arduino inputs ever read HIGH?

I'm not sure what you mean. My circuit was expanded from another example where button presses were first introduced. I have no idea why resistors are put before/after leds or switches/buttons - i just do it. Well - that's not entirely true - I was told they help make high/low signals a bit more discrete/clear....cleaning it up a bit i guess.

Would you suggest to me an alternate circuit?

He is saying, if they were attached to ground, and as an input, how could they ever be anything other than 0 volts (ground is zero volts)

input pull-up uses the arduinos internal resistors to pull up your button pin to 5v.

When your button is pressed, it goes to zero volts.

You need to check when your buttons are low.

If the pin is low, your button is pressed and you should do something.

If the pin is high, the button isn't pressed.

LetThisNightExplode:
I'm not sure what you mean.

Actually, I was wrong, they might read HIGH with your circuit as shown. But they would not do it reliably.

The problem with your button circuit as shown, is that when the button is not pressed, the Arduino input is "floating" which means it is not connected to either 5V or 0V. This means it could read HIGH or LOW at random. When the switch is pressed, the input is connected to 0V and will correctly read LOW.

At the moment your resistors are doing nothing at all.

There are three ways to fix this.

  • Connect the resistors between the Aruduino input and 5V and the switches from the Arduino input to 0V. That way, when the switch is not pressed, the Arduino input will read HIGH because of the resistor. When the switch is pressed it will read LOW.
  • Connect the resistors between the Aruduino input and 0V and the switches from the Arduino input to 5V. That way, when the switch is not pressed, the Arduino input will read LOW because of the resistor. When the switch is pressed it will read HIGH.
  • Remove the resistors, connect the switches between the Arduino inputs and 0V and change the code to use INPUT_PULLUP instead of INPUT. That way, when the switch is not pressed, the Arduino input will read HIGH because of the internal resistor. When the switch is pressed it will read LOW.