Let me preface this by saying I'm a beginner, and I know my code must have some logic errors. I need some fresh eyes on this, I have been messing with it a few days and am just running in circles at this point.

I'm trying to use buttons and button states to set hours and minutes of an alarm clock so I am trying to save the state of the buttons so after being pushed so it will remember the state rather than being changed on release. I am trying to get it so pushing button A in my code goes into the alarm clock set procedure, then until button C is pressed it will loop to set hours then minutes (I havent added minutes procedure yet) So button A starts procedure and button C completes it, while button B increases the hours/minutes variable by one.

I have thoroughly confused myself. I have two "lastButtonState" variables which may be unnecessary but it was the only thing I could think of.

Right now with my code it goes into the button C while loop but doesn't come out of it on button press. My logic for that was that the while loop should exit when button C is pressed, so I don't think I need anything within the loop to break out of it.

I have the button B setting hours part working, it just isn't exiting the button C loop.

I'm eventually going to put this code in its respective function and add in the set minutes area after set hours area.

Here is my code:

#include <LiquidCrystal.h>

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
//Constants
//const int buttonPin = 9;
const int buttonApin = 3;
const int buttonBpin = 2;
const int buttonCpin = 5;
int buttonState = 0;
int buttonState2 = 0;
int buttonState3 = 0;
//int flag = 0;
int alarmHoursInner = 1;
int lastButtonState = 0;
int lastButtonState3 = 0;
void setup() {
  // put your setup code here, to run once:
  lcd.begin(16, 2);
  Serial.begin(9600);
  //Input or output?
  pinMode(buttonApin, INPUT_PULLUP);
  pinMode(buttonBpin, INPUT_PULLUP);
  pinMode(buttonCpin, INPUT_PULLUP);
}

void loop() {
  // put your main code here, to run repeatedly:
  buttonState = digitalRead(buttonApin);
  buttonState2 = digitalRead(buttonBpin);
  buttonState3 = digitalRead(buttonCpin);

  if (buttonState == HIGH) {
    while (buttonState3 == LOW) {

      buttonState2 = digitalRead(buttonBpin);
      if (lastButtonState != buttonState2) { // last button state starts at 0 (or OFF) this line tests current state against last state
        if (buttonState2 == LOW) { // if buttonState is HIGH it went from OFF to ON
          // Serial.print("Button B works!");
          ++alarmHoursInner; // increments variable for hours
          Serial.print(alarmHoursInner); // prints hours
          Serial.println("  "); // blank line
          delay(50); // delay
        }
        else {

          Serial.print("Please push button B");
          Serial.println("  ");
        }
      }  

      lastButtonState = buttonState2;
    }
      lastButtonState3 = buttonState3;
  }
}
  • 1
    start by renaming the buttons to some useful names that describe the function.... instead of buttonA, buttonB, buttonC call them something like mode, advance, exit .... modeButton, etc. – jsotola Aug 11 at 17:19
  • research Arduino state machine – jsotola Aug 11 at 17:20
  • Ok your input about renaming is noted, thanks! I have already looked at state changes pretty thoroughly. Could you point me in the direction of something specific about state machines that would help? I googled it and looked at a few links but what part of state machines should I focus on? So far, It looks like its what I have already known about states when I developed my code. What exactly is wrong with my code? – user2565352 Aug 11 at 19:19
  • lastButtonState3 = buttonState3; .... this line is indented too far, which makes it look like it is part of the if statement .... it is at the end of the while loop ..... buttonState3 will always be LOW when this line executes – jsotola Aug 11 at 23:23

You could start with a button de-bouncing library such as Bounce2. This sketch illustrates how to detect multiple button presses from one button to cycle though 3 different options.

It may be a good idea to write out the steps of your "Alarm Setting Procedure" in plain text before writing any code. This will help you to determine the control structures needed in your sketch.

An alternative to using several buttons would be a rotary encoder with built-in push button switch. There are libraries for them which detect a button press, double press, press and hold, and of course they can increment/decrement a counter variable by "turning the dial" CW and CCW.

// Connect one end of a N.O. push button switch to
// GND and the other end to pin 4 of the Arduino.
#include <Bounce2.h>

byte buttonState = 0;
byte lastButtonState = 0;  // Only used for debug purposes.
const byte modeButtonPin = 4;
const unsigned long debouncerInterval = 50;  // Time in ms.

Bounce modeButton = Bounce();

void setup(){

  Serial.begin(9600);
  pinMode(modeButtonPin, INPUT_PULLUP);
  modeButton.attach(modeButtonPin);
  modeButton.interval(debouncerInterval);

}

void loop(){

  if(modeButton.update()){

    if(modeButton.read() == 0){
      buttonState++;
      if(buttonState > 2){buttonState = 0;}
    }

  }

  // Only used for debug purposes.
  // Print out the contents of the buttonState variable when it changes.
  if(buttonState != lastButtonState){
    if(buttonState == 0){Serial.println("Clock Mode - Current Time Displayed");}
    else if(buttonState == 1){Serial.println("Alarm Mode - Set Hours");}
    else{Serial.println("Alarm Mode - Set Minutes");}
    lastButtonState = buttonState;
  }

}

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.