Arduino Looping Through If Statements?

Unsure if there's something wrong with my code, but it looks like it should work.
The code is heavily, heavily based off of this.

Issue:
Code loops through and runs all of my desired "lcd.print" lines, without considering the required if statement. Rapidly changing from the first print to the next, to the next, then looping (to counter 0). I just can't understand what the issue with the code is and I'm having a lot of trouble with trying to troubleshoot it.

Using:
I am using an Arduino Uno on Arduno version 1.8.19.

Code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
// LiquidCrystal_I2C lcd(0x27,20,4);

const int buttonPin = 3;

int counter = 0;

void setup()
{
  pinMode(buttonPin, INPUT);
  lcd.begin();      // initialize the lcd
  // Print a message to the LCD.
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("1: Page 1");
  lcd.setCursor(0, 1);
  lcd.print("2: Page 2");
}


void loop()
{
  int buttonState;
  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW)
  {
    counter++;
    delay(150);
  }

  if (counter == 0)
  {
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Hello!");
  }
  
  else if (counter == 1)
  {
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Goodbye!");
  }

  else if (counter == 2)
  {
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("I'm Lost.");
  }

  else if (counter == 3)
  {
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("I'm not?");
  }

  else
  {
    counter = 0;
  }
}

And here is an early version of the circuit I have for this prototype, in case I might have wired something incorrectly.

(Yes, I know there are 4 buttons. I'm first trying to get button0 to work before hitting button1-3.)

Thank you to anyone who has the time to look at this, I appreciate it greatly.

If you haven't done so yet, I would start with a basic sketch to check the button behaviour.

const int buttonPin = 3;

void setup()
{
  Serial.begin(115200);
  pinMode(buttonPin, INPUT);
}

void loop()
{
  Serial.print(F("button reading ="));
  Serial.println(digitalRead(buttonPin));
  delay(500);
}
1 Like

I ran your script, and when the button is down, it's =1; not pressed is =0.

If by button behavior, you mean not in some way broken, I'm unsure if that's my case. It behaved as I expected in your script

I don't think I properly used the reply button, oops, so bumping this real quick.

(forgive me mods if this is a crime here, new to the forum)

So the buttons are working.

But your code from the opening post checks for LOW (which equals 0) and hence "not pressed".

Note:
As far as I can see, the resistors should be from the green wires to GND to achieve a pull-down, not where they are now. It however should not affect the working.

Don't worry, I did find it :wink:

1 Like

As for the code, I attempted HIGH as well and it returned a similar result.

For where the note is about the circuitry, I also copied the wiring from the linked example and still received a similar result. Unless the tutorial/example is in the wrong, I don't know why I'm struggling so badly with it.

Edit: I will be wrapping up and going away for the night to sleep, will be active again some point tomorrow.

Hello zicunningham1

Take a view here to gain the knowlege about.

Many thanks to LarryD

1 Like

150 msec of delay may not be long enough for you to press and release the button. need to recognize the transition from release to pressed

consider

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
// LiquidCrystal_I2C lcd(0x27,20,4);
const int buttonPin = 3;
int counter = 0;
int buttonState;

void setup()
{
    pinMode(buttonPin, INPUT);
    lcd.begin();      // initialize the lcd
    // Print a message to the LCD.
    lcd.backlight();
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("1: Page 1");
    lcd.setCursor(0, 1);
    lcd.print("2: Page 2");

    pinMode (buttonPin, INPUT_PULLUP);
    buttonState = digitalRead (buttonPin);
}

void loop()
{
    byte but  = digitalRead(buttonPin);
    if (buttonState != but)
    {
        buttonState = but;
        delay (20);         // debounce

        if (LOW == but)
            counter++;
    }

    if (counter == 0)
    {
        lcd.clear();
        lcd.setCursor(0,1);
        lcd.print("Hello!");
    }
    else if (counter == 1)
    {
        lcd.clear();
        lcd.setCursor(0,1);
        lcd.print("Goodbye!");
    }
    else if (counter == 2)
    {
        lcd.clear();
        lcd.setCursor(0,1);
        lcd.print("I'm Lost.");
    }
    else if (counter == 3)
    {
        lcd.clear();
        lcd.setCursor(0,1);
        lcd.print("I'm not?");
    }
    else
    {
        counter = 0;
    }
}
1 Like

It now tries looping the counter==0 in a very rapid and unpleasant fashion- to the point it's not legible. And the button does not cause any form of reaction, either.

Decided to go ahead and update the existing information about this project.

Current Code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
// LiquidCrystal_I2C lcd(0x27,20,4);
const int buttonPin = 3;
int counter = 0;
int buttonState;

void setup()
{
    pinMode(buttonPin, INPUT);
    lcd.begin();      // initialize the lcd
    // Print a message to the LCD.
    lcd.backlight();
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("1: Page 1");
    lcd.setCursor(0, 1);
    lcd.print("2: Page 2");

    pinMode (buttonPin, INPUT_PULLUP);
    buttonState = digitalRead (buttonPin);
}

void loop()
{
    byte but  = digitalRead(buttonPin);
    if (buttonState != but)
    {
        buttonState = but;
        delay (200);         // debounce

        if (HIGH == but)
            counter++;
    }

    if (counter == 0)
    {
        lcd.clear();
        lcd.setCursor(0,1);
        lcd.print("Hello!");
    }
    else if (counter == 1)
    {
        lcd.clear();
        lcd.setCursor(0,1);
        lcd.print("Goodbye!");
    }
    else if (counter == 2)
    {
        lcd.clear();
        lcd.setCursor(0,1);
        lcd.print("I'm Lost.");
    }
    else if (counter == 3)
    {
        lcd.clear();
        lcd.setCursor(0,1);
        lcd.print("I'm not?");
    }
    else
    {
        counter = 0;
    }
}

Current Circuit and Issue (video):

Edit: Although the video is in Tinkercad, I do have a real, physical circuit in front of me that does the same thing. The only difference is that the I2C library I have on my personal laptop is "lcd.begin();", while it's traditionally "lcd.init();". It's just easier to record it in Tinkercad.

Although the circuit here was nice to use, the "INPUT_PULLUP" does not work with my button; it was only returning 1 at all positions. On "INPUT" it returns 0.

In the code in post #11, you make use state change detection for the button. You can use the same approach for your counter: only update the LCD when the counter changes.

I've modified your code to suite my setup and the button works. The buttons in my setup are wired like S3 in the schematic in post #8.

Changes made:

  pinMode(buttonPin, INPUT_PULLUP);

and

    if (LOW == but)

I found the errors in it, and it was surprisingly not the code from one of the variants I had it as "broken"... it was the circuit, somehow. I revisited the button checking script and found that the button was spamming 1 quite a lot and it was caused by a bad connection, in some way, in the wire to the breadboard (from power). Remade the circuit on another Arduino kit and it worked just fine, just had issues with mine for some reason. It's a university-provided breadboard so part of me wonders if the contacts in mine on that specific zone were just beaten up pretty badly.

The code is working as intended now and I'm gonna try to figure out the state change detection instead of running a looped timer on it.

Also, note, is that INPUT_PULLUP is not being used in my code right now as it's working; how would that affect its operation? And thank you for the extensive help you've provided thus far.

The switch input would become "active low". That means that the input is LOW when the switch is pressed and HIGH when not pressed. LOW is the "true" condition, so active low.

One reason to use active low is that you are running a ground wire to the switch instead of a "hot" 5V (or whatever) wire. Less chance of a short. And the other wire has a resistor (30K - 50K for internal pullup) in series that limits the current in case that it makes contact with ground.

1 Like

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