Help with button counter

Hi all,

I am new to Arduino and working on my second project using it. For first project I used multiple button example and built on that. Now I am trying something new which involves using single button, counting the button presses and doing something different for each press count.

I am building using the same code but looks like I messed up big time. As soon as I run the code, serial monitor stuck in the loop and keep printing output for press counter 1. Can someone please point me to the right direction.

Thanks.


#include <FastLED.h>
#define NUM_LEDS 60 
#define DATA_PIN 12

CRGB leds[NUM_LEDS];

const uint8_t buttonPin = 2;               // Inputs for buttons. On many Arduinos pins 0 and 1 are used for serial making pin 2 the first free pin.
uint8_t currentpressCount = 0;             // Current button press count
uint8_t lastpressCount = 0;                // Last button press count
bool buttonPressedFlag;                   // Flags to indicate that a button has been detected as pressed and debounced


void setup() {

  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
  FastLED.clear();
  FastLED.show();
  
  Serial.begin(9600);                     // Start the serial monitor to see the results.
  char fileName[] = {__FILE__};
  Serial.println(fileName);               // Prints the name of the file the location this sketch is in.
  pinMode(buttonPin, INPUT_PULLUP);       // Make the button pins inputs with the internal pull up resistor enabled.
  }

void loop() {
  Buttons();                          // Calls the function to read the button.
  doStuff();                          // Does something in response to the input
                                      // Your other code goes here, make sure it is non blocking (no delays, no loops that don't exit quickly)
}

/* This is the function that reads the state of the button, debounces it then sets a flag for the separate doStuff()function to do something */
void Buttons() {
  #define buttonPressed LOW                // When the button is pressed the input will be low, this is to remove the confusion this might cause.
  uint32_t currentMillis = millis();       // Millis times uses to debounce the button
  static uint32_t lastMillis;              // Start of the debounce timeout for the button
  const uint32_t bounceTimeout = 20;       // Debounce time in milliseconds
  bool currentButtonState;                 // Holds the current state of the button
  static bool lastButtonState;             // Holds the previous debounced state of the button

    currentButtonState = digitalRead(buttonPin);        // Reads the current state of button and saves the result
    if (lastButtonState != currentButtonState) {        // Checks to see if the button has been pressed or released, at this point the button has not been debounced
      if (currentMillis - lastMillis >= bounceTimeout) {   // Checks to see if the state of the button has been stable for at least bounceTimeout duration
        lastButtonState = currentButtonState;           // At this point the button has been debounced, so save the last state
        if (currentButtonState == buttonPressed) {         // The button might have been pressed or released, this make sure only presses are acted on, not releases
          buttonPressedFlag = true;                        // Button press has been detected and debounced, set a flag to indicate to the next function that some action can be taken
          currentpressCount++;
        }
      }
     else {
      lastMillis = currentMillis;                         // Saves the current value of millis in last millis so the debounce timer for the button starts from current millis
    }
  }
}

void doStuff() {
 
    if (currentpressCount = 1) {
      Serial.println("Level 1"); 
      buttonPressedFlag = false;
    }
  else if (currentpressCount = 2){
    Serial.println("Level 2"); 
    buttonPressedFlag = false;
  }
   else if (currentpressCount = 3){
    Serial.println("Level 3"); 
    buttonPressedFlag = false;
   }
    else (currentpressCount = 4){
    Serial.println("Level 4"); 
    buttonPressedFlag = false;
    }}




You need to switch on Compiler Warning ALL in File → Preferences.

if (currentpressCount = 1) you need to two == for comparison

One equal is valid C syntax but 99.9% of time it is wrong. Most compiler warn you about this.

Thanks Klaus_K, appreciate the guidance. I have switched ON the compiler warning and changed the code to == from =.

But the issue is still the same. I want the code to run only once for each button press, but it keeps running the loop. I thought clearing the buttonPressedFlag will stop the loop but obviously I was wrong. Any suggestion what I am doing wrong here?

If you make changes to your code post the new version so that we can keep up. Do not modify the original post.

Sorry for that groundFungus. Here is the modified code -


#include <FastLED.h>
#define NUM_LEDS 60 
#define DATA_PIN 12

CRGB leds[NUM_LEDS];

const uint8_t buttonPin = 2;               // Inputs for buttons. On many Arduinos pins 0 and 1 are used for serial making pin 2 the first free pin.
uint8_t currentpressCount = 0;             // Current button press count
uint8_t lastpressCount = 0;                // Last button press count
bool buttonPressedFlag;                   // Flags to indicate that a button has been detected as pressed and debounced


void setup() {

  FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
  FastLED.clear();
  FastLED.show();
  
  Serial.begin(9600);                     // Start the serial monitor to see the results.
  char fileName[] = {__FILE__};
  Serial.println(fileName);               // Prints the name of the file the location this sketch is in.
  pinMode(buttonPin, INPUT_PULLUP);       // Make the button pins inputs with the internal pull up resistor enabled.
  }

void loop() {
  Buttons();                          // Calls the function to read the button.
  doStuff();                          // Does something in response to the input
                                      // Your other code goes here, make sure it is non blocking (no delays, no loops that don't exit quickly)
}

/* This is the function that reads the state of the button, debounces it then sets a flag for the separate doStuff()function to do something */
void Buttons() {
  #define buttonPressed LOW                // When the button is pressed the input will be low, this is to remove the confusion this might cause.
  uint32_t currentMillis = millis();       // Millis times uses to debounce the button
  static uint32_t lastMillis;              // Start of the debounce timeout for the button
  const uint32_t bounceTimeout = 20;       // Debounce time in milliseconds
  bool currentButtonState;                 // Holds the current state of the button
  static bool lastButtonState;             // Holds the previous debounced state of the button

    currentButtonState = digitalRead(buttonPin);        // Reads the current state of button and saves the result
    if (lastButtonState != currentButtonState) {        // Checks to see if the button has been pressed or released, at this point the button has not been debounced
      if (currentMillis - lastMillis >= bounceTimeout) {   // Checks to see if the state of the button has been stable for at least bounceTimeout duration
        lastButtonState = currentButtonState;           // At this point the button has been debounced, so save the last state
        if (currentButtonState == buttonPressed) {         // The button might have been pressed or released, this make sure only presses are acted on, not releases
          buttonPressedFlag = true;                        // Button press has been detected and debounced, set a flag to indicate to the next function that some action can be taken
          currentpressCount++;
        }
      }
     else {
      lastMillis = currentMillis;                         // Saves the current value of millis in last millis so the debounce timer for the button starts from current millis
    }
  }
}

void doStuff() {
 
    if (currentpressCount == 1) {
      Serial.println("Level 1"); 
      buttonPressedFlag = false;
    }
  else if (currentpressCount == 2){
    Serial.println("Level 2"); 
    buttonPressedFlag = false;
  }
   else if (currentpressCount == 3){
    Serial.println("Level 3"); 
    buttonPressedFlag = false;
   }
    else if (currentpressCount == 4){
    Serial.println("Level 4"); 
    buttonPressedFlag = false;
    }}



You do not reset currentpressCount so you will print continuously.

If you want to print only once you also need to check the buttonPressedFlag in the if statement in doStuff().

I tried checking the flag at different points. Good thing is that now it is not stuck in loop but now I can see serial monitor printing output for counter 1 to 4 all at once, on just 1 button press. This is what I changed in code -

void doStuff() {

    if (buttonPressedFlag = true && currentpressCount == 1) {
      Serial.println("Level 1"); 
      buttonPressedFlag = false;
    }
  else if (buttonPressedFlag = true && currentpressCount == 2){
    Serial.println("Level 2"); 
    buttonPressedFlag = false;
  }
   else if (buttonPressedFlag = true && currentpressCount == 3){
    Serial.println("Level 3"); 
    buttonPressedFlag = false;
   }
    else if (buttonPressedFlag = true && currentpressCount == 4){
    Serial.println("Level 4"); 
    buttonPressedFlag = false;
    }}

Read the code again. You repeated a mistake. :wink:

Hello,
put all button relevant data and information in a struc{}.
Due to you have access to the button information over all functions inside your sketch.

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