Trap timer with RTC

I'm a beginner. I've seem similar things, but not understood or found the answers I need. I have an Uno and a DS3231. I'm working on a trap timer circuit based on another stopwatch but with 2 mutually exclusive buttons. I would like to use the DS3231 to make it better than using Arduino millis(0). From what I understand, the DS3231 does not provide below seconds, but does produce 32 Khz. Could I count how many of those and do sums? Maybe too many. One of the outputs I want will be a timestamp to serial. Pretty sure the DS3231 will provide that, but not made it work yet.

Please define "better"

The DS3231 will be a more accurate time keeper than the arduino (seconds per year vs seconds per day), but the arduino runs at 16MHz so has much more resolution (4 usec). What is the timescale you are trying to measure?

Thanks. Likely to be less than a minute max. Usually a few seconds. Needs MS as best I can Maybe I don't need DS 3231 except for real timestamp on print output?

Yeah, I would just use millis() or micros() for your timing and the DS3231 for the actual timestamp data.

IF the accuracy is super critical, I suppose you could calibrate you arduino by measuring how many milliseconds or microseconds it counted in a given time interval which was defined by the DS3231, but that sounds like a lot of work for little/no reward.

Thanks again. Can I ask you, can you see my project? I'm having trouble getting the stopwatch to see the RTC. Tried some of the code in various places and it compiles, but the program does not run. Tried various libs. I think the relevant bit's I'm trying to add are:
#include "RTClib.h"
RTC_DS3231 rtc;
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}

DateTime now = rtc.now();

I may have missed the begin. I will fiddle a bit more.

You have not posted your code, so no, I can not see it. Start with wiring up the RTC. The RTClib library has many examples. Try them. You can also download the i2c scanner library which will scan the i2c bus and report any devices it finds. It must find your RTC or else you don't have it wired correctly.

Hi,
I had uploaded my project, but I'm not sure how to make it public.
protobikes - Arduino Project Hub

I'll have another look at what you suggest.

I find the if (! rtc.begin()) {Serial.println("Couldn't find RTC");
while (1);
}
code is working. I get the error if it isn't connected, but maybe it will still do that without being able to read from it.

take a few moments and read this: How to get the best out of this forum - Using Arduino / Installation & Troubleshooting - Arduino Forum
And then post your code here using code tags.
Same goes for any warnings/error messages you get when compiling.
Same goes for any output you see on Serial Monitor when running.

Thanks, I'll read up.

I'm using an Arduino R3, with LCD Keypad Shield and DS3231. My code is below. Various libs I was unsure about. // Serial.print(now.day(), DEC); does not work if included. Not sure where to get/setup.

/*

  Standalone Arduino StopWatch

  By Conor M - 11/05/15

  Modified by Elac - 12/05/15

  Modified By Conor M - 12/05/15

  Mofified by Jonathan Woolrich (Protobikes) Jan 2022

*/

// call the necessary libraries

#include <Wire.h>
#include "WireRtcLib.h"
#include "RTClib.h"
// #include <DS3231.h>
#include <SPI.h>
#include <LiquidCrystal.h>
#include <HardwareSerial.h>
// these are the pins used on the shield for this sketch
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);
RTC_DS3231 rtc;
// variables used on more than 1 function need to be declared here
// WireRtcLib rtc;
unsigned long start, finished, elapsed;
boolean r = false;
// Variables for button debounce time
long lastButtonPressTime = 0; // the last time the button was pressed
long debounceDelay = 50; // the debounce time; keep this as low as possible
float h, m, s, ms;

void setup()
{
  Serial.begin(9600); // open the serial port at 9600 bps:
  lcd.begin(16, 2); // inicialize the lcd (16 chars, 2 lines)

  // a little introduction :)
  lcd.setCursor(4, 0); // set the cursor to first character on line 1 - NOT needed (it sets automatically on lcd.begin()
  lcd.print("Arduino");
  lcd.setCursor(3, 1); // set the cursor to 4th character on line 2
  lcd.print("StopWatch");
  delay(2000); // wait 2 seconds
  lcd.clear(); // clear the display
  lcd.print(" Select to Start");
  lcd.setCursor(0, 1); // set the cursor to 3rd character on line 2
  lcd.print("  Left to Stop");
  // rtc.begin();
  // WireRtcLib::tm* t = rtc.getTime();
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
}

void loop()
{
  DateTime now = rtc.now();
  CheckStartStop();
  DisplayResult();
}

void CheckStartStop()
{ // 1
  int x = analogRead (0); // assign 'x' to the Arduino's AnalogueInputs (Shield's buttons)
  if ((x < 800 && x > 600 ) && (r == false)) // if the button is SELECT and not timing
  { // 2
    start = millis();        // saves start time to calculate the elapsed time
    if ((millis() - lastButtonPressTime) > debounceDelay)
    { // 3
      if (r == false)
      { // 4
        lcd.clear();
        lcd.setCursor(3, 0); // needed
        lcd.print("  Timing");
        r = true;
      }                        // E4
    }                       // E3
    lastButtonPressTime = millis();
  }                       // E2
  else if ((r == true) && (x < 600 && x > 400)) //If timing and Left button pressed
  {
    lcd.setCursor(2, 0); // needed
    lcd.print("   Result  ");
    r = false;                // Reset
    finished = millis(); // saves stop time to calculate the elapsed time
    lastButtonPressTime = millis();
    // print result to serial port.
    Serial.print("Time: ");
    Serial.print(h, 0);
    Serial.print("h ");
    Serial.print(m, 0);
    Serial.print("m ");
    Serial.print(s, 0);
    //Serial.print("s ");
    Serial.print(".");
    Serial.print(ms, 0);
    //Serial.print("ms ");
    Serial.print("s Timestamp ");
    // Serial.print(now.day(), DEC);
    Serial.println();
    Serial.println();
    Serial.println();
    Serial.println();
    Serial.println();
    Serial.println();
    Serial.println();
    Serial.println();
    Serial.println();
    Serial.println();
  }
}                       // E1

void DisplayResult()
{
  // float h, m, s, ms;
  if (r == true)          // timing in progress
  { //2
    finished = millis(); // saves stop time to calculate the elapsed time
    unsigned long over;

    // MATH time!!!
    elapsed = finished - start;

    h = int(elapsed / 3600000);
    over = elapsed % 3600000;
    m = int(over / 60000);
    over = over % 60000;
    s = int(over / 1000);
    ms = over % 1000;
    lcd.setCursor(0, 1);
    lcd.print(h, 0); // display variable 'h' - the 0 after it is the number of algorithms after a comma (ex: lcd.print(h, 2); would print 0,00
    lcd.print("h "); // and the letter 'h' after it
    lcd.print(m, 0);
    lcd.print("m ");
    lcd.print(s, 0);
    lcd.print("s ");
    if (h < 10)
    { //3
      lcd.print(ms, 0);
      lcd.print("ms ");
    }                  //e3
  }                  //e2
}                  //e1

Something like this should get you close {Note: I increased the baud rate to a modern value - adjust Serial Monitor to match]

#include "RTClib.h"
#include <LiquidCrystal.h>

// these are the pins used on the shield for this sketch
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);
RTC_DS3231 rtc;

// variables used on more than 1 function need to be declared here
unsigned long start, finished;

void setup() {
  Serial.begin(115200);
  lcd.begin(16, 2); // inicialize the lcd (16 chars, 2 lines)

  // a little introduction :)
  lcd.setCursor(4, 0); // set the cursor to first character on line 1 - NOT needed (it sets automatically on lcd.begin()
  lcd.print("Arduino");
  lcd.setCursor(3, 1); // set the cursor to 4th character on line 2
  lcd.print("StopWatch");
  delay(2000); // wait 2 seconds
  lcd.clear(); // clear the display
  lcd.print(" Select to Start");
  lcd.setCursor(0, 1); // set the cursor to 3rd character on line 2
  lcd.print("  Left to Stop");
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
}

enum { START, TIMING, STOPPED };
int state = START;

void loop() {
  CheckStartStop();
}

void CheckStartStop()
{
  int x = analogRead(A0);

  switch (state) {
    case START:   // waiting to start
      // if the button is SELECT then begin
      if (x < 800 && x > 600 ) {
        start = millis();        // saves start time to calculate the elapsed time
        lcd.clear();
        lcd.setCursor(3, 0); // needed
        lcd.print("  Timing");
        state = TIMING;
      }
      break;

    case TIMING:  // running
      //If Left button pressed, then stop
      if (x < 600 && x > 400) {
        finished = millis(); // saves stop time to calculate the elapsed time
        start = STOPPED;
      }
      break;

    case STOPPED:   // finished, display results
      DisplayResult(finished - start);
      state = START;
      break;
  }
}


void DisplayResult(unsigned long elapsed) {
  int  h = elapsed / (60 * 60 * 1000UL);
  elapsed %= 60 * 60 * 1000UL;
  int m = elapsed / (60 * 1000UL);
  elapsed %= 60 * 1000UL;
  int s = elapsed / 1000UL;
  int ms = elapsed % 1000UL;

  char buffer[15];

  sprintf( buffer, "%02d:%02d:%02d.%03d", h, m, s, ms );
  lcd.setCursor(0, 1);
  lcd.print(buffer);

  DateTime now = rtc.now();

  Serial.println(now.timestamp(DateTime::TIMESTAMP_FULL));  // FULL
  Serial.println(now.timestamp(DateTime::TIMESTAMP_DATE));  // date
  Serial.println(now.timestamp(DateTime::TIMESTAMP_TIME));  // time

  Serial.print( " - " );
  Serial.println(buffer);
}

Thanks. I'm having a play. Not running so far. I was using 9600 for the 2 x dot matrix thermal printers the project will run. I find they will do 19200, but not more. By the look, I don't think this will show timing continuously, which is a nice feature of what I had. This project is to replace an existing timer someone else made, which has some unwanted "features"..
The use environment is quite difficult, with up to 100 machines arriving at varying, often short intervals. A clear indication timing is going on should be a help. I'm thinking of a buzzer as well. Long way to go, but I wanted to get the core program running.

Nothing on serial monitor. I wonder if these have anything to do with why?
java.io.IOException: jssc.SerialPortException: Port name - COM4; Method name - setEventsMask(); Exception type - Can't set mask.
at processing.app.Serial.dispose(Serial.java:171)
at processing.app.SerialMonitor.close(SerialMonitor.java:147)
at processing.app.AbstractMonitor.suspend(AbstractMonitor.java:113)
at processing.app.Editor$UploadHandler.run(Editor.java:2055)
at java.lang.Thread.run(Thread.java:748)
Caused by: jssc.SerialPortException: Port name - COM4; Method name - setEventsMask(); Exception type - Can't set mask.
at jssc.SerialPort.setEventsMask(SerialPort.java:279)
at jssc.SerialPort.removeEventListener(SerialPort.java:1064)
at jssc.SerialPort.closePort(SerialPort.java:1090)
at processing.app.Serial.dispose(Serial.java:168)
... 4 more
Invalid library found in C:\Users\Proto\OneDrive\Documents\Arduino\libraries\Blink: no headers files (.h) found in C:\Users\Proto\OneDrive\Documents\Arduino\libraries\Blink
Invalid library found in C:\Users\Proto\OneDrive\Documents\Arduino\libraries\Blink: no headers files (.h) found in C:\Users\Proto\OneDrive\Documents\Arduino\libraries\Blink
Invalid library found in C:\Users\Proto\OneDrive\Documents\Arduino\libraries\Blink: no headers files (.h) found in C:\Users\Proto\OneDrive\Documents\Arduino\libraries\Blink
Invalid library found in C:\Users\Proto\OneDrive\Documents\Arduino\libraries\Blink: no headers files (.h) found in C:\Users\Proto\OneDrive\Documents\Arduino\libraries\Blink
Invalid library found in C:\Users\Proto\OneDrive\Documents\Arduino\libraries\Blink: no headers files (.h) found in C:\Users\Proto\OneDrive\Documents\Arduino\libraries\Blink

Compile got a lot better when I put the baud rate back to 9600. I added code

        lcd.clear();
        lcd.setCursor(3, 0); // needed
        lcd.print("  Finished");

to case TIMING and it works on the LCD, so case STOPPED is probably not working. Will add a tag to that.

Sorry for all the waffle. Not persuaded the Case statement to work in that version, but stole the timestamp print lines and put into my program. Result looks like this:

Time: 0h 1m 23.510s Timestamp 2022-01-05T23:04:43

Not sure where the last T came from, and order of date is not what I prefer, but it works. I'm guessing the layout is in RTClib.h, if I can track it down.

Now got

Time: 0h 0m 9.240s Timestamp 2022-01-05 23:31:49.

Order is from lib.

Project is now public. Trap Timer for Cycling Sprints - Arduino Project Hub

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