Push Button Timer with LCD and reset button

Hi,

I'm looking to create a basic Timer / stop watch that uses a push button. I would like to display on a 16×2 parallel LCD how long the push button was pressed down for. Then be able to reset the screen with a second push button and be able to run the test again.

I'm not the greatest at programming but I have gotten my UNO R3 to connect and I loaded the inputdebounce library. So far I got the serial monitor to show how long the button was pressed, I just don't know where to go from here. Any help would be great.

Here is the code I found to show the time that the pushbutton is pressed.

/*
Test InputDebounce Arduino Library
Mario Ban, 05.2015
GitHub - Mokolea/InputDebounce: Simple polling input debounce Arduino library.
Copyright 2017 Mario Ban
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "InputDebounce.h"

#define BUTTON_DEBOUNCE_DELAY 20 // [ms]

static const int pinLED = LED_BUILTIN; // 13
static const int pinSwitch = 2;

static InputDebounce buttonTest; // not enabled yet, setup has to be called later

void setup()
{
// initialize digital pin as an output
pinMode(pinLED, OUTPUT);

// init serial
Serial.begin(9600);

Serial.println("Test InputDebounce library");

// setup input button (debounced)
buttonTest.setup(pinSwitch, BUTTON_DEBOUNCE_DELAY, InputDebounce::PIM_INT_PULL_UP_RES);

// examples
// buttonTest.setup(pinSwitch);
// buttonTest.setup(pinSwitch, DEFAULT_INPUT_DEBOUNCE_DELAY);
// buttonTest.setup(pinSwitch, BUTTON_DEBOUNCE_DELAY, InputDebounce::PIM_EXT_PULL_UP_RES);
}

void loop()
{
static unsigned int buttonTest_StateOnCount = 0; // to handle new pressed state, and still pressed state
static unsigned int buttonTest_OnTimeLast = 0; // to handle new released state, and remember last on-time (button pressed)

unsigned long now = millis();

// poll button state, return continuous on-time [ms] if pressed (debounced)
unsigned int buttonTest_OnTime = buttonTest.process(now);

// handle input button
if(buttonTest_OnTime) {
// save current on-time (button pressed), to be used when released
buttonTest_OnTimeLast = buttonTest_OnTime;
// check for state change
unsigned int count = buttonTest.getStatePressedCount();
if(buttonTest_StateOnCount != count) {
buttonTest_StateOnCount = count;
// handle pressed state
digitalWrite(pinLED, HIGH); // turn the LED on
Serial.print("HIGH");
}
else {
// handle still pressed state
Serial.print("HIGH still pressed");
}
Serial.print(" (");
Serial.print(buttonTest_OnTime);
Serial.println("ms)");
}
else {
if(buttonTest_OnTimeLast) {
// handle released state
digitalWrite(pinLED, LOW); // turn the LED off
Serial.print("LOW (last on-time: HIGH ");
Serial.print(buttonTest_OnTimeLast);
Serial.println("ms)");
buttonTest_OnTimeLast = 0; // reset, do not handle this released state again
}
}

delay(1); // [ms]
}

Take what you want:


//Forum URL  https://forum.arduino.cc/t/timer-without-delay/882316?u=larryd

// Version    YY/MM/DD  Description
// 1.00       20/09/06  If your LCD is parallel wired, comment line with the arrows  <-----<<<<<
// 1.01       20/09/09  Functioning sketch
// 1.02       21/07/06  Added LCD pin numbers used by:  @millionish

#define switchIsClosed  LOW

#define flagIsSet       true
#define flagIsReset     false

#define enabled         true
#define disabled        false

//************************************************************************
//select Serial or Parallel LCD option that you have
//************************************************************************

//comment the next line if you have a parallel LCD
//#define serialLCDisBeingUsed //    <-----<<<<<              <-----<<<<<   

#ifdef  serialLCDisBeingUsed

#include <Wire.h>

//Use I2C library:     https://github.com/duinoWitchery/hd44780
//LCD Reference:       https://www.arduino.cc/en/Reference/LiquidCrystal

#include <hd44780.h>   //main hd44780 header

//NOTE:
//hd44780_I2Cexp control LCD using I2C I/O expander backpack (PCF8574 or MCP23008)
//hd44780_I2Clcd control LCD with native I2C interface (PCF2116, PCF2119x, etc...)

#include <hd44780ioClass/hd44780_I2Cexp.h> //I2C expander i/o class header

//         LCD I2C PCB
// * LCD I2C pin 1     to GND
// * LCD I2C pin 2     to +5V
// * LCD I2C pin 3     SDA, UNO A4
// * LCD I2C pin 4     SCL, UNO A5

//If you do not know what your I2C address is, first run the 'I2C_Scanner' sketch
hd44780_I2Cexp lcd(0x3F);
//hd44780_I2Cexp lcd(0x27);

//************************************************************************
#else

#include <LiquidCrystal.h>

//        Common used LCD circuit
// * LCD RS pin 4,     to digital pin 7
// * LCD Enable pin 6, to digital pin 6
// * LCD D4 pin 11,    to digital pin 5
// * LCD D5 pin 12,    to digital pin 4
// * LCD D6 pin 13,    to digital pin 3
// * LCD D7 pin 14,    to digital pin 2
//
// * LCD pin 1 VSS     to GND
// * LCD pin 2 VDD     to +5V
// * LCD pin 5 R/W     to GND
// * LCD pin 15 'A'    to back light resistor (if not on PCB) to +5V
// * LCD pin 16 'K'    to GND
//
// * 10K Potentiometer:
// * both ends to ground,
// * wiper to LCD VO, LCD pin 3
//
//                  R  E  D  D  D  D
//                  S  N  4  5  6  7
//LiquidCrystal lcd(7, 6, 5, 4, 3, 2);


LiquidCrystal lcd(5, 6, A5, A4, A3, A2);

//  N O T E  make sure these do not conflict with the pins used below

#endif
//************************************************************************


bool switchFlag               = flagIsReset;

byte lastSwitchState;

const byte heartbeatLED       = 13;
const byte mySwitch           = 2;

//timing stuff
unsigned long heartbeatMillis;
unsigned long switchMillis;
unsigned long startMillis;
unsigned long updateMillis;

//Finite Sate Machine definition
enum Machine {POWERUP, STARTUP, TIMING, LOCKLCD};
Machine SM = POWERUP;

//************************************************************************
void setup()
{
  lcd.begin(16, 2);   // <-----<<<<<  Make changes for the size of the LCD

  pinMode(heartbeatLED, OUTPUT);

  //turn on internal pull-up resistor
  pinMode( mySwitch, INPUT_PULLUP );

} //END of setup()


//************************************************************************
void loop()
{
  //***********************
  //time to toggle the heartbeatLED ?
  if (millis() - heartbeatMillis >= 500)
  {
    //restart the TIMER
    heartbeatMillis = millis();

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //***********************
  //time to check the switches ?
  if (millis() - switchMillis >= 50)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();
  }

  //***********************
  //check the State Machine
  checkMachine();

} //END of loop()


//************************************************************************
void checkSwitches()
{
  //*****************************************    mySwitch
  //
  byte state = digitalRead(mySwitch);

  //***********************
  //has the switch changed state ?
  if (lastSwitchState != state)
  {
    //update to the new state
    lastSwitchState = state;

    //************
    //was the switch pushed ?
    if (state == switchIsClosed)
    {
      switchFlag = flagIsSet;
    }

  } //END of  if (lastSwitchState != state)


} //END of  checkSwitches()


//************************************************************************
void checkMachine()
{
  //update the state machine
  switch (SM)
  {
    case POWERUP:
      lcd.setCursor(0, 0);
      //                   111111
      //         0123456789012345
      lcd.print("   STOPWATCH    ");

      lcd.setCursor(0, 1);
      //                   111111
      //         0123456789012345
      lcd.print(" W a i t i n g  ");

      //next state
      SM = STARTUP;

      break;

    //***********
    case STARTUP:
      //has the user pressed the switch yet ?
      if (switchFlag == flagIsSet)
      {
        switchFlag = flagIsReset;

        //restart the TIMER
        startMillis = millis();

        //next state
        SM = TIMING;
      }

      break;

    //***********
    case TIMING:
      //time to update the LCD (every 50ms)
      if (millis() - updateMillis > 50)
      {
        //restart the TIMER
        updateMillis = millis();

        lcd.setCursor(0, 0);
        //                   111111
        //         0123456789012345
        lcd.print("   STOPWATCH    ");

        lcd.setCursor(0, 1);
        //                   111111
        //         0123456789012345
        lcd.print("Time:           ");

        float Time = (float)(millis() - startMillis) / 1000;

        lcd.setCursor(6, 1);
        //                   111111
        //         0123456789012345
        //         Time: ###.##
        lcd.print(Time); //2 decimal places

        lcd.setCursor(13, 1);
        //                   111111
        //         0123456789012345
        //         Time: ###.## sec
        lcd.print("sec");
      }

      //has the user pressed the switch yet ?
      if (switchFlag == flagIsSet)
      {
        switchFlag = flagIsReset;

        //next state
        SM = LOCKLCD;
      }

      break;

    //***********
    case LOCKLCD:
      //has the user pressed the switch yet ?
      if (switchFlag == flagIsSet)
      {
        switchFlag = flagIsReset;

        //next state
        SM = POWERUP;
      }

      break;

  } //END of switch/case

} //END of checkMachine()

//*********************************************************************

Hi eopett!
Did you transfer the program to your UNO?
did you connect the 2 push-buttons to the pins of your UNO?

Thank you! I ordered the LCD so once it arrives I'll try it out! I will respond soon with an update.

How could we change it so the timer starts and stays timing until the switch is released? Basically act like a closed switch to run it, then when it opens - it stops the timer. Then use a second switch to reset it?

My goal is to use this to measure how long a Load is turned on for. The load will be tied to a transistor which will turn on the stopwatch. Then a seperate button for a reset. Thanks

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