Search code examples
c++esp32real-time-clock

Adafruit RTClib TimeSpan calculation fails on ESP32


I'm currently trying to measure remaining time until a given timestamp using Adafruit's RTClib library. My RTC module is a DS3231. here is my TimeSpan object in code:

TimeSpan remaining = next.depart - rtc.now();

However when i try to print the remaining minutes i get no data. Here is my code that prints the output:

  Serial.println(String("current time: " + rtc.now().timestamp()));
  Serial.println(String("targetTime: " + next.depart.timestamp()));
  Serial.println(String("remaining time: " + remaining.minutes()));

And the output is right except for the remaining time in minutes:

current time: 2020-12-06T05:38:55
target time: 2020-12-06T05:42:30
aining time: 

Notice that the last line is cut off in the serial output and the remaining minutes aren't displayed. current time and target time are both correct in the readout. I can't perform any operations with the remaining time either:

if(remaining.minutes() >= 10)

In this case the condition is never met. Am i missing something?


Solution

  • Your line of code:

      Serial.println(String("remaining time: " + remaining.minutes()));
    

    is not doing what you think it's doing.

    remaining.minutes() returns type int8_t not type String. You're adding it to a C character pointer to the C string remaining time: - if the value is greater than the length of that string then the resulting pointer is invalid and you're lucky your program doesn't crash.

    For instance, if remaining.minutes() were 3 then your output would be:

    aining time: 
    

    Instead your code should look more like this:

      Serial.println("remaining time: " + String(remaining.minutes()));
    

    or better:

      Serial.print("remaining time: ");
      Serial.println(remaining.minutes());
    

    The second form has the benefit of avoiding unnecessary String object instantiations and allocating memory.

    The reason your two lines:

      Serial.println(String("current time: " + rtc.now().timestamp()));
      Serial.println(String("targetTime: " + next.depart.timestamp()));
    

    work is that the timestamp() method returns a String, so adding a C character string to it results in string concatenation rather than adding an integer to a character pointer.

    In these two cases your enclosing call to String() is superfluous and should be avoided:

      Serial.println("current time: " + rtc.now().timestamp());
      Serial.println("targetTime: " + next.depart.timestamp());
    

    You're already computing String values; there's no need to make new String objects from them.

    Find out what value remaining.minutes() is in order to answer your other question. It's likely an issue with the way remaining is computed, and is a matter for different question.