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