How do I make LCD display to stick with message every time I press button?

Hello y'all,

I'm working on this project dealing with interrupts along with LCD display. My goal is to have my LCD display showing seconds counting before I press 1st button to display message saying "Interruption received, press button 2 to continue" then after pressing 2nd button, it would display "Been waiting for X seconds, now it resets at X seconds"

My problem with this project is when I press 1st button, it would loop showing mixed messages on my LCD display, it cannot stick with message I want to it to be shown. How do I make messages stay on LCD display whatever I want it to be? I got this kind of idea from this source, http://www.instructables.com/id/Arduino-Push-Switch-Debouncing-Interrupts/

Here's my code -

int Scount1 = 0;                     // count seconds
int Scount2 = 0;
int Scount3 = 0;
const int current_position = 0;
const int button1 = 2;
const int button2 = 3;
int reading1 = 0;
int reading2 = 0;

LiquidCrystal lcd(12, 11, 7, 6, 5, 4); // pins connected to LCD

void setup() {
  lcd.begin(16, 2);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);

  attachInterrupt(0, boom, RISING); // digital pin 2, button 1
  attachInterrupt(1, reset, RISING); // digital pin 3, button 2
}

void loop() {

  reading1 = digitalRead(button1);
  reading2 = digitalRead(button2);

  switch (current_position)
  {
    case 0:
      counting();
      break;
    case 1:
      boom();
      break;
    case 2:
      reset();
      break;
  }
}

void counting()
{
  lcd.setCursor (0, 0);              // sets cursor to 1st line
  lcd.print ("Waiting for ");
  lcd.print (Scount1);
  delay (988);
  lcd.setCursor(0, 1);
  lcd.print ("seconds.");
  Scount1++;
}

void boom()
{
  lcd.setCursor(0, 0);
  lcd.print("Interrupt received!");
  lcd.setCursor(0, 1);
  lcd.print("Press 2 to reset");
  delay(150);
}

void reset()
{
  lcd.setCursor(0, 0);             // sets cursor to 1st line
  lcd.print("Been waiting for ");
  lcd.print(Scount2);
  lcd.setCursor(0, 1);
  lcd.print("Now waiting at ");
  lcd.print (Scount3);
  delay (988);
  lcd.setCursor(0, 1);
  lcd.print ("secs.");
  Scount3++;
}

First thing is to remove all of the interrupt code. You do not understand what interrupts are. Yes, it is a common "newbie" blunder to think they are for making your main function do something different.

Buttons should be polled in your loop() code and all decisions made there.

Oh no! You got this idea from an "instructable". Clearly he did not understand what interrupts are either. No surprise there.

Sigh! :roll_eyes:

Paul__B:
First thing is to remove all of the interrupt code. You do not understand what interrupts are. Yes, it is a common "newbie" blunder to think they are for making your main function do something different.

Buttons should be polled in your loop() code and all decisions made there.

Oh no! You got this idea from an "instructable". Clearly he did not understand what interrupts are either. No surprise there.

Sigh! :roll_eyes:

Thank you. I needed it very much! No, it wasn't sarcasm!

OK, so I apologise that I do not have the time - or more correctly am too fatigued - to write you the proper code just now. Maybe in a day or two.

Let me just try and get the specification right.

It starts counting - and displaying seconds.

Press a button - it displays a first message, taking two lines to do so - so the seconds display disappears.

It then counts from the moment the first button was pressed.

When the second button is pressed, it displays the time elapsed from the first, and the sum of that time and the time when the first button was pressed.

Then what?

There is a hint here - you must specify with absolute precision every possible consequence of the sequence of button presses.

Cam9191:
Hello y'all,

I'm working on this project dealing with interrupts along with LCD display. My goal is to have my LCD display showing seconds counting before I press 1st button to display message saying "Interruption received, press button 2 to continue" then after pressing 2nd button, it would display "Been waiting for X seconds, now it resets at X seconds"

My problem with this project is when I press 1st button, it would loop showing mixed messages on my LCD display, it cannot stick with message I want to it to be shown. How do I make messages stay on LCD display whatever I want it to be? I got this kind of idea from this source, http://www.instructables.com/id/Arduino-Push-Switch-Debouncing-Interrupts/

Here's my code -

int Scount1 = 0;                     // count seconds

int Scount2 = 0;
int Scount3 = 0;
const int current_position = 0;
const int button1 = 2;
const int button2 = 3;
int reading1 = 0;
int reading2 = 0;

LiquidCrystal lcd(12, 11, 7, 6, 5, 4); // pins connected to LCD

void setup() {
  lcd.begin(16, 2);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);

attachInterrupt(0, boom, RISING); // digital pin 2, button 1
  attachInterrupt(1, reset, RISING); // digital pin 3, button 2
}

void loop() {

reading1 = digitalRead(button1);
  reading2 = digitalRead(button2);

switch (current_position)
  {
    case 0:
      counting();
      break;
    case 1:
      boom();
      break;
    case 2:
      reset();
      break;
  }
}

void counting()
{
  lcd.setCursor (0, 0);              // sets cursor to 1st line
  lcd.print ("Waiting for ");
  lcd.print (Scount1);
  delay (988);
  lcd.setCursor(0, 1);
  lcd.print ("seconds.");
  Scount1++;
}

void boom()
{
  lcd.setCursor(0, 0);
  lcd.print("Interrupt received!");
  lcd.setCursor(0, 1);
  lcd.print("Press 2 to reset");
  delay(150);
}

void reset()
{
  lcd.setCursor(0, 0);            // sets cursor to 1st line
  lcd.print("Been waiting for ");
  lcd.print(Scount2);
  lcd.setCursor(0, 1);
  lcd.print("Now waiting at ");
  lcd.print (Scount3);
  delay (988);
  lcd.setCursor(0, 1);
  lcd.print ("secs.");
  Scount3++;
}

By resets at X seconds, do you mean resets starting at how many seconds that were waited for the second button press and continuing on from there?

Best Regards

Paul__B:
OK, so I apologise that I do not have the time - or more correctly am too fatigued - to write you the proper code just now. Maybe in a day or two.

Let me just try and get the specification right.

It starts counting - and displaying seconds.

Press a button - it displays a first message, taking two lines to do so - so the seconds display disappears.

It then counts from the moment the first button was pressed.

When the second button is pressed, it displays the time elapsed from the first, and the sum of that time and the time when the first button was pressed.

Then what?

There is a hint here - you must specify with absolute precision every possible consequence of the sequence of button presses.

Exactly, you said it correctly. I wrote code similarly what you just explained, but it wouldn't respect the code when 1st button is pressed because it would loop back to the first message?

Angelusvetus:
By resets at X seconds, do you mean resets starting at how many seconds that were waited for the second button press and continuing on from there?

Best Regards

Please take a look at Paul__B's 2nd post. He said it all very exactly I'm have been trying to work on.

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

int Scount1 = 0;                     // count seconds
int Scount2 = 0;
int Scount3 = 0;

long second1 = ((millis() + 500) / 1000);
long second2 = ((millis() + 500) / 1000);
long second3 = ((millis() + 500) / 1000);

// set up a constant for the tilt switchPin
const int switchPin1 = 2;
const int switchPin2 = 3;

// variable to hold the value of the switchPin
int switchState = 0;

// variable to hold previous value of the switchpin
int prevSwitchState = 0;

void setup() {
  // set up the number of columns and rows on the LCD
  lcd.begin(16, 2);

  // set up the switch pin as an input
  pinMode(switchPin1, INPUT_PULLUP);
  pinMode(switchPin2, INPUT_PULLUP);

  //attachInterrupt(0, boom, RISING);
  //attachInterrupt(1, reset, RISING);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Waiting for ");
}

void loop() {

                   // count seconds

  // check the status of the switch
  switchState = digitalRead(switchPin1);

  // compare the switchState to its previous state
  if (switchState != prevSwitchState) {
    if (switchState == LOW) {
      boom();
      second1;
    }
  }
  // save the current switch state as the last state
  prevSwitchState = switchState;

  // check the status of the switch
  switchState = digitalRead(switchPin2);

  // compare the switchState to its previous state
  if (switchState != prevSwitchState) {
    if (switchState == LOW) {
      long timed = ((millis() + 500) / 1000) - second1;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Waited for ");
      lcd.setCursor(0,1);
      lcd.print(timed);
      lcd.print(" secs.");
    }
  }
  // save the current switch state as the last state
  prevSwitchState = switchState;
}

void boom()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("BOOM! Press 2");
  lcd.setCursor(0, 1);
  lcd.print("to reset");
}

void reset()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Waited for ");
  lcd.print(Scount2);
  lcd.print(" secs.");
  lcd.setCursor(0, 1);
  lcd.print("Waiting at ");
  lcd.print ("X");
  lcd.print(" sec");
}

I'm struggling a bit on the beginning message I want it to do is when I start the arduino, I would want it to say "Waiting for X seconds" before I press 1st button because this message would be stuck on display and mix with 1st button's message.

Are you clearing the screen before each write?

Angelusvetus:
Are you clearing the screen before each write?

Of course! Did you take a look at my recent post of my code?

Without being able to see what this display is doing, it is difficult for me to visualize the issue. If posting a link of the display and bug in action on youtube is not possible...

  1. What ever the offending text that is not going away, find all occurances of that string in the code.
  2. One at a time... comment that line out and recompile/upload until the offending text does not show.
  3. This will give a place to start.

I'm confused about your use of "switchstate". In LOOP you use this variable to store the value of switch 1 and then almost immediately after to store the value of switch 2.

  switchState = digitalRead(switchPin1);    
  if (switchState != prevSwitchState)       // compare the switchState to its previous state
  {  //do stuff    }
  prevSwitchState = switchState;       // save the current switch state as the last state

  switchState = digitalRead(switchPin2);    // check the status of the switch
  if (switchState != prevSwitchState)   // compare the switchState to its previous state
{  //do stuff  }
  prevSwitchState = switchState;       // save the current switch state as the last state

Don't you want to save the status of the switches in different locations?

arloG:
I'm confused about your use of "switchstate". In LOOP you use this variable to store the value of switch 1 and then almost immediately after to store the value of switch 2.

  switchState = digitalRead(switchPin1);    

if (switchState != prevSwitchState)      // compare the switchState to its previous state
  {  //do stuff    }
  prevSwitchState = switchState;      // save the current switch state as the last state

switchState = digitalRead(switchPin2);    // check the status of the switch
  if (switchState != prevSwitchState)  // compare the switchState to its previous state
{  //do stuff  }
  prevSwitchState = switchState;      // save the current switch state as the last state



Don't you want to save the status of the switches in different locations?

Not sure, but I think if only one is pressed at a time, it should work. It would be a good idea, after the other issue is resolved, to interlock the code to prevent multiple buttons from being pressed. The outcome would be unpredictable without it.

My big problems with this project is starting a timer after pressing 1st button so it can be displayed to count seconds to be displayed how long it waits after I press 2nd button and eliminating the welcome message with timer before I press 1st button because it would be stuck in the loop after pressing 1st or 2nd button.

This sounds like you want button 1 to start a timer and button 2 to stop the timer. This is different than you described in your original post. In any case, your problem isn't an LCD issue, it's a logic issue. The code below uses switch 1 to start a timer and switch 2 to stop it. The display is the serial monitor. If you want it on an LCD you can substitute for the Serial.prints. Your messages will have to be shortened for the LCD display.

#include <LiquidCrystal.h>

long startTime;                     // count seconds
long period;
int seconds;

// assign switch inputs
const int switchPin1 = 2;
const int switchPin2 = 3;

// variables to hold the value of the switchPins
int switchState1 = 0;
int switchState2 = 0;
// variables to hold previous value of the switch
int prevSwitchState1 = 0;
int prevSwitchState2 = 0;

void setup() 
{ Serial.begin(9600);      // open the serial port at 9600 bps:    
  pinMode(switchPin1, INPUT_PULLUP);
  pinMode(switchPin2, INPUT_PULLUP);
  reset();
  Serial.println("Ready for button 1");
}

void loop() 
{  switchState1 = digitalRead(switchPin1);    // check the status of the switch
  if (switchState1 != prevSwitchState1)         // compare the switchState to its previous state
  {   if (switchState1 == LOW) 
     {   startCount();
     }
  }
   prevSwitchState1 = switchState1;          // save the current switch state as the last state

}

void startCount()
  {  reset();
     Serial.println("Start counting ");
     while (switchState2 = prevSwitchState2)  
     {     switchState2 = digitalRead(switchPin2);    // check the status of the switch
           prevSwitchState2 = switchState2;            // save the current switch state as the last state
           period=(int)((millis()-startTime)/1000);
           if((int)period!= seconds)
           {  Serial.print (" ");
              Serial.print(seconds+1);
              seconds = (int)period;
           }  
     }   
          boom();
   }

void boom()
{ Serial.println(" Boom");
  Serial.println("Interruption received, press button 2 to continue" );
  Serial.println();
  Serial.print( "Waited for ");
  Serial.print(seconds);
  Serial.println(" seconds");
  Serial.println("Push button 1 to count again");
  reset();
}

void reset()
{  startTime = millis();
   seconds=0;
   switchState2 = digitalRead(switchPin2);    // check the status of the switch   
   prevSwitchState2 = switchState2;         // save the current switch state as the last state
}

This line should have been deleted:
Serial.println("Interruption received, press button 2 to continue" );

arloG:
This sounds like you want button 1 to start a timer and button 2 to stop the timer. This is different than you described in your original post. In any case, your problem isn't an LCD issue, it's a logic issue. The code below uses switch 1 to start a timer and switch 2 to stop it. The display is the serial monitor. If you want it on an LCD you can substitute for the Serial.prints. Your messages will have to be shortened for the LCD display.

#include <LiquidCrystal.h>

long startTime;                    // count seconds
long period;
int seconds;

// assign switch inputs
const int switchPin1 = 2;
const int switchPin2 = 3;

// variables to hold the value of the switchPins
int switchState1 = 0;
int switchState2 = 0;
// variables to hold previous value of the switch
int prevSwitchState1 = 0;
int prevSwitchState2 = 0;

void setup()
{ Serial.begin(9600);      // open the serial port at 9600 bps:   
  pinMode(switchPin1, INPUT_PULLUP);
  pinMode(switchPin2, INPUT_PULLUP);
  reset();
  Serial.println("Ready for button 1");
}

void loop()
{  switchState1 = digitalRead(switchPin1);    // check the status of the switch
  if (switchState1 != prevSwitchState1)        // compare the switchState to its previous state
  {  if (switchState1 == LOW)
    {  startCount();
    }
  }
  prevSwitchState1 = switchState1;          // save the current switch state as the last state

}

void startCount()
  {  reset();
    Serial.println("Start counting ");
    while (switchState2 = prevSwitchState2) 
    {    switchState2 = digitalRead(switchPin2);    // check the status of the switch
          prevSwitchState2 = switchState2;            // save the current switch state as the last state
          period=(int)((millis()-startTime)/1000);
          if((int)period!= seconds)
          {  Serial.print (" ");
              Serial.print(seconds+1);
              seconds = (int)period;
          } 
    } 
          boom();
  }

void boom()
{ Serial.println(" Boom");
  Serial.println("Interruption received, press button 2 to continue" );
  Serial.println();
  Serial.print( "Waited for ");
  Serial.print(seconds);
  Serial.println(" seconds");
  Serial.println("Push button 1 to count again");
  reset();
}

void reset()
{  startTime = millis();
  seconds=0;
  switchState2 = digitalRead(switchPin2);    // check the status of the switch 
  prevSwitchState2 = switchState2;        // save the current switch state as the last state
}

Wow! Thank you for the code. However, I modified the code you wrote for me to work with LCD display. However, I faced a couple difficult issues. First - how do I get my start() to display message with second number being counted? The 2nd issue goes the same for LCD message after pressing 2nd button for "Reset: X". Here's the modified code -

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

unsigned long time;
long startTime;                     // count seconds
long startTime1;
long startTime2;
long period;
long period1;
long period2;
int seconds;
int seconds1;
int seconds2;

// assign switch inputs
const int switchPin1 = 2;
const int switchPin2 = 3;

// variables to hold the value of the switchPins
int switchState1 = 0;
int switchState2 = 0;

// variables to hold previous value of the switch
int prevSwitchState1 = 0;
int prevSwitchState2 = 0;

void setup()
{
  lcd.begin(16, 2);
  Serial.begin(9600);      // open the serial port at 9600 bps:
  pinMode(switchPin1, INPUT_PULLUP);
  pinMode(switchPin2, INPUT_PULLUP);
  //start();
}

void loop()
{
  /**
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Time: ");
    time = ((millis() + 500) / 1000);
    //prints time since program started
    lcd.print(time);
    // wait a second so as not to send massive amounts of data
    delay(1000);
  */

  switchState1 = digitalRead(switchPin1);    // check the status of the switch
  if (switchState1 != prevSwitchState1)         // compare the switchState to its previous state
  {
    if (switchState1 == LOW)
    {
      boom();
    }
  }
  prevSwitchState1 = switchState1;          // save the current switch state as the last state

  switchState2 = digitalRead(switchPin2);
  if (switchState2 != prevSwitchState2)         // compare the switchState to its previous state
  {
    if (switchState2 == LOW)
    {
      newCount();
    }
  }
  prevSwitchState2 = switchState2;
}

void start()
{
  forStart();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Waiting... ");

  //period = ((millis() - startTime) / 1000);
  //lcd.print(period);

  lcd.setCursor(0, 1);
  lcd.print("seconds.");
}

void boom()
{
  forBoom();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("BOOM! Press 2");
  lcd.setCursor(0, 1);
  lcd.print("to continue.");
  while (switchState2 = prevSwitchState2)
  {
    switchState2 = digitalRead(switchPin2);    // check the status of the switch
    prevSwitchState2 = switchState2;            // save the current switch state as the last state
    period1 = (int)((millis() - startTime1) / 1000);
    if ((int)period1 != seconds1)
    {
      seconds1 = (int)period1;
    }
  }
}

void newCount()
{
  newReset();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Waited: ");
  lcd.print(seconds1);
  lcd.print(" secs.");
  lcd.setCursor(0, 1);
  lcd.println("Reset: ");
  
  while (switchState1 = prevSwitchState1)
  {
    switchState1 = digitalRead(switchPin1);    // check the status of the switch
    prevSwitchState1 = switchState1;            // save the current switch state as the last state
    period2 = ((millis() - startTime2) / 1000);
    if (period2 != seconds2)
    {
      seconds2 = period2;
      lcd.print(period2);
    }
  }
}

void forStart()
{
  startTime = millis();
  seconds = 0;
}

void forBoom()
{
  startTime1 = millis();
  seconds1 = 0;
  switchState2 = digitalRead(switchPin2);    // check the status of the switch
  prevSwitchState2 = switchState2;         // save the current switch state as the last state
}

void newReset()
{
  startTime2 = millis();
  seconds2 = 0;
  switchState1 = digitalRead(switchPin1);    // check the status of the switch
  prevSwitchState1 = switchState1;         // save the current switch state as the last state
}

To be clarified, my goal with this project is if you were here to see my arduino in person -

LCD display shows 1st message on 16x2 screen with counter-

"Waiting... X (counter starts)
seconds."

press 1st button

"BOOM! Press button 2
to continue." (counter starts for 2nd button)

press 2nd button

"Waited: X secs (result of counter from 1st button)
Reset: X secs" (new counter starts)

I don't understand your requirements. Is what you want to do:

  1. Display an initial message. Something like "Push button 1 to start timer"
  2. Wait for button 1.
  3. When button 1 is pushed, start a timer. Display a new message like: "Counting. Push button 2 to stop"
  4. Wait for button 2.
  5. When button 2 is pushed, stop the timer. Display a message: "Timer ran for XX seconds, Push button 1 to restart the time."
  6. Reset the timer value.

and start again, but at step 2.