Timer without delay()

I have written a code for a stopwatch to run on LCD screen (when button pressed, it starts), but I have used delay(). Is there a way to perform it without delay()?

#include<LiquidCrystal.h>

int timerMode = 0;
long startTime;

int buttonPin1 = 2;

void setup() {
  // turn on internal pull-up resistor
  pinMode( buttonPin1, INPUT_PULLUP );
  LiquidCrystal lcd(5, 6, A5, A4, A3, A2);
}

void loop() {
  lcd.setCursor(0, 1);
  if (buttonValue1 == LOW) {
    startTime = millis();
    timerMode++;
    delay(400);
  }


  if (timerMode == 1) {
    lcd.setCursor(0, 1);
    lcd.print("Time : ");
    lcd.setCursor(7, 1);
    lcd.print((millis() - startTime) / 1000.0);
    lcd.setCursor(12, 1);
    lcd.print(" sec");
  }
  if (timerMode > 1) {
    delay(6000);
    timerMode = 0;
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print("TIMER");
    }
}

What is timerMode ? Is that a variable that tells what state the sketch is in ? You could call it "state". Give it a number, such as 1, 2, 3 and don't increment it.
Do you want to start when a button is pressed or when a button is released ? You can already read about the State Change Detection.
Do you want to add a 'pause' button ?

I suppose you know the Blink Without Delay ?
You need two variables. A unsigned long previousMillis as a timestamp when the timer was started. And a variable that tells when the stopwatch is running/active (it can also be a 'state' variable).

Please show a full sketch that we can try.

You may want to Google Arduino State Machine too.

I've edited the initial post to include full code.

Not quite all there :wink: .

Does your sketch compile ?


Edit:
How is the stop watch supposed to work ?
You push the switch to start the clock then push the switch a second time to stop the clock ?

Yes exactly

IS your display 16X2 ?

Here is an old version of a Stop Watch sketch:

//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()

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

yes, it's 16x2

A sketch is offered in post #9.

How to write Timers and Delays in Arduino
and
Multi-tasking in Arduino
should be of help.
and for button debounce Debouncing Switches in Arduino

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