How to use timespan for the RTClib (RTC_DS3231)

Hello,

Good day, Please I am designing a run hour meter, and I am using a DS3231 RTC module, I have gone through the functions to use and the one to work for the desired outcome is TimeSpan();

But when I use it, an error is thrown

"DateTime::TimeSpan() function not defined"

Please, how do i use this function.

Regards

Please post the full sketch that you tried and details of where you got the library as there are many with the same name but different functions

// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include "RTClib.h"

RTC_DS3231 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
int inpin = 2;
int instate;
boolean startWelding = false;
uint32_t run_hour = 0;
uint32_t norun_time = 0;
int timeStart = 0;
int timeStop = 0;

void setup () {
 pinMode(inpin, INPUT_PULLUP);
 Serial.begin(57600);
//  DateTime timeStart = TimeSpan.hours();

#ifndef ESP8266
 while (!Serial); // wait for serial port to connect. Needed for native USB
#endif

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

 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(2014, 1, 21, 3, 0, 0));
 }

 // When time needs to be re-set on a previously configured device, 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(2014, 1, 21, 3, 0, 0));
}

void loop () {
 instate = digitalRead(inpin);
 DateTime now = rtc.now();
 

 Serial.print(now.year());
 Serial.print('/');
 Serial.print(now.month(), DEC);
 Serial.print('/');
 Serial.print(now.day(), DEC);
 Serial.print(" (");
 Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
 Serial.print(") ");
 Serial.print(now.hour(), DEC);
 Serial.print(':');
 Serial.print(now.minute(), DEC);
 Serial.print(':');
 Serial.print(now.second(), DEC);
 Serial.println();
 
 Serial.print("Temperature: ");
 Serial.print(rtc.getTemperature());
 Serial.println(" C");

 if (instate == LOW)
 {
   startWelding = true;
   Serial.println("Welding has started");
   //    Serial.println(String("DateTime::TIMESTAMP_FULL:\t") + now.timestamp(DateTime::TIMESTAMP_FULL));
 } else
 {
   startWelding = false;
   Serial.println("Welding has stopped");
 }

 if (startWelding)
 {
   timeStart = TimeSpan(minutes);
   //    run_hour = timeStart - timeStop;
   startWelding = true;
 }
 else
 {
   if (!startWelding)
   {
     timeStop = now.minute();
     //    timeStop = timeStart;
     startWelding = false;
   }
 }


 run_hour = timeStart;
 norun_time = timeStop - timeStart;
 //  run_hour != timeStop-timeStart;

 Serial.println("Total Run Hour: " + String(timeStart));
 Serial.println(norun_time);
 delay(3000);
}

Come on Ceejay, after over 40 posts and no doubt reading many more you should know better than that how to post code

See Read this before posting a programming question and follow the advice given

1 Like

Okay, take a look now please

Where did you get the RTC_DS3231 library that you are using? Not all RTC libraries have the timespan() function.

AdaFruit have an RTC library, here is the link GitHub - adafruit/RTClib: A fork of Jeelab's fantastic RTC Arduino library

Check to make sure you don't have another library with a file named RTClib.h, I suspect the compiler is trying to use the wrong library. I cannot get your sketch to compile as posted, I'm not getting the error for TimeSpan() but minutes does not appear to be defined anywhere.

Okay, I will check

what are you really trying to do? this feels really weird (although commented out)

//  DateTime timeStart = TimeSpan.hours();

Yes, What are you trying to do with the use of the TimeSpan. It's typically used to return a value in seconds from a days, hours, minutes, seconds input. It's not clear how you are trying to use it in your code, and there may be simpler ways to achieve what you want.

you get a timeSpan object when you do a difference of two DateTime for example. or you can add or subtract a ∆t TimeSpan to/from a DateTime to move from ∆t in time.

here it's really weird, you set the date from the number of hours in a time span ??

J-M-L:
what are you really trying to do? this feels really weird (although commented out)

//  DateTime timeStart = TimeSpan.hours();

What you explained is what I am trying to do, I really do not understand how to go about it, the example code I saw on the RTClib used to timespan function in setup, and I am trying to use it in loop, what i want to achieve is this;

When the welder starts welding, the time is registered, when he stops, the time is registered, the run hour would now be the difference between both times, below is the initial code I used before I discovered timespan.

if (startWelding)
{
timeStart = now.hour();
}
else
{
if (!startWelding)
{
timeStop = now.hour();
}
}

run_hour = timeStop - timeStart;

Serial.println(run_hour);

This is the example code from the library

// Simple date conversions and calculations

#include "RTClib.h"

void showDate(const char* txt, const DateTime& dt) {
  Serial.print(txt);
  Serial.print(' ');
  Serial.print(dt.year(), DEC);
  Serial.print('/');
  Serial.print(dt.month(), DEC);
  Serial.print('/');
  Serial.print(dt.day(), DEC);
  Serial.print(' ');
  Serial.print(dt.hour(), DEC);
  Serial.print(':');
  Serial.print(dt.minute(), DEC);
  Serial.print(':');
  Serial.print(dt.second(), DEC);

  Serial.print(" = ");
  Serial.print(dt.unixtime());
  Serial.print("s / ");
  Serial.print(dt.unixtime() / 86400L);
  Serial.print("d since 1970");

  Serial.println();
}

void showTimeSpan(const char* txt, const TimeSpan& ts) {
  Serial.print(txt);
  Serial.print(" ");
  Serial.print(ts.days(), DEC);
  Serial.print(" days ");
  Serial.print(ts.hours(), DEC);
  Serial.print(" hours ");
  Serial.print(ts.minutes(), DEC);
  Serial.print(" minutes ");
  Serial.print(ts.seconds(), DEC);
  Serial.print(" seconds (");
  Serial.print(ts.totalseconds(), DEC);
  Serial.print(" total seconds)");
  Serial.println();
}

void setup () {
  Serial.begin(57600);

#ifndef ESP8266
  while (!Serial); // wait for serial port to connect. Needed for native USB
#endif

  DateTime dt0 (0, 1, 1, 0, 0, 0);
  showDate("dt0", dt0);

  DateTime dt1 (1, 1, 1, 0, 0, 0);
  showDate("dt1", dt1);

  DateTime dt2 (2009, 1, 1, 0, 0, 0);
  showDate("dt2", dt2);

  DateTime dt3 (2009, 1, 2, 0, 0, 0);
  showDate("dt3", dt3);

  DateTime dt4 (2009, 1, 27, 0, 0, 0);
  showDate("dt4", dt4);

  DateTime dt5 (2009, 2, 27, 0, 0, 0);
  showDate("dt5", dt5);

  DateTime dt6 (2009, 12, 27, 0, 0, 0);
  showDate("dt6", dt6);

  DateTime dt7 (dt6.unixtime() + 3600); // One hour later.
  showDate("dt7", dt7);

  DateTime dt75 = dt6 + TimeSpan(0, 1, 0, 0); // One hour later with TimeSpan addition.
  showDate("dt7.5", dt75);

  DateTime dt8 (dt6.unixtime() + 86400L); // One day later.
  showDate("dt8", dt8);

  DateTime dt85 = dt6 + TimeSpan(1, 0, 0, 0); // One day later with TimeSpan addition.
  showDate("dt8.5", dt85);

  DateTime dt9 (dt6.unixtime() + 7 * 86400L); // One week later.
  showDate("dt9", dt9);

  DateTime dt95 = dt6 + TimeSpan(7, 0, 0, 0); // One week later with TimeSpan addition.
  showDate("dt9.5", dt95);

  DateTime dt10 = dt6 + TimeSpan(0, 0, 42, 42); // Fourty two minutes and fourty two seconds later.
  showDate("dt10", dt10);

  DateTime dt11 = dt6 - TimeSpan(7, 0, 0, 0);  // One week ago.
  showDate("dt11", dt11);

  TimeSpan ts1 = dt6 - dt5;
  showTimeSpan("dt6-dt5", ts1);

  TimeSpan ts2 = dt10 - dt6;
  showTimeSpan("dt10-dt6", ts2);
}

void loop () {
}

Probably easier to just record the Epoch time for stop and start then subtract them. That will give you run time in seconds which can be converted to hours.

Ceejay90:
What you explained is what I am trying to do, I really do not understand how to go about it, the example code I saw on the RTClib used to timespan function in setup, and I am trying to use it in loop, what i want to achieve is this;

When the welder starts welding, the time is registered, when he stops, the time is registered, the run hour would now be the difference between both times, below is the initial code I used before I discovered timespan.

if (startWelding)

{
timeStart = now.hour();
}
else
{
if (!startWelding)
{
timeStop = now.hour();
}
}

run_hour = timeStop - timeStart;

Serial.println(run_hour);

Using only the hour for the time is not going to work very well. Someone that starts welding at 59 minutes past the hour, then stops 1 minute later, will give a run time of 1 hour, while someone that starts exactly as the hour begins, and stops at 59 minutes past the hour, will give a run time of 0 hours. You would be much better off using unix time (epoch time) for the start and stop times, then you can easily calculate the run time in seconds, and then convert to hours from that.

gfvalvo:
Probably easier to just record the Epoch time for stop and start then subtract them. That will give you run time in seconds which can be converted to hours.

I don't know how to do this which you explained, never used it before. Please how do i do it?

First, read about Unix Time.

Then checkout the unixtime() function in the library you're using:

uint32_t DateTime::unixtime(void) const {
  uint32_t t;
  uint16_t days = date2days(yOff, m, d);
  t = time2ulong(days, hh, mm, ss);
  t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000

  return t;
}

This will return the Unix Time for any given DateTime object. This format is much easier for doing interval calculations and time comparisons because you don't have to bother with years, months, days, and hours.

gfvalvo:
First, read about Unix Time.

Then checkout the unixtime() function in the library you're using:

uint32_t DateTime::unixtime(void) const {

uint32_t t;
  uint16_t days = date2days(yOff, m, d);
  t = time2ulong(days, hh, mm, ss);
  t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000

return t;
}



This will return the Unix Time for any given DateTime object. This format is much easier for doing interval calculations and time comparisons because you don't have to bother with years, months, days, and hours.

Okay thanks, I will do this.

gfvalvo:
This format is much easier for doing interval calculations and time comparisons because you don't have to bother with years, months, days, and hours.

Sure, but you are pretty low level there and the point is that OP might want to be able to display the time in months, days, hours etc... So that's where the helper classes come in (rather than re-inventing the wheel) and it's not rocket science:

You need two variables to record when you start and stop weldingDateTime weldingStartTime, weldingEndTime;

When welding starts, you do a weldingStartTime = rtc.now();

Then, when welding ends, you do a weldingEndTime = rtc.now();

then if you want to know how long it has been that's a time span (a duration) and you doTimeSpan weldingDuration = weldingEndTime - weldingStartTime;

As it's an object, you can access all the methods offered by the TimeSpan class (including a totalseconds() method which will basically give you the unix time difference)

that's it.