Button Input only works sometimes

My code is pretty long, scroll down to the comment saying "broken below here" for the part concerning the button. The button is supposed to increment a number and display it on a screen. Sometimes it works and sometimes it doesn't, I suspect it is a problem with my button1state and lastbutton1state if statement. If some of the code is not clear I can explain it.

#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
#include <dht.h>

dht DHT;
volatile int alarmpage = 0;
const int unsigned long period = 1000;
const int unsigned long tempperiod = 5000;
unsigned long temptime = 0;
unsigned long clocktime = 0;
int initial = 0;
byte count = 0;
boolean type = true;
int alarmminute = 0;
int alarmhour = 0;
int exitbutton = 0;
bool alarmstart = false;

//button debouncing variables
int button1state;
int button2state;
int button3state;
int lastbutton1state = LOW;
int lastbutton2state = LOW;
int lastbutton3state = LOW;
const int button1pin = 2;
const int button2pin = 3;
const int button3pin = 8;


#define DHT11_PIN 5

RTC_Millis rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);

void alarmprogram() {
  alarmpage = 1;

}

void setup() {
  lcd.init(); // initialize the lcd
  lcd.backlight();
  lcd.setCursor(0, 0);
  Serial.begin(9600);
  rtc.begin(DateTime(F(__DATE__), F(__TIME__)));
  attachInterrupt(0, alarmprogram, RISING);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(8, INPUT);
}

void loop() {
  unsigned long currenttime = millis();


  //print initial time
  if (initial == 0) {
    lcd.clear();
    DateTime now = rtc.now();
    int currentmin = now.minute();
    int currentsec = now.second();
    lcd.print("Time:  ");
    lcd.print(now.hour(), DEC);
    lcd.print(':');
    if (currentmin < 10) {
      lcd.print('0');
    }
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    if (currentsec < 10) {
      lcd.print('0');
    }
    lcd.print(now.second(), DEC);
    lcd.setCursor(0, 1);
    lcd.print("Date: ");
    lcd.print(now.month(), DEC);
    lcd.print("/");
    lcd.print(now.day(), DEC);
    lcd.print("/");
    lcd.print(now.year(), DEC);
    initial = 1;
  }

  if (currenttime - clocktime >= period && alarmpage == 0) {
    //print updated time after 1 second

    if (type == true) {

      lcd.setCursor(0, 0);
      DateTime now = rtc.now();
      int currentmin = now.minute();
      int currentsec = now.second();
      lcd.print("Time:  ");
      lcd.print(now.hour(), DEC);
      lcd.print(':');
      if (currentmin < 10) {
        lcd.print('0');
      }
      lcd.print(now.minute(), DEC);
      lcd.print(':');
      if (currentsec < 10) {
        lcd.print('0');
      }
      lcd.print(now.second(), DEC);
      lcd.setCursor(0, 1);
      lcd.print("Date: ");
      lcd.print(now.month(), DEC);
      lcd.print("/");
      lcd.print(now.day(), DEC);
      lcd.print("/");
      lcd.print(now.year(), DEC);

      initial = 1;

    }

    else if (type == false) {
      int chk = DHT.read11(DHT11_PIN);
      lcd.setCursor(0, 0);
      lcd.print("Temp: ");
      lcd.print(DHT.temperature);
      lcd.print(" C");
      lcd.setCursor(0, 1);
      lcd.print("Humidity :");
      lcd.print(DHT.humidity);
      lcd.print("%");

    }
    clocktime = currenttime;
    count++;

  }

  if (count == 5) {
    type = !type;
    count = 0;
    lcd.clear();
  }

  //BROKEN BELOW HERE

  while (alarmpage == 1) {
    button1state = digitalRead(button1pin);
    button2state = digitalRead(button2pin);
    button3state = digitalRead(button3pin);
    if (alarmstart == false) {
      lcd.clear();
      lcd.print("Alarm Time: ");
      lcd.setCursor(0, 1);
      lcd.print("00:00");
      //alarminitialize = 1;
    }

    if (button1state == HIGH && lastbutton1state == LOW) {

      alarmhour++;
      lcd.setCursor(0, 1);
      lcd.print(alarmhour);
      lcd.print(":");
      lcd.print(alarmminute);
      alarmstart = true;
      

    }



    if (digitalRead(3) == HIGH) {
      alarmminute++;
      lcd.setCursor(0, 1);
      lcd.print(alarmhour);
      lcd.print(":");
      lcd.print(alarmminute);
      alarmstart = true;
    }
    if (digitalRead(8) == HIGH) {
      exitbutton = 1;
    }

    if (exitbutton == 1) {
      alarmpage = 0;
    }
    lastbutton1state = digitalRead(button1pin);

  }


}

Try:


  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);

How is the switch (button) wired? The best way is to wire the switch to ground and to an input set to pinMode INPUT_PULLUP. The input will read HIGH when the switch is open (not pressed) and LOW when closed (pressed). You may have to adjust the logic in your program to fit.

See my state change detection for active low switches tutorial.

No change from this, I have it wired with a resistor that is between the pin and ground so it reads high when the button is pressed, I forget if this is pull up or pull down

That is pull down, so the input will read LOW for the open (unpressed) switch and HIGH for the closed (pressed) switch.

If you are wired for pulldown and do not wish to change to pullup and the switches wired to ground, don't use INPUT_PULLUP.

FYI

As far as I can tell it is wired fine, it correctly reads as high when pressed because other parts of the code relying on button presses work. See code below for excerpt that works fine for detecting button presses. The problem is they continue to increment the number multiple times per press, so I was trying to make it only increment once with the button1state and lastbutton1state if statement, which introduced this new issue

    if (digitalRead(3) == HIGH) {
      alarmminute++;
      lcd.setCursor(0, 1);
      lcd.print(alarmhour);
      lcd.print(":");
      lcd.print(alarmminute);
      alarmstart = true;
    }
    if (digitalRead(8) == HIGH) {
      exitbutton = 1;
    }

Show us a good schematic of your circuit.

Show us a good image of your ‘actual’ wiring.


Switches should be acknowledged when they go HIGH not when the level is HIGH.


BTW
In the Arduino IDE, use Ctrl T to format your code.

There are a ton of wires so I will explain it as best I can. Button 1 is the left most, all 3 are connected the same way but with the input pin being the only difference. The red wire of button 1 is connected to 5V, and on the other side of the button is a blue wire going to a digital input pin and a resistor. At the end of the resistor is a yellow wire going to ground. Again, if I remove the if statement logic and just check for a digital read of high then it increments the number correctly only when button 1 is pressed but does it too many times so I don't suspect wiring is the issue

Study this:

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