Adding stop/start button and reset button to stopwatch

yes you are right ,thanks for detecting thst

#include "RTClib.h"
//Setup the Real Time Clock, DS3231
RTC_DS3231 rtc;

const byte SQWinput = 2;  // Must be External Interrupt

volatile uint32_t  MillisecondsAtStartOfSecond = 0;
 
 unsigned long secondss=0 ;
 unsigned long minutess=0 ;

const byte StartButtonPin = 7;  // Button wired from pin to GND
const byte StopResetButtonPin = 3; // Button wired from pin to GND
bool StartButtonWasPressed = false;
bool StopResetButtonWasPressed = false;

unsigned long DebounceTimer = 0;
const unsigned DebounceTime = 10;

bool IssRunning = false;
unsigned long ElapsedTime = 0;
unsigned long LastStartTime = 0;


 
 unsigned long  hourss =0;
 unsigned long ms;

boolean passed_second=true;
boolean startt=true;





const byte resetButton = 3;
// Instantiate another Bounce object


const char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

// The SQW pin, when set to 1 Hz mode, has a falling edge at the beginning of every second.
void SQWFallingISR()
{
  MillisecondsAtStartOfSecond = millis();
}

void setup ()
{
  Serial.begin(9600); // Set Serial Monitor to 115200
  delay(200);

  pinMode(7, INPUT);
  digitalWrite(7, HIGH);
  pinMode(3, INPUT);
  digitalWrite(3, HIGH);
 


  
  if (! rtc.begin())
  {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }

  if (rtc.lostPower())
  {
    Serial.println("RTC lost power, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2022, 4, 03, 21, 14, 0));
  }

  // Configure SQW pin on the DS3231 to output a 1Hz squarewave 
  rtc.writeSqwPinMode(DS3231_SquareWave1Hz);

  // Get MillisecondsAtStartOfSecond on the falling edge of SQW.
  attachInterrupt(digitalPinToInterrupt(SQWinput), SQWFallingISR, FALLING);
}



void loop ()
{
  DateTime now = rtc.now();


   unsigned long currentTime = millis();

  bool startButtonIsPressed = digitalRead(StartButtonPin) == LOW;
  bool stopResetButtonIsPressed = digitalRead(StopResetButtonPin) == LOW;

 

  // State Change Detection and debounce
    if (startButtonIsPressed != StartButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime)
  {
    // Button has changed state
    StopResetButtonWasPressed = stopResetButtonIsPressed;
    DebounceTimer = currentTime;

    if (stopResetButtonIsPressed)
    {
      // Just Pressed STOP/RESET
      if (IssRunning)
      {
        // Pausing the timer
        IssRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
      }
      else
      {
        // Was not running so reset everything
        ElapsedTime = 0;
        IssRunning = false;
      }
    }
  }

  // Get time since last reset
 
  noInterrupts();
  // How long since the second started?
  
 
  // State Change Detection and debounce
  if (startButtonIsPressed != StartButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime)
  {
    // Button has changed state
    StartButtonWasPressed = startButtonIsPressed;
    DebounceTimer = currentTime;

    if (startButtonIsPressed)
    {
      // Just Pressed START
      if (!IssRunning)
      {  
         interrupts();

        // Starting/Restarting the timer
        LastStartTime = currentTime;
        IssRunning = true;
      }
      else
      {
        // Pausing the timer
        IssRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
      }
    }
  }

  // State Change Detection and debounce
  if (stopResetButtonIsPressed != StopResetButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime)
  {
    // Button has changed state
    StopResetButtonWasPressed = stopResetButtonIsPressed;
    DebounceTimer = currentTime;

    if (stopResetButtonIsPressed)
    {
      // Just Pressed STOP/RESET
      if (IssRunning)
      {
        // Pausing the timer
        IssRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
      }
      else
      {
        // Was not running so reset everything
        ElapsedTime = 0;
        IssRunning = false;
      }
    }
  }

   unsigned long DisplayTime;
  if (IssRunning)
    DisplayTime = ElapsedTime + (currentTime - LastStartTime);
  else
    DisplayTime = ElapsedTime;

  unsigned long hundredths = DisplayTime / 10;
  unsigned long secondss = hundredths / 100;
  unsigned long minutess = secondss / 60;
  int hourss = minutess / 60;
  int clok;

  if (secondss < 100)
    {// Display seconds.hundredths up to 100 seconds, then minutes:seconds
    clok = (secondss % 100) * 100 + (hundredths % 100);
      Serial.println(clok);
}
  else if (minutess < 100)
  {  // Display minutes:seconds up to 100 minutes, then hours/minutes
    clok = (minutess % 100) * 100 + (secondss % 60);
    Serial.println(clok);}
  else{
    clok = (hourss % 100) * 100 + (minutess % 60);
    Serial.println(clok);}

  // Clear all segments before enabling a digit
 

  // Display each digit, right to left
  
    // Peel a digit off the low end of the number
    int digit = clok % 10;
    clok /= 10;

    // Blank the MSD if it is zero
    
    
      // Display the digit on the seven segments
     

    if (secondss < 100)
    {
      // Steady decimal point when showing seconds and hundredths
   
    }
    else if (minutess < 100)
    {
      // Steady colon when showing minutes and seconds

    }
    else
    {
      // Make the colon blink each second
   
    }

    // Turn on the digit briefly

  
}

it is now jsut displaying zero

what is the problem ,it is so confusing

Maybe this will help. It's the Stopwatch code with all of the Seven-Segment display parts removed. Output is via Serial Monitor.

/////////////////////////////////////
//  Stopwatch Example
//
//  Written by: John Wasser
/////////////////////////////////////
const byte StartButtonPin = A1;  // Button wired from pin to GND
const byte StopResetButtonPin = A2; // Button wired from pin to GND

bool StartButtonWasPressed = false;
bool StopResetButtonWasPressed = false;

unsigned long DebounceTimer = 0;
const unsigned DebounceTime = 10;

bool IsRunning = false;
unsigned long ElapsedTime = 0;
unsigned long LastStartTime = 0;

static void ShowTheTime()
{
  static unsigned long lastDisplayTime = 0;
  unsigned long displayTime = ElapsedTime;
  if (IsRunning)
    displayTime += millis() - LastStartTime;

  if (displayTime != lastDisplayTime)
  {
    lastDisplayTime = displayTime;

    // This is where you would put your code to display the time
    Serial.println(displayTime / 1000.0, 3);
  }
}

void setup()
{
  Serial.begin(115200);
  delay(200);

  pinMode(StartButtonPin, INPUT_PULLUP);
  pinMode(StopResetButtonPin, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentTime = millis();

  bool startButtonIsPressed = digitalRead(StartButtonPin) == LOW;
  bool stopResetButtonIsPressed = digitalRead(StopResetButtonPin) == LOW;

  // State Change Detection and debounce
  if (startButtonIsPressed != StartButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime)
  {
    // Button has changed state
    StartButtonWasPressed = startButtonIsPressed;
    DebounceTimer = currentTime;

    if (startButtonIsPressed)
    {
      // Just Pressed START
      if (!IsRunning)
      {
        // Starting/Restarting the timer
        LastStartTime = currentTime;
        IsRunning = true;
        Serial.println("Started");
      }
      else
      {
        // Pausing the timer
        IsRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
        Serial.println("Paused");
      }
    }
  }

  // State Change Detection and debounce
  if (stopResetButtonIsPressed != StopResetButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime)
  {
    // Button has changed state
    StopResetButtonWasPressed = stopResetButtonIsPressed;
    DebounceTimer = currentTime;

    if (stopResetButtonIsPressed)
    {
      // Just Pressed STOP/RESET
      if (IsRunning)
      {
        // Pausing the timer
        IsRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
        Serial.println("Stopped");
      }
      else
      {
        // Was not running so reset everything
        ElapsedTime = 0;
        IsRunning = false;
        Serial.println("Reset");
      }
    }
  }

  ShowTheTime();
}

@johnwasser

that is very helpful

will give it a try BIG THANK U :clap:

it is working perfectly

but how can it be based on sq wave output from RTC chip?

this is the stumbling block now

You could measure the drift of the millis() value relative to the RTC and calculate a correction. You already had part of that:

Just expand that to calculate drift:

volatile long  TotalAdjustment = 0;

// The SQW pin, when set to 1 Hz mode, has a falling edge at the beginning of every second.
void SQWFallingISR()
{
  static unsigned long previousSecondMillis = 0;
  unsigned long nowMillis = millis();
  // How many extra millis() in this second?
  int drift = nowMillis - (previousSecondMillis + 1000);
  // Subtract the extra millis.
  TotalAdjustment -= drift;
  previousSecondMillis = nowMillis;
}

Then write a function to fetch adjusted millis():

unsigned long AdjustedMillis()
{
  noInterrupts();
  unsigned long am = millis() + TotalAdjustment;
  interrupts();
  return am;
}

Use AdjustedMillis() in the rest of the sketch.

that is amazing ,you are really specialised :clap:

i will complete it and give it a try

hoping that the rest of members here get benfit from all of your help in this topic(extensive workshop in stop watch)

it is working perfectly

here is the full sketch

/////////////////////////////////////
//  Stopwatch Example
//
//  Written by: John Wasser
/////////////////////////////////////
const byte StartButtonPin = 7;  // Button wired from pin to GND
const byte StopResetButtonPin = 3; // Button wired from pin to GND

bool StartButtonWasPressed = false;
bool StopResetButtonWasPressed = false;

unsigned long DebounceTimer = 0;
const unsigned DebounceTime = 10;

volatile uint32_t  MillisecondsAtStartOfSecond = 0;
volatile long  TotalAdjustment = 0;

bool IsRunning = false;
unsigned long ElapsedTime = 0;
unsigned long LastStartTime = 0;

void SQWFallingISR()
{
  static unsigned long previousSecondMillis = 0;
  unsigned long nowMillis = millis();
  // How many extra millis() in this second?
  int drift = nowMillis - (previousSecondMillis + 1000);
  // Subtract the extra millis.
  TotalAdjustment -= drift;
  previousSecondMillis = nowMillis;
}

unsigned long AdjustedMillis()
{
  noInterrupts();
  unsigned long am = millis() + TotalAdjustment;
  interrupts();
  return am;
}

static void ShowTheTime()
{
  static unsigned long lastDisplayTime = 0;
  unsigned long displayTime = ElapsedTime;
  if (IsRunning)
    displayTime += AdjustedMillis()- LastStartTime;

  if (displayTime != lastDisplayTime)
  {
    lastDisplayTime = displayTime;

    // This is where you would put your code to display the time
    Serial.println(displayTime / 1000.0, 3);
  }
}

void setup()
{
  Serial.begin(115200);
  delay(200);

  pinMode(StartButtonPin, INPUT_PULLUP);
  pinMode(StopResetButtonPin, INPUT_PULLUP);
}

void loop()
{
  unsigned long currentTime = millis();

  

  
  bool startButtonIsPressed = digitalRead(StartButtonPin) == LOW;
  bool stopResetButtonIsPressed = digitalRead(StopResetButtonPin) == LOW;

  // State Change Detection and debounce
  if (startButtonIsPressed != StartButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime)
  {
    // Button has changed state
    StartButtonWasPressed = startButtonIsPressed;
    DebounceTimer = currentTime;

    if (startButtonIsPressed)
    {
      // Just Pressed START
      if (!IsRunning)
      {
        // Starting/Restarting the timer
        LastStartTime = currentTime;
        IsRunning = true;
        Serial.println("Started");
      }
      else
      {
        // Pausing the timer
        IsRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
        Serial.println("Paused");
      }
    }
  }

  // State Change Detection and debounce
  if (stopResetButtonIsPressed != StopResetButtonWasPressed &&
      currentTime - DebounceTimer > DebounceTime)
  {
    // Button has changed state
    StopResetButtonWasPressed = stopResetButtonIsPressed;
    DebounceTimer = currentTime;

    if (stopResetButtonIsPressed)
    {
      // Just Pressed STOP/RESET
      if (IsRunning)
      {
        // Pausing the timer
        IsRunning = false; // Paused
        ElapsedTime += currentTime - LastStartTime;
        Serial.println("Stopped");
      }
      else
      {
        // Was not running so reset everything
        ElapsedTime = 0;
        IsRunning = false;
        Serial.println("Reset");
      }
    }
  }

  ShowTheTime();
}

BIG THANK YOU :100:

YOU A REAL EXPERT :clap: :clap:

You missed one.

Yes you are right it should be AdjustedMillis() instead