#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
}
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;
}