bclose

59 – The new Arduino Time library

Objectives

.

 
  • Show the need to manage a calendar with date and time.
  • Introduce the new Arduino Time library.
  • Basic functions and user defined data types.
  • The need for synchronization.
 

BILL OF MATERIALS

 

Arduino UNO Arduino UNO or equivalent.

 

MEASURING TIME

 

The accurate time measurement is one of those wonders of modern technology to which we do not pay attention. If you spend some time searching on internet you will be surprised by the level of accuracy and price that it has been achieved.

But having a reasonably accurate clock is a luxury that we enjoyed only 150 years ago (and only for the rich). The democratization of time measurement is rather more recent.

Since ancient times water and sand clepsydras have been used to measure time, but the truth is that they were disgusting (a slave was needed to fill the water clock or sand periodically). Already in the middle ages appeared the first mechanical clocks in Europe to be used in bell towers, forget about carrying one in the pocket, as they gave the hours using 2 tons bells.

The first reliable system to measure time was born with the escape clock in the eighteenth century by a British navy contest, which needed a system to know the longitude of their ships when expanding the British Empire though the Pacific ocean. Their solution was a decisive factor in the expansion of the British Empire in the two succeeding centuries.

 
  • Latitude was much less problematic and could be solved using a sextant, but the longitude was a tricky subject for sailors of all previous times.
  • How many would know how to determine the approximate longitude where they are using your wristwatch (or the iPhone, but without internet, of course)?
 

The nineteenth century brought reasonably accurate and pocket clocks (mechanicals clocks, of course). Probably there are still some of them in your houses, the grandfather’s clock, for example, between the jewellery and family relics.

But when watches really started to be precise and within everybody’s reach was in the 70’s, with the digital quartz watch.
They were watches, as defined by an old watchmaker, in which the only moving things were the numbers.

Quartz was the base of oscillators with an accuracy unknown up to then and even nowadays any normal wristwatch carries one of these small quartz crystals as its heart.

As we said in the chapter about buzzers, Arduino incorporates a piezoelectric crystal as a clock, which beats at 16 Mhz, or 16 millions of pulses per second. And we can expect a precision less than 0.5 seconds per day and with excellent stability against temperature changes (The bogeyman of mechanical watches)

All this sticky preface tries to make you realize that sooner or later, you will need to control the time in your Arduino.
So far we have seen some very basic time instructions like delay(), millis() and micros(), etc. These instructions are very useful for controlling very short time lapses, but soon you will feel the need to measure the time in minutes, hours, days and probably months and years.

Won’t you? Well it depends a lot on the type of projects you do. But imagine, for example, a data logger in which you have an Arduino connected to a machine, supervising its variables, which can be revolutions per minute, its voltage peaks, current intensity or simply if it is on or stopped.

We do not even talk about how to measure these variables, but simply keep records of their values for a further study. Imagine that you want your energy bill and know exactly when you consume and how much …

There are plenty of cases in which you want to monitor a system, keep track of the values and add them a time stamp in order to make graphs later or perhaps to use them in your own sketch.

Adding a time stamp to your data is imperative.

And because of that, since we are not the first to face this problem, there already exist solutions (thanks to God). In this chapter we will introduce the new Arduino Time library, see how to handle and use it when needed and which options do we have.

 

ARDUINO TIME LIBRARY

 

Time is a standard Arduino library but requires installation before using, because it consumes valuable resources, especially in a Arduino UNO.

You can download it here:

Time.zip

Then you must install it following the standard procedure.

Why should we use library to measure time? Why don’t we just make some calculations? Now we are already expert programmers (or almost), so we can do it

Blessed innocence! Mainly because managing time is quite annoying, as we saw when we made the clock in the chapter: Display with interface

The main drawback is that hours and minutes are counted in sexagesimal, not in centesimal, system, and if this were not
enough, days have 24 hours or two cycles of 12 hours, some months have 30 days, another months have 31, and February has 28 or 29, it depends. A year have 12 months and not 10, as it should if it were decimal (and we believe we only use the decimal system).

Wait a minute, we have not even spoken of the corrections of the Gregorian calendar, the leap year and the exceptions to the rules. It’s like a computer hell.

Heed the grandfather and use the libary, it will make your life easier.

The Time library first defines a special type of variable, called 32-bit time_t, which is the basis of everything.
The idea is that time_t stores time values in a special format, calculated as the number of seconds elapsed from 1 January 1970 up to a given date..

It stores… what? Calm down, for those who come from the world of computing we must tell you that it is the standard Unix / Linux method. And for those who are newbies, we must tell them that conversions are automatically made by the library, so don’t fear.

The advantage of such an anti-intuitive thing is that by turning a date and time into a number of seconds from a reference date, we can subtract dates and times easily and the result is still a date or time that measures the difference between the two, expressed in years, months, days, minutes and seconds.

Clean and effective. And besides, the library does all the work of converting dates and times into time_T so that we can operate easily.

 
  • The drawback is in the small print, the library does not work with dates prior to 1970, which is not usually serious whenever you have it clear.
 

The practical way to handle time is to start by defining a variable time_t:

time_t T = now();

Clever readers could have realized that now() is a function, which provides the current internal time value in Arduino. And what time is that? A disgusting value, because every time you power off your Arduino or reset it, the time is reset to 0.

Can we do something to set it on time? Nothing easier:

setTime(19,58,00,6,11,2014); // Las 19:58:00 del dia 6 de Nov de 2014

To make a clock with calendar we could use the following sketch:

#include <Time.h>

void setup()
  {   Serial.begin(115200);
      setTime(19,58,00,6,11,2014);
  }
void loop()
  {   time_t t = now();

      Serial.print(day(t));
      Serial.print(+ "/") ;
      Serial.print(month(t));
      Serial.print(+ "/") ;
      Serial.print(year(t)); 
      Serial.print( " ") ;
      Serial.print(hour(t));  
      Serial.print(+ ":") ;
      Serial.print(minute(t));
      Serial.print(":") ;
      Serial.println(second(t));
      delay(1000);
  }

As you can see, this program uses the basic date-time handling functions: first how to set the clock and then how to get the day, month, year, hour, minute and second.

Imagine now that we have two dates: “6 Nov 2014 20:17” and “13 Nov 2014 16:45” and we want to subtract them to know common things like how many days or hours someone has worked (people are very picky about what must earn according to the number of hours and days they have worked).

 
  • I propose you to calculate it by hand and then check it with your Arduino to see how many can do it right. No, it’s not a joke even though we are laughing..
 

To calculate this difference, we have to take a detour and talk about an important structure in the new Time library, which has put the old one upside down.

When we want to generate time_t dates from numbers of days (or hours and minutes) the new library defines a structure of type tmElements_t (do not panic), which has the following members:

   tmElements_t  tm ;
   tm.Second     Seconds       0 to 59
   tm.Minute     Minutes       0 to 59
   tm.Hour       Hours         0 to 23
   tm.Wday       DayOfTheWeek  0 to 6  (Not used in mktime)
   tm.Day        Day           1 to 31
   tm.Month      Month         1 to 12
   tm.Year       Year          0 to 99 (Difference from 1970)

Thus, for the first date above we would have:

   tmElements_t DateTime ;
   Fecha.Second = 0;
   Fecha.Minute = 17;
   Fecha.Hour = 20;
   Fecha.Day =6 ;
   Fecha.Month = 11 ;
   Fecha.Year = 2014 -1970 ;
   T0 = makeTime(DateTime);

Where we assign values to the Date members of type tmElements, with the properties that you see. That way T0 is “6 Nov 2014 – 20:17:00” in seconds. And makeTime() is a function that returns the time in format time_t, of a structure tmElements_t.

To show its use, we will slightly modify the previous program

Sketch 59_1
#include 
time_t  T0, T1 ;         // Date-Time variables

void setup()
   {    Serial.begin(115200);  }

void loop()
   {    T0 = SetDateTime (2014, 11, 6, 20, 17, 0);  // 6 nov 2014  20:17
        printDateTime (T0) ;
        T1 = SetDateTime (2014, 11, 13, 16, 45, 0);  // 13 nov 2014 16:45
        printDateTime (T1) ;
        printDateTime (T1 - T0);

        Serial.println("--------------------------------------------------");
        time_t H =  T1 - T0 ;

        Serial.print(String(year(H )- 1970)+" years,"  + String(month(H)-1 )+" months,");
        Serial.println(String(day(H))+ " days," + String(hour(H))+ " hours");
        Serial.println("---------------------------------------------------");
   }

void printDateTime(time_t  t)
   {
       Serial.print(day(t)) ;    Serial.print(+ "/") ;   Serial.print(month(t));   Serial.print(+ "/") ;
       Serial.print(year(t));    Serial.print( " ") ;
       Serial.print(hour(t));   Serial.print(+ ":") ;   Serial.print(minute(t));   Serial.print(":") ;
       Serial.println(second(t));
       delay(1000);
   }

time_t SetDateTime(int y, int m, int d, int h, int mi, int s  )
   {  tmElements_t DateTime ;
      DateTime.Second = s;
      DateTime.Minute = mi;
      DateTime.Hour = h;
      DateTime.Day = d ;
      DateTime.Month = m ;
      DateTime.Year = y -1970 ;
 
      return makeTime(DateTime);
   }

The printDate() function formats the output of a variable time_t in seconds. The function SetDate() is more interesting because it uses a tm_Elements_t structure to assign the values passed as dates, to return a standard converted date.

We can already calculate the difference between them but the result would be in seconds, which would not be very descriptive. That’s why we have calculated H as its difference and printed it with a bit of formatting.

This is the output of the sketch:

Results of the sketch

 

The third line contains the correct answer to the difference between dates, but you have to interpret it. “7/1/1970” means 7 days, 0 months 0 years, because January is month 1 (there is no month 0). In the same way 1970 is the first year of the internal calendar and therefore means 0 years.

The answer is valid but for some reason, not many people are willing to accept it this way. That’s why we formated the answer in the following line.

 

CLOCK SYNCHRONIZATION IN ARDUINO

 

We still have another budding time bomb. The internal time of Arduino is saved in a variable that counts the milliseconds elapsed from the moment we power it up or reset it. If we leave it working enough time, another problem to take into account is the overflow of Arduino internal clock.

Since it stores the number of milliseconds elapsed since power-up, if it uses an unsigned long variable of 32 bits to save it, the maximum value it can contain is:

232 = 4.294.967.296

And since the number of milliseconds per day is:

1000 ms * 60 secs * 60 mins * 24 hours  =  86.400.000

The clock will inevitably overflow in:

4.294.967.296 / 86400000 = 49, 7102696 days

That is, something less than 50 days, after which the clock will be reset and start again.

The question of clock synchronization is not a trivial issue, and much of the raison d’être of the new Time library has to do with this idea (as incredible as it may seem to you now).

 
  • Anyone who has several clocks in their house knows how desperate is to set them in hour after a blackout and also as the months go by get all of them synchronized is a full time job.
  • Have you ever thought that the logical thing is that they should get synchronized by some kind of procedure, let’s say via WI-FI, by checking the time on Internet?
  • It is another of the many ways in which the Internet of things (IOT ) could help humanity..
 

There are several methods that can be used to set the internal clock of Arduino every time we reset it:

 
  • By hand, as we have done in the examples of this chapter. This method works for the examples but we need another solution.
  • Via a serial program from our PC. It works but requires a PC that must be on and a program for the synchronization service.
  • Via a real time clock chip and a battery that keeps the date and time, even if we power the Arduino off. This will be the subject of our next chapter.
  • By getting synchronized over internet via a time service (yes sir, that exists). They are called NTP (Network Time Protocol) servers.
  • Using a GPS watch, which in case you do not know are the most wildly accurate clocks that you can buy at an affordable price (We’ll talk about them when we get to GPS).
 

You have examples of all these methods in the example sketches of the Time library, so we do not think it is worthwhile to discuss each one now. Once you install the library the examples are already installed. Take a look at them.

To help you synchronize your Arduino, the new Time library has logical functions that tell us if the time has been synchronized and how long ago.

Function Meaning
timeStatus();

It can return three values:

  • timeNotSet The clock has not been set/synchronized.
  • timeSet The clock has been set.
  • timeNeedsSync The clock was set but the synchronization with an external time service has failed.
setSyncProvider Defines a function that is periodically called to synchronize with an external service.
setSyncInterval() Defines how long the setSyncProvider() function is called.

 

 

 

Summary

.

 
    • We have seen how to install the new time library.
    • We have made a couple of sketches to show the use of the new time_t data type.
    • We have introduced the basic concepts of synchronization with external services.
 
 

 

No Comments

Give a Reply