diff --git a/examples/GPSSensor/GPSSensor.ino b/examples/GPSSensor/GPSSensor.ino index b49ab96..f654bc1 100644 --- a/examples/GPSSensor/GPSSensor.ino +++ b/examples/GPSSensor/GPSSensor.ino @@ -50,7 +50,7 @@ static const uint32_t GPSBaud = 9600; const int offset = 1; #include -#include +#include #include #include #include diff --git a/examples/IrrigationController/IrrigationController.ino b/examples/IrrigationController/IrrigationController.ino index 8d9302a..7e37bcb 100644 --- a/examples/IrrigationController/IrrigationController.ino +++ b/examples/IrrigationController/IrrigationController.ino @@ -91,7 +91,7 @@ Contributed by Jim (BulldogLowell@gmail.com) with much contribution from Pete (p //#define MY_NODE_ID 1 // Set this to fix your Radio ID or use Auto #include -#include +#include #include #include #include diff --git a/examples/RainGauge/RainGauge.ino b/examples/RainGauge/RainGauge.ino index 6a93374..d7ea6bc 100644 --- a/examples/RainGauge/RainGauge.ino +++ b/examples/RainGauge/RainGauge.ino @@ -47,7 +47,7 @@ #include #include #include -#include +#include #define SKETCH_NAME "Rain Gauge" #define SKETCH_VERSION "1.4.1a" diff --git a/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino b/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino index 1ce3538..848d8b3 100644 --- a/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino +++ b/examples/RealTimeClockDisplaySensor/RealTimeClockDisplaySensor.ino @@ -48,7 +48,7 @@ #include #include -#include +#include #include // A DS3231/DS3232 library #include #include diff --git a/examples/TimeAwareSensor/TimeAwareSensor.ino b/examples/TimeAwareSensor/TimeAwareSensor.ino index c8df071..053c5d1 100644 --- a/examples/TimeAwareSensor/TimeAwareSensor.ino +++ b/examples/TimeAwareSensor/TimeAwareSensor.ino @@ -34,7 +34,7 @@ #include #include -#include +#include bool timeReceived = false; unsigned long lastUpdate=0, lastRequest=0; diff --git a/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino b/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino index 8129410..1636ef8 100644 --- a/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino +++ b/examples/TouchDisplaySceneControllerSensor/TouchDisplaySceneControllerSensor.ino @@ -62,7 +62,7 @@ #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 -#include +#include #include #include #include diff --git a/libraries/Time/DateStrings.cpp b/libraries/Time/DateStrings.cpp index a0eef9d..3eccff3 100644 --- a/libraries/Time/DateStrings.cpp +++ b/libraries/Time/DateStrings.cpp @@ -1,20 +1,33 @@ /* DateStrings.cpp * Definitions for date strings for use with the Time library * + * Updated for Arduino 1.5.7 18 July 2014 + * * No memory is consumed in the sketch if your code does not call any of the string methods * You can change the text of the strings, make sure the short strings are each exactly 3 characters - * the long strings can be any length up to the constant dt_MAX_STRING_LEN defined in Time.h + * the long strings can be any length up to the constant dt_MAX_STRING_LEN defined in TimeLib.h * */ - -#include -#include "Time.h" + +#if defined(__AVR__) +#include +#else +// for compatiblity with Arduino Due and Teensy 3.0 and maybe others? +#define PROGMEM +#define PGM_P const char * +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#define pgm_read_word(addr) (*(const unsigned char **)(addr)) +#define strcpy_P(dest, src) strcpy((dest), (src)) +#endif +#include // for strcpy_P or strcpy +#include "TimeLib.h" // the short strings for each day or month must be exactly dt_SHORT_STR_LEN #define dt_SHORT_STR_LEN 3 // the length of short strings static char buffer[dt_MAX_STRING_LEN+1]; // must be big enough for longest string and the terminating null +const char monthStr0[] PROGMEM = ""; const char monthStr1[] PROGMEM = "January"; const char monthStr2[] PROGMEM = "February"; const char monthStr3[] PROGMEM = "March"; @@ -28,10 +41,10 @@ const char monthStr10[] PROGMEM = "October"; const char monthStr11[] PROGMEM = "November"; const char monthStr12[] PROGMEM = "December"; -PGM_P const monthNames_P[] PROGMEM = +const PROGMEM char * const PROGMEM monthNames_P[] = { - "",monthStr1,monthStr2,monthStr3,monthStr4,monthStr5,monthStr6, - monthStr7,monthStr8,monthStr9,monthStr10,monthStr11,monthStr12 + monthStr0,monthStr1,monthStr2,monthStr3,monthStr4,monthStr5,monthStr6, + monthStr7,monthStr8,monthStr9,monthStr10,monthStr11,monthStr12 }; const char monthShortNames_P[] PROGMEM = "ErrJanFebMarAprMayJunJulAugSepOctNovDec"; @@ -45,15 +58,19 @@ const char dayStr5[] PROGMEM = "Thursday"; const char dayStr6[] PROGMEM = "Friday"; const char dayStr7[] PROGMEM = "Saturday"; -PGM_P const dayNames_P[] PROGMEM = { dayStr0,dayStr1,dayStr2,dayStr3,dayStr4,dayStr5,dayStr6,dayStr7}; -const char dayShortNames_P[] PROGMEM = "ErrSunMonTueWedThrFriSat"; +const PROGMEM char * const PROGMEM dayNames_P[] = +{ + dayStr0,dayStr1,dayStr2,dayStr3,dayStr4,dayStr5,dayStr6,dayStr7 +}; + +const char dayShortNames_P[] PROGMEM = "ErrSunMonTueWedThuFriSat"; /* functions to return date strings */ char* monthStr(uint8_t month) { strcpy_P(buffer, (PGM_P)pgm_read_word(&(monthNames_P[month]))); - return buffer; + return buffer; } char* monthShortStr(uint8_t month) diff --git a/libraries/Time/Examples/Processing/SyncArduinoClock/SyncArduinoClock.pde b/libraries/Time/Examples/Processing/SyncArduinoClock/SyncArduinoClock.pde index 4c74d4b..4313be3 100644 --- a/libraries/Time/Examples/Processing/SyncArduinoClock/SyncArduinoClock.pde +++ b/libraries/Time/Examples/Processing/SyncArduinoClock/SyncArduinoClock.pde @@ -12,9 +12,12 @@ import processing.serial.*; +import java.util.Date; +import java.util.Calendar; +import java.util.GregorianCalendar; -public static final short portIndex = 1; // select the com port, 0 is the first port -public static final char TIME_HEADER = 'T'; //header byte for arduino serial time message +public static final short portIndex = 0; // select the com port, 0 is the first port +public static final String TIME_HEADER = "T"; //header for arduino serial time message public static final char TIME_REQUEST = 7; // ASCII bell character public static final char LF = 10; // ASCII linefeed public static final char CR = 13; // ASCII linefeed @@ -25,10 +28,15 @@ void setup() { println(Serial.list()); println(" Connecting to -> " + Serial.list()[portIndex]); myPort = new Serial(this,Serial.list()[portIndex], 9600); + println(getTimeNow()); } void draw() { + textSize(20); + textAlign(CENTER); + fill(0); + text("Click to send\nTime Sync", 0, 75, 200, 175); if ( myPort.available() > 0) { // If data is available, char val = char(myPort.read()); // read it and store it in val if(val == TIME_REQUEST){ @@ -52,19 +60,19 @@ void mousePressed() { } -void sendTimeMessage(char header, long time) { +void sendTimeMessage(String header, long time) { String timeStr = String.valueOf(time); myPort.write(header); // send header and time to arduino - myPort.write(timeStr); + myPort.write(timeStr); + myPort.write('\n'); } long getTimeNow(){ // java time is in ms, we want secs - GregorianCalendar cal = new GregorianCalendar(); - cal.setTime(new Date()); - int tzo = cal.get(Calendar.ZONE_OFFSET); - int dst = cal.get(Calendar.DST_OFFSET); - long now = (cal.getTimeInMillis() / 1000) ; - now = now + (tzo/1000) + (dst/1000); - return now; + Date d = new Date(); + Calendar cal = new GregorianCalendar(); + long current = d.getTime()/1000; + long timezone = cal.get(cal.ZONE_OFFSET)/1000; + long daylight = cal.get(cal.DST_OFFSET)/1000; + return current + timezone + daylight; } diff --git a/libraries/Time/Examples/Processing/SyncArduinoClock/readme.txt b/libraries/Time/Examples/Processing/SyncArduinoClock/readme.txt index 985bd80..da9721d 100644 --- a/libraries/Time/Examples/Processing/SyncArduinoClock/readme.txt +++ b/libraries/Time/Examples/Processing/SyncArduinoClock/readme.txt @@ -6,4 +6,4 @@ The portIndex must be set the Serial port connected to Arduino. Download TimeSerial.pde onto Arduino and you should see the time message displayed when you run SyncArduinoClock in Processing. The Arduino time is set from the time on your computer through the -Processing sketch. \ No newline at end of file +Processing sketch. diff --git a/libraries/Time/Examples/TimeGPS/TimeGPS.pde b/libraries/Time/Examples/TimeGPS/TimeGPS.pde deleted file mode 100644 index 1c7b25e..0000000 --- a/libraries/Time/Examples/TimeGPS/TimeGPS.pde +++ /dev/null @@ -1,82 +0,0 @@ -/* - * TimeGPS.pde - * example code illustrating time synced from a GPS - * - */ - -#include -#include //http://arduiniana.org/libraries/TinyGPS/ -#include //http://arduiniana.org/libraries/newsoftserial/ -// GPS and NewSoftSerial libraries are the work of Mikal Hart - -TinyGPS gps; -NewSoftSerial serial_gps = NewSoftSerial(3, 2); // receive on pin 3 - -const int offset = 1; // offset hours from gps time (UTC) -time_t prevDisplay = 0; // when the digital clock was displayed - -void setup() -{ - Serial.begin(9600); - serial_gps.begin(4800); - Serial.println("Waiting for GPS time ... "); - setSyncProvider(gpsTimeSync); -} - -void loop() -{ - while (serial_gps.available()) - { - gps.encode(serial_gps.read()); // process gps messages - } - if(timeStatus()!= timeNotSet) - { - if( now() != prevDisplay) //update the display only if the time has changed - { - prevDisplay = now(); - digitalClockDisplay(); - } - } -} - -void digitalClockDisplay(){ - // digital clock display of the time - Serial.print(hour()); - printDigits(minute()); - printDigits(second()); - Serial.print(" "); - Serial.print(day()); - Serial.print(" "); - Serial.print(month()); - Serial.print(" "); - Serial.print(year()); - Serial.println(); -} - -void printDigits(int digits){ - // utility function for digital clock display: prints preceding colon and leading 0 - Serial.print(":"); - if(digits < 10) - Serial.print('0'); - Serial.print(digits); -} - -time_t gpsTimeSync(){ - // returns time if avail from gps, else returns 0 - unsigned long fix_age = 0 ; - gps.get_datetime(NULL,NULL, &fix_age); - unsigned long time_since_last_fix; - if(fix_age < 1000) - return gpsTimeToArduinoTime(); // return time only if updated recently by gps - return 0; -} - -time_t gpsTimeToArduinoTime(){ - // returns time_t from gps date and time with the given offset hours - tmElements_t tm; - int year; - gps.crack_datetime(&year, &tm.Month, &tm.Day, &tm.Hour, &tm.Minute, &tm.Second, NULL, NULL); - tm.Year = year - 1970; - time_t time = makeTime(tm); - return time + (offset * SECS_PER_HOUR); -} diff --git a/libraries/Time/Examples/TimeNTP/TimeNTP.pde b/libraries/Time/Examples/TimeNTP/TimeNTP.pde deleted file mode 100644 index ff9311a..0000000 --- a/libraries/Time/Examples/TimeNTP/TimeNTP.pde +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Time_NTP.pde - * Example showing time sync to NTP time source - * - * This sketch uses the Ethenet library with the user contributed UdpBytewise extension - */ - -#include -#include -#include // UDP library from: bjoern@cs.stanford.edu 12/30/2008 -#if UDP_TX_PACKET_MAX_SIZE <64 || UDP_RX_PACKET_MAX_SIZE < 64 -#error : UDP packet size to small - modify UdpBytewise.h to set buffers to 64 bytes -#endif -/* - * - * You may need to modify the UdpBytewise.h library to allow enough space in the buffers for the NTP packets. - * Open up UdpBytewse.h and set the following buffers to 64 bytes: - * #define UDP_TX_PACKET_MAX_SIZE 64 - * #define UDP_RX_PACKET_MAX_SIZE 64 - */ - - -byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; -byte ip[] = { 192, 168, 1, 44 }; // set the IP address to an unused address on your network - -byte SNTP_server_IP[] = { 192, 43, 244, 18}; // time.nist.gov -//byte SNTP_server_IP[] = { 130,149,17,21}; // ntps1-0.cs.tu-berlin.de -//byte SNTP_server_IP[] = { 192,53,103,108}; // ptbtime1.ptb.de - - -time_t prevDisplay = 0; // when the digital clock was displayed -const long timeZoneOffset = 0L; // set this to the offset in seconds to your local time; - -void setup() -{ - Serial.begin(9600); - Ethernet.begin(mac,ip); - Serial.println("waiting for sync"); - setSyncProvider(getNtpTime); - while(timeStatus()== timeNotSet) - ; // wait until the time is set by the sync provider -} - -void loop() -{ - if( now() != prevDisplay) //update the display only if the time has changed - { - prevDisplay = now(); - digitalClockDisplay(); - } -} - -void digitalClockDisplay(){ - // digital clock display of the time - Serial.print(hour()); - printDigits(minute()); - printDigits(second()); - Serial.print(" "); - Serial.print(day()); - Serial.print(" "); - Serial.print(month()); - Serial.print(" "); - Serial.print(year()); - Serial.println(); -} - -void printDigits(int digits){ - // utility function for digital clock display: prints preceding colon and leading 0 - Serial.print(":"); - if(digits < 10) - Serial.print('0'); - Serial.print(digits); -} - -/*-------- NTP code ----------*/ - -unsigned long getNtpTime() -{ - sendNTPpacket(SNTP_server_IP); - delay(1000); - if ( UdpBytewise.available() ) { - for(int i=0; i < 40; i++) - UdpBytewise.read(); // ignore every field except the time - const unsigned long seventy_years = 2208988800UL + timeZoneOffset; - return getUlong() - seventy_years; - } - return 0; // return 0 if unable to get the time -} - -unsigned long sendNTPpacket(byte *address) -{ - UdpBytewise.begin(123); - UdpBytewise.beginPacket(address, 123); - UdpBytewise.write(B11100011); // LI, Version, Mode - UdpBytewise.write(0); // Stratum - UdpBytewise.write(6); // Polling Interval - UdpBytewise.write(0xEC); // Peer Clock Precision - write_n(0, 8); // Root Delay & Root Dispersion - UdpBytewise.write(49); - UdpBytewise.write(0x4E); - UdpBytewise.write(49); - UdpBytewise.write(52); - write_n(0, 32); //Reference and time stamps - UdpBytewise.endPacket(); -} - -unsigned long getUlong() -{ - unsigned long ulong = (unsigned long)UdpBytewise.read() << 24; - ulong |= (unsigned long)UdpBytewise.read() << 16; - ulong |= (unsigned long)UdpBytewise.read() << 8; - ulong |= (unsigned long)UdpBytewise.read(); - return ulong; -} - -void write_n(int what, int how_many) -{ - for( int i = 0; i < how_many; i++ ) - UdpBytewise.write(what); -} diff --git a/libraries/Time/Examples/TimeRTCSet/TimeRTCSet.pde b/libraries/Time/Examples/TimeRTCSet/TimeRTCSet.pde deleted file mode 100644 index e798164..0000000 --- a/libraries/Time/Examples/TimeRTCSet/TimeRTCSet.pde +++ /dev/null @@ -1,82 +0,0 @@ -/* - * TimeRTCSet.pde - * example code illustrating Time library with Real Time Clock. - * - * RTC clock is set in response to serial port time message - * A Processing example sketch to set the time is inclided in the download - */ - -#include -#include -#include // a basic DS1307 library that returns time as a time_t - - -void setup() { - Serial.begin(9600); - setSyncProvider(RTC.get); // the function to get the time from the RTC - if(timeStatus()!= timeSet) - Serial.println("Unable to sync with the RTC"); - else - Serial.println("RTC has set the system time"); -} - -void loop() -{ - if(Serial.available()) - { - time_t t = processSyncMessage(); - if(t >0) - { - RTC.set(t); // set the RTC and the system time to the received value - setTime(t); - } - } - digitalClockDisplay(); - delay(1000); -} - -void digitalClockDisplay(){ - // digital clock display of the time - Serial.print(hour()); - printDigits(minute()); - printDigits(second()); - Serial.print(" "); - Serial.print(day()); - Serial.print(" "); - Serial.print(month()); - Serial.print(" "); - Serial.print(year()); - Serial.println(); -} - -void printDigits(int digits){ - // utility function for digital clock display: prints preceding colon and leading 0 - Serial.print(":"); - if(digits < 10) - Serial.print('0'); - Serial.print(digits); -} - -/* code to process time sync messages from the serial port */ -#define TIME_MSG_LEN 11 // time sync to PC is HEADER followed by unix time_t as ten ascii digits -#define TIME_HEADER 'T' // Header tag for serial time sync message - -time_t processSyncMessage() { - // return the time if a valid sync message is received on the serial port. - while(Serial.available() >= TIME_MSG_LEN ){ // time message consists of a header and ten ascii digits - char c = Serial.read() ; - Serial.print(c); - if( c == TIME_HEADER ) { - time_t pctime = 0; - for(int i=0; i < TIME_MSG_LEN -1; i++){ - c = Serial.read(); - if( c >= '0' && c <= '9'){ - pctime = (10 * pctime) + (c - '0') ; // convert digits to a number - } - } - return pctime; - } - } - return 0; -} - diff --git a/libraries/Time/Examples/TimeSerialDateStrings/TimeSerialDateStrings.pde b/libraries/Time/Examples/TimeSerialDateStrings/TimeSerialDateStrings.pde deleted file mode 100644 index 62eac10..0000000 --- a/libraries/Time/Examples/TimeSerialDateStrings/TimeSerialDateStrings.pde +++ /dev/null @@ -1,80 +0,0 @@ -/* - * TimeSerialDateStrings.pde - * example code illustrating Time library date strings - * - * This sketch adds date string functionality to TimeSerial.pde - * - */ - -#include - -#define TIME_MSG_LEN 11 // time sync to PC is HEADER followed by unix time_t as ten ascii digits -#define TIME_HEADER 'T' // Header tag for serial time sync message -#define TIME_REQUEST 7 // ASCII bell character requests a time sync message - -void setup() { - Serial.begin(9600); - setSyncProvider( requestSync); //set function to call when sync required - Serial.println("Waiting for sync message"); -} - -void loop(){ - if(Serial.available() ) - { - processSyncMessage(); - } - if(timeStatus()!= timeNotSet) - { - digitalClockDisplay(); - } - delay(1000); -} - -void digitalClockDisplay(){ - // digital clock display of the time - Serial.print(hour()); - printDigits(minute()); - printDigits(second()); - Serial.print(" "); - Serial.print(dayStr(weekday())); - Serial.print(" "); - Serial.print(day()); - Serial.print(" "); - Serial.print(monthShortStr(month())); - Serial.print(" "); - Serial.print(year()); - Serial.println(); -} - -void printDigits(int digits){ - // utility function for digital clock display: prints preceding colon and leading 0 - Serial.print(":"); - if(digits < 10) - Serial.print('0'); - Serial.print(digits); -} - -void processSyncMessage() { - // if time sync available from serial port, update time and return true - while(Serial.available() >= TIME_MSG_LEN ){ // time message consists of a header and ten ascii digits - char c = Serial.read() ; - Serial.print(c); - if( c == TIME_HEADER ) { - time_t pctime = 0; - for(int i=0; i < TIME_MSG_LEN -1; i++){ - c = Serial.read(); - if( c >= '0' && c <= '9'){ - pctime = (10 * pctime) + (c - '0') ; // convert digits to a number - } - } - setTime(pctime); // Sync Arduino clock to the time received on the serial port - } - } -} - -time_t requestSync() -{ - Serial.print(TIME_REQUEST,BYTE); - return 0; // the time will be sent later in response to serial mesg -} - diff --git a/libraries/Time/Readme.txt b/libraries/Time/Readme.txt index 06d82f1..67b148e 100644 --- a/libraries/Time/Readme.txt +++ b/libraries/Time/Readme.txt @@ -90,9 +90,9 @@ illustrating how the library can be used with various time sources: The NTP protocol uses UDP and the UdpBytewise library is required, see: http://bitbucket.org/bjoern/arduino_osc/src/14667490521f/libraries/Ethernet/ --TimeGPS gets time from a GPS - This requires the TinyGPS and NewSoftSerial libraries from Mikal Hart: - http://arduiniana.org/libraries/TinyGPS and http://arduiniana.org/libraries/newsoftserial/ +- TimeGPS gets time from a GPS + This requires the TinyGPS library from Mikal Hart: + http://arduiniana.org/libraries/TinyGPS Differences between this code and the playground DateTime library although the Time library is based on the DateTime codebase, the API has changed. @@ -128,4 +128,4 @@ Low level functions to convert between system time and individual time elements makeTime( &tm); // return time_t from elements stored in tm struct The DS1307RTC library included in the download provides an example of how a time provider -can use the low level functions to interface with the Time library. \ No newline at end of file +can use the low level functions to interface with the Time library. diff --git a/libraries/Time/Time.cpp b/libraries/Time/Time.cpp index 86bdcd5..5ca1327 100644 --- a/libraries/Time/Time.cpp +++ b/libraries/Time/Time.cpp @@ -1,6 +1,6 @@ /* time.c - low level time and date functions - Copyright (c) Michael Margolis 2009 + Copyright (c) Michael Margolis 2009-2014 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,9 +16,15 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - 6 Jan 2010 - initial release - 12 Feb 2010 - fixed leap year calculation error - 1 Nov 2010 - fixed setTime bug (thanks to Korman for this) + 1.0 6 Jan 2010 - initial release + 1.1 12 Feb 2010 - fixed leap year calculation error + 1.2 1 Nov 2010 - fixed setTime bug (thanks to Korman for this) + 1.3 24 Mar 2012 - many edits by Paul Stoffregen: fixed timeStatus() to update + status, updated examples for Arduino 1.0, fixed ARM + compatibility issues, added TimeArduinoDue and TimeTeensy3 + examples, add error checking and messages to RTC examples, + add examples to DS1307RTC library. + 1.4 5 Sep 2014 - compatibility with Arduino 1.5.7 */ #if ARDUINO >= 100 @@ -27,15 +33,14 @@ #include #endif -#include "Time.h" +#include "TimeLib.h" static tmElements_t tm; // a cache of time elements -static time_t cacheTime; // the time the cache was updated -static time_t syncInterval = 300; // time sync will be attempted after this many seconds +static time_t cacheTime; // the time the cache was updated +static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds -void refreshCache( time_t t){ - if( t != cacheTime) - { +void refreshCache(time_t t) { + if (t != cacheTime) { breakTime(t, tm); cacheTime = t; } @@ -143,15 +148,17 @@ int year(time_t t) { // the year for the given time static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0 -void breakTime(time_t time, tmElements_t &tm){ +void breakTime(time_t timeInput, tmElements_t &tm){ // break the given time_t into time components // this is a more compact version of the C library localtime function // note that year is offset from 1970 !!! uint8_t year; uint8_t month, monthLength; + uint32_t time; unsigned long days; - + + time = (uint32_t)timeInput; tm.Second = time % 60; time /= 60; // now it is minutes tm.Minute = time % 60; @@ -200,7 +207,7 @@ time_t makeTime(tmElements_t &tm){ // previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9 int i; - time_t seconds; + uint32_t seconds; // seconds from 1970 till 1 jan 00:00:00 of the given year seconds= tm.Year*(SECS_PER_DAY * 365); @@ -222,14 +229,14 @@ time_t makeTime(tmElements_t &tm){ seconds+= tm.Hour * SECS_PER_HOUR; seconds+= tm.Minute * SECS_PER_MIN; seconds+= tm.Second; - return seconds; + return (time_t)seconds; } /*=====================================================*/ /* Low level system time functions */ -static time_t sysTime = 0; -static time_t prevMillis = 0; -static time_t nextSyncTime = 0; +static uint32_t sysTime = 0; +static uint32_t prevMillis = 0; +static uint32_t nextSyncTime = 0; static timeStatus_t Status = timeNotSet; getExternalTime getTimePtr; // pointer to external sync function @@ -240,39 +247,43 @@ time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync #endif -time_t now(){ - while( millis() - prevMillis >= 1000){ +time_t now() { + // calculate number of seconds passed since last call to now() + while (millis() - prevMillis >= 1000) { + // millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference sysTime++; prevMillis += 1000; #ifdef TIME_DRIFT_INFO sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift -#endif +#endif } - if(nextSyncTime <= sysTime){ - if(getTimePtr != 0){ - time_t t = getTimePtr(); - if( t != 0) + if (nextSyncTime <= sysTime) { + if (getTimePtr != 0) { + time_t t = getTimePtr(); + if (t != 0) { setTime(t); - else - Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync; + } else { + nextSyncTime = sysTime + syncInterval; + Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync; + } } } - return sysTime; + return (time_t)sysTime; } -void setTime(time_t t){ +void setTime(time_t t) { #ifdef TIME_DRIFT_INFO if(sysUnsyncedTime == 0) sysUnsyncedTime = t; // store the time of the first call to set a valid Time #endif - sysTime = t; - nextSyncTime = t + syncInterval; - Status = timeSet; + sysTime = (uint32_t)t; + nextSyncTime = (uint32_t)t + syncInterval; + Status = timeSet; prevMillis = millis(); // restart counting from now (thanks to Korman for this fix) } -void setTime(int hr,int min,int sec,int dy, int mnth, int yr){ +void setTime(int hr,int min,int sec,int dy, int mnth, int yr){ // year can be given as full four digit year or two digts (2010 or 10 for 2010); //it is converted to years since 1970 if( yr > 99) @@ -288,11 +299,13 @@ void setTime(int hr,int min,int sec,int dy, int mnth, int yr){ setTime(makeTime(tm)); } -void adjustTime(long adjustment){ +void adjustTime(long adjustment) { sysTime += adjustment; } -timeStatus_t timeStatus(){ // indicates if time has been set and recently synchronized +// indicates if time has been set and recently synchronized +timeStatus_t timeStatus() { + now(); // required to actually update the status return Status; } @@ -303,5 +316,6 @@ void setSyncProvider( getExternalTime getTimeFunction){ } void setSyncInterval(time_t interval){ // set the number of seconds between re-sync - syncInterval = interval; -} \ No newline at end of file + syncInterval = (uint32_t)interval; + nextSyncTime = sysTime + syncInterval; +} diff --git a/libraries/Time/Time.h b/libraries/Time/Time.h index e54f3b0..a79b080 100644 --- a/libraries/Time/Time.h +++ b/libraries/Time/Time.h @@ -1,126 +1 @@ -/* - time.h - low level time and date functions -*/ - -/* - July 3 2011 - fixed elapsedSecsThisWeek macro (thanks Vincent Valdy for this) - - fixed daysToTime_t macro (thanks maniacbug) -*/ - -#ifndef _Time_h -#define _Time_h - -#include - -typedef unsigned long time_t; - -typedef enum {timeNotSet, timeNeedsSync, timeSet -} timeStatus_t ; - -typedef enum { - dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday -} timeDayOfWeek_t; - -typedef enum { - tmSecond, tmMinute, tmHour, tmWday, tmDay,tmMonth, tmYear, tmNbrFields -} tmByteFields; - -typedef struct { - uint8_t Second; - uint8_t Minute; - uint8_t Hour; - uint8_t Wday; // day of week, sunday is day 1 - uint8_t Day; - uint8_t Month; - uint8_t Year; // offset from 1970; -} tmElements_t, TimeElements, *tmElementsPtr_t; - -//convenience macros to convert to and from tm years -#define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year -#define CalendarYrToTm(Y) ((Y) - 1970) -#define tmYearToY2k(Y) ((Y) - 30) // offset is from 2000 -#define y2kYearToTm(Y) ((Y) + 30) - -typedef time_t(*getExternalTime)(); -//typedef void (*setExternalTime)(const time_t); // not used in this version - - -/*==============================================================================*/ -/* Useful Constants */ -#define SECS_PER_MIN (60UL) -#define SECS_PER_HOUR (3600UL) -#define SECS_PER_DAY (SECS_PER_HOUR * 24UL) -#define DAYS_PER_WEEK (7UL) -#define SECS_PER_WEEK (SECS_PER_DAY * DAYS_PER_WEEK) -#define SECS_PER_YEAR (SECS_PER_WEEK * 52UL) -#define SECS_YR_2000 (946684800UL) // the time at the start of y2k - -/* Useful Macros for getting elapsed time */ -#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN) -#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN) -#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR) -#define dayOfWeek(_time_) ((( _time_ / SECS_PER_DAY + 4) % DAYS_PER_WEEK)+1) // 1 = Sunday -#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) // this is number of days since Jan 1 1970 -#define elapsedSecsToday(_time_) (_time_ % SECS_PER_DAY) // the number of seconds since last midnight -// The following macros are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971 -// Always set the correct time before settting alarms -#define previousMidnight(_time_) (( _time_ / SECS_PER_DAY) * SECS_PER_DAY) // time at the start of the given day -#define nextMidnight(_time_) ( previousMidnight(_time_) + SECS_PER_DAY ) // time at the end of the given day -#define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) + ((dayOfWeek(_time_)-1) * SECS_PER_DAY) ) // note that week starts on day 1 -#define previousSunday(_time_) (_time_ - elapsedSecsThisWeek(_time_)) // time at the start of the week for the given time -#define nextSunday(_time_) ( previousSunday(_time_)+SECS_PER_WEEK) // time at the end of the week for the given time - - -/* Useful Macros for converting elapsed time to a time_t */ -#define minutesToTime_t ((M)) ( (M) * SECS_PER_MIN) -#define hoursToTime_t ((H)) ( (H) * SECS_PER_HOUR) -#define daysToTime_t ((D)) ( (D) * SECS_PER_DAY) // fixed on Jul 22 2011 -#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK) - -/*============================================================================*/ -/* time and date functions */ -int hour(); // the hour now -int hour(time_t t); // the hour for the given time -int hourFormat12(); // the hour now in 12 hour format -int hourFormat12(time_t t); // the hour for the given time in 12 hour format -uint8_t isAM(); // returns true if time now is AM -uint8_t isAM(time_t t); // returns true the given time is AM -uint8_t isPM(); // returns true if time now is PM -uint8_t isPM(time_t t); // returns true the given time is PM -int minute(); // the minute now -int minute(time_t t); // the minute for the given time -int second(); // the second now -int second(time_t t); // the second for the given time -int day(); // the day now -int day(time_t t); // the day for the given time -int weekday(); // the weekday now (Sunday is day 1) -int weekday(time_t t); // the weekday for the given time -int month(); // the month now (Jan is month 1) -int month(time_t t); // the month for the given time -int year(); // the full four digit year: (2009, 2010 etc) -int year(time_t t); // the year for the given time - -time_t now(); // return the current time as seconds since Jan 1 1970 -void setTime(time_t t); -void setTime(int hr,int min,int sec,int day, int month, int yr); -void adjustTime(long adjustment); - -/* date strings */ -#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null) -char* monthStr(uint8_t month); -char* dayStr(uint8_t day); -char* monthShortStr(uint8_t month); -char* dayShortStr(uint8_t day); - -/* time sync functions */ -timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized -void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider -void setSyncInterval(time_t interval); // set the number of seconds between re-sync - -/* low level functions to convert to and from system time */ -void breakTime(time_t time, tmElements_t &tm); // break time_t into elements -time_t makeTime(tmElements_t &tm); // convert time elements into time_t - - -#endif /* _Time_h */ - +#include "TimeLib.h" diff --git a/libraries/Time/TimeLib.h b/libraries/Time/TimeLib.h new file mode 100644 index 0000000..ddb1668 --- /dev/null +++ b/libraries/Time/TimeLib.h @@ -0,0 +1,144 @@ +/* + time.h - low level time and date functions +*/ + +/* + July 3 2011 - fixed elapsedSecsThisWeek macro (thanks Vincent Valdy for this) + - fixed daysToTime_t macro (thanks maniacbug) +*/ + +#ifndef _Time_h +#ifdef __cplusplus +#define _Time_h + +#include +#ifndef __AVR__ +#include // for __time_t_defined, but avr libc lacks sys/types.h +#endif + + +#if !defined(__time_t_defined) // avoid conflict with newlib or other posix libc +typedef unsigned long time_t; +#endif + + +// This ugly hack allows us to define C++ overloaded functions, when included +// from within an extern "C", as newlib's sys/stat.h does. Actually it is +// intended to include "time.h" from the C library (on ARM, but AVR does not +// have that file at all). On Mac and Windows, the compiler will find this +// "Time.h" instead of the C library "time.h", so we may cause other weird +// and unpredictable effects by conflicting with the C library header "time.h", +// but at least this hack lets us define C++ functions as intended. Hopefully +// nothing too terrible will result from overriding the C library header?! +extern "C++" { +typedef enum {timeNotSet, timeNeedsSync, timeSet +} timeStatus_t ; + +typedef enum { + dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday +} timeDayOfWeek_t; + +typedef enum { + tmSecond, tmMinute, tmHour, tmWday, tmDay,tmMonth, tmYear, tmNbrFields +} tmByteFields; + +typedef struct { + uint8_t Second; + uint8_t Minute; + uint8_t Hour; + uint8_t Wday; // day of week, sunday is day 1 + uint8_t Day; + uint8_t Month; + uint8_t Year; // offset from 1970; +} tmElements_t, TimeElements, *tmElementsPtr_t; + +//convenience macros to convert to and from tm years +#define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year +#define CalendarYrToTm(Y) ((Y) - 1970) +#define tmYearToY2k(Y) ((Y) - 30) // offset is from 2000 +#define y2kYearToTm(Y) ((Y) + 30) + +typedef time_t(*getExternalTime)(); +//typedef void (*setExternalTime)(const time_t); // not used in this version + + +/*==============================================================================*/ +/* Useful Constants */ +#define SECS_PER_MIN ((time_t)(60UL)) +#define SECS_PER_HOUR ((time_t)(3600UL)) +#define SECS_PER_DAY ((time_t)(SECS_PER_HOUR * 24UL)) +#define DAYS_PER_WEEK ((time_t)(7UL)) +#define SECS_PER_WEEK ((time_t)(SECS_PER_DAY * DAYS_PER_WEEK)) +#define SECS_PER_YEAR ((time_t)(SECS_PER_WEEK * 52UL)) +#define SECS_YR_2000 ((time_t)(946684800UL)) // the time at the start of y2k + +/* Useful Macros for getting elapsed time */ +#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN) +#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN) +#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR) +#define dayOfWeek(_time_) ((( _time_ / SECS_PER_DAY + 4) % DAYS_PER_WEEK)+1) // 1 = Sunday +#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) // this is number of days since Jan 1 1970 +#define elapsedSecsToday(_time_) (_time_ % SECS_PER_DAY) // the number of seconds since last midnight +// The following macros are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971 +// Always set the correct time before settting alarms +#define previousMidnight(_time_) (( _time_ / SECS_PER_DAY) * SECS_PER_DAY) // time at the start of the given day +#define nextMidnight(_time_) ( previousMidnight(_time_) + SECS_PER_DAY ) // time at the end of the given day +#define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) + ((dayOfWeek(_time_)-1) * SECS_PER_DAY) ) // note that week starts on day 1 +#define previousSunday(_time_) (_time_ - elapsedSecsThisWeek(_time_)) // time at the start of the week for the given time +#define nextSunday(_time_) ( previousSunday(_time_)+SECS_PER_WEEK) // time at the end of the week for the given time + + +/* Useful Macros for converting elapsed time to a time_t */ +#define minutesToTime_t ((M)) ( (M) * SECS_PER_MIN) +#define hoursToTime_t ((H)) ( (H) * SECS_PER_HOUR) +#define daysToTime_t ((D)) ( (D) * SECS_PER_DAY) // fixed on Jul 22 2011 +#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK) + +/*============================================================================*/ +/* time and date functions */ +int hour(); // the hour now +int hour(time_t t); // the hour for the given time +int hourFormat12(); // the hour now in 12 hour format +int hourFormat12(time_t t); // the hour for the given time in 12 hour format +uint8_t isAM(); // returns true if time now is AM +uint8_t isAM(time_t t); // returns true the given time is AM +uint8_t isPM(); // returns true if time now is PM +uint8_t isPM(time_t t); // returns true the given time is PM +int minute(); // the minute now +int minute(time_t t); // the minute for the given time +int second(); // the second now +int second(time_t t); // the second for the given time +int day(); // the day now +int day(time_t t); // the day for the given time +int weekday(); // the weekday now (Sunday is day 1) +int weekday(time_t t); // the weekday for the given time +int month(); // the month now (Jan is month 1) +int month(time_t t); // the month for the given time +int year(); // the full four digit year: (2009, 2010 etc) +int year(time_t t); // the year for the given time + +time_t now(); // return the current time as seconds since Jan 1 1970 +void setTime(time_t t); +void setTime(int hr,int min,int sec,int day, int month, int yr); +void adjustTime(long adjustment); + +/* date strings */ +#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null) +char* monthStr(uint8_t month); +char* dayStr(uint8_t day); +char* monthShortStr(uint8_t month); +char* dayShortStr(uint8_t day); + +/* time sync functions */ +timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized +void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider +void setSyncInterval(time_t interval); // set the number of seconds between re-sync + +/* low level functions to convert to and from system time */ +void breakTime(time_t time, tmElements_t &tm); // break time_t into elements +time_t makeTime(tmElements_t &tm); // convert time elements into time_t + +} // extern "C++" +#endif // __cplusplus +#endif /* _Time_h */ + diff --git a/libraries/Time/examples/TimeArduinoDue/TimeArduinoDue.ino b/libraries/Time/examples/TimeArduinoDue/TimeArduinoDue.ino new file mode 100644 index 0000000..f0a9a95 --- /dev/null +++ b/libraries/Time/examples/TimeArduinoDue/TimeArduinoDue.ino @@ -0,0 +1,71 @@ +/* + * TimeRTC.pde + * example code illustrating Time library with Real Time Clock. + * + * This example requires Markus Lange's Arduino Due RTC Library + * https://github.com/MarkusLange/Arduino-Due-RTC-Library + */ + +#include +#include + +// Select the Slowclock source +//RTC_clock rtc_clock(RC); +RTC_clock rtc_clock(XTAL); + +void setup() { + Serial.begin(9600); + rtc_clock.init(); + if (rtc_clock.date_already_set() == 0) { + // Unfortunately, the Arduino Due hardware does not seem to + // be designed to maintain the RTC clock state when the + // board resets. Markus described it thusly: "Uhh the Due + // does reset with the NRSTB pin. This resets the full chip + // with all backup regions including RTC, RTT and SC. Only + // if the reset is done with the NRST pin will these regions + // stay with their old values." + rtc_clock.set_time(__TIME__); + rtc_clock.set_date(__DATE__); + // However, this might work on other unofficial SAM3X boards + // with different reset circuitry than Arduino Due? + } + setSyncProvider(getArduinoDueTime); + if(timeStatus()!= timeSet) + Serial.println("Unable to sync with the RTC"); + else + Serial.println("RTC has set the system time"); +} + +time_t getArduinoDueTime() +{ + return rtc_clock.unixtime(); +} + +void loop() +{ + digitalClockDisplay(); + delay(1000); +} + +void digitalClockDisplay(){ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + diff --git a/libraries/Time/examples/TimeGPS/TimeGPS.ino b/libraries/Time/examples/TimeGPS/TimeGPS.ino new file mode 100644 index 0000000..fea9698 --- /dev/null +++ b/libraries/Time/examples/TimeGPS/TimeGPS.ino @@ -0,0 +1,87 @@ +/* + * TimeGPS.pde + * example code illustrating time synced from a GPS + * + */ + +#include +#include // http://arduiniana.org/libraries/TinyGPS/ +#include +// TinyGPS and SoftwareSerial libraries are the work of Mikal Hart + +SoftwareSerial SerialGPS = SoftwareSerial(10, 11); // receive on pin 10 +TinyGPS gps; + +// To use a hardware serial port, which is far more efficient than +// SoftwareSerial, uncomment this line and remove SoftwareSerial +//#define SerialGPS Serial1 + +// Offset hours from gps time (UTC) +const int offset = 1; // Central European Time +//const int offset = -5; // Eastern Standard Time (USA) +//const int offset = -4; // Eastern Daylight Time (USA) +//const int offset = -8; // Pacific Standard Time (USA) +//const int offset = -7; // Pacific Daylight Time (USA) + +// Ideally, it should be possible to learn the time zone +// based on the GPS position data. However, that would +// require a complex library, probably incorporating some +// sort of database using Eric Muller's time zone shape +// maps, at http://efele.net/maps/tz/ + +time_t prevDisplay = 0; // when the digital clock was displayed + +void setup() +{ + Serial.begin(9600); + while (!Serial) ; // Needed for Leonardo only + SerialGPS.begin(4800); + Serial.println("Waiting for GPS time ... "); +} + +void loop() +{ + while (SerialGPS.available()) { + if (gps.encode(SerialGPS.read())) { // process gps messages + // when TinyGPS reports new data... + unsigned long age; + int Year; + byte Month, Day, Hour, Minute, Second; + gps.crack_datetime(&Year, &Month, &Day, &Hour, &Minute, &Second, NULL, &age); + if (age < 500) { + // set the Time to the latest GPS reading + setTime(Hour, Minute, Second, Day, Month, Year); + adjustTime(offset * SECS_PER_HOUR); + } + } + } + if (timeStatus()!= timeNotSet) { + if (now() != prevDisplay) { //update the display only if the time has changed + prevDisplay = now(); + digitalClockDisplay(); + } + } +} + +void digitalClockDisplay(){ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits) { + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + diff --git a/libraries/Time/examples/TimeNTP/TimeNTP.ino b/libraries/Time/examples/TimeNTP/TimeNTP.ino new file mode 100644 index 0000000..17a908f --- /dev/null +++ b/libraries/Time/examples/TimeNTP/TimeNTP.ino @@ -0,0 +1,135 @@ +/* + * Time_NTP.pde + * Example showing time sync to NTP time source + * + * This sketch uses the Ethernet library + */ + +#include +#include +#include +#include + +byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +// NTP Servers: +IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov +// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov +// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov + + +const int timeZone = 1; // Central European Time +//const int timeZone = -5; // Eastern Standard Time (USA) +//const int timeZone = -4; // Eastern Daylight Time (USA) +//const int timeZone = -8; // Pacific Standard Time (USA) +//const int timeZone = -7; // Pacific Daylight Time (USA) + + +EthernetUDP Udp; +unsigned int localPort = 8888; // local port to listen for UDP packets + +void setup() +{ + Serial.begin(9600); + while (!Serial) ; // Needed for Leonardo only + delay(250); + Serial.println("TimeNTP Example"); + if (Ethernet.begin(mac) == 0) { + // no point in carrying on, so do nothing forevermore: + while (1) { + Serial.println("Failed to configure Ethernet using DHCP"); + delay(10000); + } + } + Serial.print("IP number assigned by DHCP is "); + Serial.println(Ethernet.localIP()); + Udp.begin(localPort); + Serial.println("waiting for sync"); + setSyncProvider(getNtpTime); +} + +time_t prevDisplay = 0; // when the digital clock was displayed + +void loop() +{ + if (timeStatus() != timeNotSet) { + if (now() != prevDisplay) { //update the display only if time has changed + prevDisplay = now(); + digitalClockDisplay(); + } + } +} + +void digitalClockDisplay(){ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits){ + // utility for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +/*-------- NTP code ----------*/ + +const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message +byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets + +time_t getNtpTime() +{ + while (Udp.parsePacket() > 0) ; // discard any previously received packets + Serial.println("Transmit NTP Request"); + sendNTPpacket(timeServer); + uint32_t beginWait = millis(); + while (millis() - beginWait < 1500) { + int size = Udp.parsePacket(); + if (size >= NTP_PACKET_SIZE) { + Serial.println("Receive NTP Response"); + Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer + unsigned long secsSince1900; + // convert four bytes starting at location 40 to a long integer + secsSince1900 = (unsigned long)packetBuffer[40] << 24; + secsSince1900 |= (unsigned long)packetBuffer[41] << 16; + secsSince1900 |= (unsigned long)packetBuffer[42] << 8; + secsSince1900 |= (unsigned long)packetBuffer[43]; + return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR; + } + } + Serial.println("No NTP Response :-("); + return 0; // return 0 if unable to get the time +} + +// send an NTP request to the time server at the given address +void sendNTPpacket(IPAddress &address) +{ + // set all bytes in the buffer to 0 + memset(packetBuffer, 0, NTP_PACKET_SIZE); + // Initialize values needed to form NTP request + // (see URL above for details on the packets) + packetBuffer[0] = 0b11100011; // LI, Version, Mode + packetBuffer[1] = 0; // Stratum, or type of clock + packetBuffer[2] = 6; // Polling Interval + packetBuffer[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + packetBuffer[12] = 49; + packetBuffer[13] = 0x4E; + packetBuffer[14] = 49; + packetBuffer[15] = 52; + // all NTP fields have been given values, now + // you can send a packet requesting a timestamp: + Udp.beginPacket(address, 123); //NTP requests are to port 123 + Udp.write(packetBuffer, NTP_PACKET_SIZE); + Udp.endPacket(); +} + diff --git a/libraries/Time/examples/TimeNTP_ESP8266WiFi/TimeNTP_ESP8266WiFi.ino b/libraries/Time/examples/TimeNTP_ESP8266WiFi/TimeNTP_ESP8266WiFi.ino new file mode 100644 index 0000000..1aeb2d7 --- /dev/null +++ b/libraries/Time/examples/TimeNTP_ESP8266WiFi/TimeNTP_ESP8266WiFi.ino @@ -0,0 +1,156 @@ +/* + * TimeNTP_ESP8266WiFi.ino + * Example showing time sync to NTP time source + * + * This sketch uses the ESP8266WiFi library + */ + +#include +#include +#include + +const char ssid[] = "*************"; // your network SSID (name) +const char pass[] = "********"; // your network password + +// NTP Servers: +static const char ntpServerName[] = "us.pool.ntp.org"; +//static const char ntpServerName[] = "time.nist.gov"; +//static const char ntpServerName[] = "time-a.timefreq.bldrdoc.gov"; +//static const char ntpServerName[] = "time-b.timefreq.bldrdoc.gov"; +//static const char ntpServerName[] = "time-c.timefreq.bldrdoc.gov"; + +const int timeZone = 1; // Central European Time +//const int timeZone = -5; // Eastern Standard Time (USA) +//const int timeZone = -4; // Eastern Daylight Time (USA) +//const int timeZone = -8; // Pacific Standard Time (USA) +//const int timeZone = -7; // Pacific Daylight Time (USA) + + +WiFiUDP Udp; +unsigned int localPort = 8888; // local port to listen for UDP packets + +time_t getNtpTime(); +void digitalClockDisplay(); +void printDigits(int digits); +void sendNTPpacket(IPAddress &address); + +void setup() +{ + Serial.begin(9600); + while (!Serial) ; // Needed for Leonardo only + delay(250); + Serial.println("TimeNTP Example"); + Serial.print("Connecting to "); + Serial.println(ssid); + WiFi.begin(ssid, pass); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.print("IP number assigned by DHCP is "); + Serial.println(WiFi.localIP()); + Serial.println("Starting UDP"); + Udp.begin(localPort); + Serial.print("Local port: "); + Serial.println(Udp.localPort()); + Serial.println("waiting for sync"); + setSyncProvider(getNtpTime); + setSyncInterval(300); +} + +time_t prevDisplay = 0; // when the digital clock was displayed + +void loop() +{ + if (timeStatus() != timeNotSet) { + if (now() != prevDisplay) { //update the display only if time has changed + prevDisplay = now(); + digitalClockDisplay(); + } + } +} + +void digitalClockDisplay() +{ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print("."); + Serial.print(month()); + Serial.print("."); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits) +{ + // utility for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if (digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +/*-------- NTP code ----------*/ + +const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message +byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets + +time_t getNtpTime() +{ + IPAddress ntpServerIP; // NTP server's ip address + + while (Udp.parsePacket() > 0) ; // discard any previously received packets + Serial.println("Transmit NTP Request"); + // get a random server from the pool + WiFi.hostByName(ntpServerName, ntpServerIP); + Serial.print(ntpServerName); + Serial.print(": "); + Serial.println(ntpServerIP); + sendNTPpacket(ntpServerIP); + uint32_t beginWait = millis(); + while (millis() - beginWait < 1500) { + int size = Udp.parsePacket(); + if (size >= NTP_PACKET_SIZE) { + Serial.println("Receive NTP Response"); + Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer + unsigned long secsSince1900; + // convert four bytes starting at location 40 to a long integer + secsSince1900 = (unsigned long)packetBuffer[40] << 24; + secsSince1900 |= (unsigned long)packetBuffer[41] << 16; + secsSince1900 |= (unsigned long)packetBuffer[42] << 8; + secsSince1900 |= (unsigned long)packetBuffer[43]; + return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR; + } + } + Serial.println("No NTP Response :-("); + return 0; // return 0 if unable to get the time +} + +// send an NTP request to the time server at the given address +void sendNTPpacket(IPAddress &address) +{ + // set all bytes in the buffer to 0 + memset(packetBuffer, 0, NTP_PACKET_SIZE); + // Initialize values needed to form NTP request + // (see URL above for details on the packets) + packetBuffer[0] = 0b11100011; // LI, Version, Mode + packetBuffer[1] = 0; // Stratum, or type of clock + packetBuffer[2] = 6; // Polling Interval + packetBuffer[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + packetBuffer[12] = 49; + packetBuffer[13] = 0x4E; + packetBuffer[14] = 49; + packetBuffer[15] = 52; + // all NTP fields have been given values, now + // you can send a packet requesting a timestamp: + Udp.beginPacket(address, 123); //NTP requests are to port 123 + Udp.write(packetBuffer, NTP_PACKET_SIZE); + Udp.endPacket(); +} diff --git a/libraries/Time/Examples/TimeRTC/TimeRTC.pde b/libraries/Time/examples/TimeRTC/TimeRTC.ino similarity index 71% rename from libraries/Time/Examples/TimeRTC/TimeRTC.pde rename to libraries/Time/examples/TimeRTC/TimeRTC.ino index 0e37c51..fa10ff6 100644 --- a/libraries/Time/Examples/TimeRTC/TimeRTC.pde +++ b/libraries/Time/examples/TimeRTC/TimeRTC.ino @@ -4,12 +4,13 @@ * */ -#include -#include +#include +#include #include // a basic DS1307 library that returns time as a time_t void setup() { Serial.begin(9600); + while (!Serial) ; // wait until Arduino Serial Monitor opens setSyncProvider(RTC.get); // the function to get the time from the RTC if(timeStatus()!= timeSet) Serial.println("Unable to sync with the RTC"); @@ -19,8 +20,15 @@ void setup() { void loop() { - digitalClockDisplay(); - delay(1000); + if (timeStatus() == timeSet) { + digitalClockDisplay(); + } else { + Serial.println("The time has not been set. Please run the Time"); + Serial.println("TimeRTCSet example, or DS1307RTC SetTime example."); + Serial.println(); + delay(4000); + } + delay(1000); } void digitalClockDisplay(){ diff --git a/libraries/Time/Examples/TimeRTCLog/TimeRTCLog.pde b/libraries/Time/examples/TimeRTCLog/TimeRTCLog.ino similarity index 94% rename from libraries/Time/Examples/TimeRTCLog/TimeRTCLog.pde rename to libraries/Time/examples/TimeRTCLog/TimeRTCLog.ino index b8297b6..0b250c2 100644 --- a/libraries/Time/Examples/TimeRTCLog/TimeRTCLog.pde +++ b/libraries/Time/examples/TimeRTCLog/TimeRTCLog.ino @@ -6,8 +6,8 @@ * the time of the event and time since the previous event is calculated and sent to the serial port. */ -#include -#include +#include +#include #include // a basic DS1307 library that returns time as a time_t const int nbrInputPins = 6; // monitor 6 digital pins @@ -20,8 +20,9 @@ void setup() { setSyncProvider(RTC.get); // the function to sync the time from the RTC for(int i=0; i < nbrInputPins; i++){ pinMode( inputPins[i], INPUT); - // digitalWrite( inputPins[i], HIGH); // uncomment these lines if - // state[i] = HIGH; // pull-up resistors are wanted + // uncomment these lines if pull-up resistors are wanted + // pinMode( inputPins[i], INPUT_PULLUP); + // state[i] = HIGH; } } diff --git a/libraries/Time/examples/TimeRTCSet/TimeRTCSet.ino b/libraries/Time/examples/TimeRTCSet/TimeRTCSet.ino new file mode 100644 index 0000000..49c49f3 --- /dev/null +++ b/libraries/Time/examples/TimeRTCSet/TimeRTCSet.ino @@ -0,0 +1,80 @@ +/* + * TimeRTCSet.pde + * example code illustrating Time library with Real Time Clock. + * + * RTC clock is set in response to serial port time message + * A Processing example sketch to set the time is included in the download + * On Linux, you can use "date +T%s > /dev/ttyACM0" (UTC time zone) + */ + +#include +#include +#include // a basic DS1307 library that returns time as a time_t + + +void setup() { + Serial.begin(9600); + while (!Serial) ; // Needed for Leonardo only + setSyncProvider(RTC.get); // the function to get the time from the RTC + if (timeStatus() != timeSet) + Serial.println("Unable to sync with the RTC"); + else + Serial.println("RTC has set the system time"); +} + +void loop() +{ + if (Serial.available()) { + time_t t = processSyncMessage(); + if (t != 0) { + RTC.set(t); // set the RTC and the system time to the received value + setTime(t); + } + } + digitalClockDisplay(); + delay(1000); +} + +void digitalClockDisplay(){ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +/* code to process time sync messages from the serial port */ +#define TIME_HEADER "T" // Header tag for serial time sync message + +unsigned long processSyncMessage() { + unsigned long pctime = 0L; + const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 + + if(Serial.find(TIME_HEADER)) { + pctime = Serial.parseInt(); + return pctime; + if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013) + pctime = 0L; // return 0 to indicate that the time is not valid + } + } + return pctime; +} + + + + + diff --git a/libraries/Time/Examples/TimeSerial/TimeSerial.pde b/libraries/Time/examples/TimeSerial/TimeSerial.ino similarity index 56% rename from libraries/Time/Examples/TimeSerial/TimeSerial.pde rename to libraries/Time/examples/TimeSerial/TimeSerial.ino index 382c598..07e609f 100644 --- a/libraries/Time/Examples/TimeSerial/TimeSerial.pde +++ b/libraries/Time/examples/TimeSerial/TimeSerial.ino @@ -3,34 +3,38 @@ * example code illustrating Time library set through serial port messages. * * Messages consist of the letter T followed by ten digit time (as seconds since Jan 1 1970) - * you can send the text on the next line using Serial Monitor to set the clock to noon Jan 1 2010 - T1262347200 + * you can send the text on the next line using Serial Monitor to set the clock to noon Jan 1 2013 + T1357041600 * - * A Processing example sketch to automatically send the messages is inclided in the download + * A Processing example sketch to automatically send the messages is included in the download + * On Linux, you can use "date +T%s\n > /dev/ttyACM0" (UTC time zone) */ -#include +#include -#define TIME_MSG_LEN 11 // time sync to PC is HEADER followed by unix time_t as ten ascii digits -#define TIME_HEADER 'T' // Header tag for serial time sync message +#define TIME_HEADER "T" // Header tag for serial time sync message #define TIME_REQUEST 7 // ASCII bell character requests a time sync message void setup() { Serial.begin(9600); + while (!Serial) ; // Needed for Leonardo only + pinMode(13, OUTPUT); setSyncProvider( requestSync); //set function to call when sync required Serial.println("Waiting for sync message"); } void loop(){ - if(Serial.available() ) - { + if (Serial.available()) { processSyncMessage(); } - if(timeStatus()!= timeNotSet) - { - digitalWrite(13,timeStatus() == timeSet); // on if synced, off if needs refresh + if (timeStatus()!= timeNotSet) { digitalClockDisplay(); } + if (timeStatus() == timeSet) { + digitalWrite(13, HIGH); // LED on if synced + } else { + digitalWrite(13, LOW); // LED off if needs refresh + } delay(1000); } @@ -56,27 +60,22 @@ void printDigits(int digits){ Serial.print(digits); } + void processSyncMessage() { - // if time sync available from serial port, update time and return true - while(Serial.available() >= TIME_MSG_LEN ){ // time message consists of a header and ten ascii digits - char c = Serial.read() ; - Serial.print(c); - if( c == TIME_HEADER ) { - time_t pctime = 0; - for(int i=0; i < TIME_MSG_LEN -1; i++){ - c = Serial.read(); - if( c >= '0' && c <= '9'){ - pctime = (10 * pctime) + (c - '0') ; // convert digits to a number - } - } - setTime(pctime); // Sync Arduino clock to the time received on the serial port - } + unsigned long pctime; + const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 + + if(Serial.find(TIME_HEADER)) { + pctime = Serial.parseInt(); + if( pctime >= DEFAULT_TIME) { // check the integer is a valid time (greater than Jan 1 2013) + setTime(pctime); // Sync Arduino clock to the time received on the serial port + } } } time_t requestSync() { - Serial.print(TIME_REQUEST,BYTE); + Serial.write(TIME_REQUEST); return 0; // the time will be sent later in response to serial mesg } diff --git a/libraries/Time/examples/TimeSerialDateStrings/TimeSerialDateStrings.ino b/libraries/Time/examples/TimeSerialDateStrings/TimeSerialDateStrings.ino new file mode 100644 index 0000000..95d2568 --- /dev/null +++ b/libraries/Time/examples/TimeSerialDateStrings/TimeSerialDateStrings.ino @@ -0,0 +1,108 @@ +/* + * TimeSerialDateStrings.pde + * example code illustrating Time library date strings + * + * This sketch adds date string functionality to TimeSerial sketch + * Also shows how to handle different messages + * + * A message starting with a time header sets the time + * A Processing example sketch to automatically send the messages is inclided in the download + * On Linux, you can use "date +T%s\n > /dev/ttyACM0" (UTC time zone) + * + * A message starting with a format header sets the date format + + * send: Fs\n for short date format + * send: Fl\n for long date format + */ + +#include + +// single character message tags +#define TIME_HEADER 'T' // Header tag for serial time sync message +#define FORMAT_HEADER 'F' // Header tag indicating a date format message +#define FORMAT_SHORT 's' // short month and day strings +#define FORMAT_LONG 'l' // (lower case l) long month and day strings + +#define TIME_REQUEST 7 // ASCII bell character requests a time sync message + +static boolean isLongFormat = true; + +void setup() { + Serial.begin(9600); + while (!Serial) ; // Needed for Leonardo only + setSyncProvider( requestSync); //set function to call when sync required + Serial.println("Waiting for sync message"); +} + +void loop(){ + if (Serial.available() > 1) { // wait for at least two characters + char c = Serial.read(); + if( c == TIME_HEADER) { + processSyncMessage(); + } + else if( c== FORMAT_HEADER) { + processFormatMessage(); + } + } + if (timeStatus()!= timeNotSet) { + digitalClockDisplay(); + } + delay(1000); +} + +void digitalClockDisplay() { + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + if(isLongFormat) + Serial.print(dayStr(weekday())); + else + Serial.print(dayShortStr(weekday())); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + if(isLongFormat) + Serial.print(monthStr(month())); + else + Serial.print(monthShortStr(month())); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits) { + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +void processFormatMessage() { + char c = Serial.read(); + if( c == FORMAT_LONG){ + isLongFormat = true; + Serial.println(F("Setting long format")); + } + else if( c == FORMAT_SHORT) { + isLongFormat = false; + Serial.println(F("Setting short format")); + } +} + +void processSyncMessage() { + unsigned long pctime; + const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 - paul, perhaps we define in time.h? + + pctime = Serial.parseInt(); + if( pctime >= DEFAULT_TIME) { // check the integer is a valid time (greater than Jan 1 2013) + setTime(pctime); // Sync Arduino clock to the time received on the serial port + } +} + +time_t requestSync() { + Serial.write(TIME_REQUEST); + return 0; // the time will be sent later in response to serial mesg +} diff --git a/libraries/Time/examples/TimeTeensy3/TimeTeensy3.ino b/libraries/Time/examples/TimeTeensy3/TimeTeensy3.ino new file mode 100644 index 0000000..f68dd8c --- /dev/null +++ b/libraries/Time/examples/TimeTeensy3/TimeTeensy3.ino @@ -0,0 +1,78 @@ +/* + * TimeRTC.pde + * example code illustrating Time library with Real Time Clock. + * + */ + +#include + +void setup() { + // set the Time library to use Teensy 3.0's RTC to keep time + setSyncProvider(getTeensy3Time); + + Serial.begin(115200); + while (!Serial); // Wait for Arduino Serial Monitor to open + delay(100); + if (timeStatus()!= timeSet) { + Serial.println("Unable to sync with the RTC"); + } else { + Serial.println("RTC has set the system time"); + } +} + +void loop() { + if (Serial.available()) { + time_t t = processSyncMessage(); + if (t != 0) { + Teensy3Clock.set(t); // set the RTC + setTime(t); + } + } + digitalClockDisplay(); + delay(1000); +} + +void digitalClockDisplay() { + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print(" "); + Serial.print(month()); + Serial.print(" "); + Serial.print(year()); + Serial.println(); +} + +time_t getTeensy3Time() +{ + return Teensy3Clock.get(); +} + +/* code to process time sync messages from the serial port */ +#define TIME_HEADER "T" // Header tag for serial time sync message + +unsigned long processSyncMessage() { + unsigned long pctime = 0L; + const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 + + if(Serial.find(TIME_HEADER)) { + pctime = Serial.parseInt(); + return pctime; + if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013) + pctime = 0L; // return 0 to indicate that the time is not valid + } + } + return pctime; +} + +void printDigits(int digits){ + // utility function for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if(digits < 10) + Serial.print('0'); + Serial.print(digits); +} + diff --git a/libraries/Time/keywords.txt b/libraries/Time/keywords.txt index f921672..073f8f8 100644 --- a/libraries/Time/keywords.txt +++ b/libraries/Time/keywords.txt @@ -5,25 +5,26 @@ ####################################### # Datatypes (KEYWORD1) ####################################### -time_t KEYWORD1 +time_t KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### now KEYWORD2 -second KEYWORD2 +second KEYWORD2 minute KEYWORD2 -hour KEYWORD2 -day KEYWORD2 -month KEYWORD2 -year KEYWORD2 -isAM KEYWORD2 -isPM KEYWORD2 -weekday KEYWORD2 -setTime KEYWORD2 -adjustTime KEYWORD2 -setSyncProvider KEYWORD2 -setSyncInteval KEYWORD2 -timeStatus KEYWORD2 +hour KEYWORD2 +day KEYWORD2 +month KEYWORD2 +year KEYWORD2 +isAM KEYWORD2 +isPM KEYWORD2 +weekday KEYWORD2 +setTime KEYWORD2 +adjustTime KEYWORD2 +setSyncProvider KEYWORD2 +setSyncInterval KEYWORD2 +timeStatus KEYWORD2 +TimeLib KEYWORD2 ####################################### # Instances (KEYWORD2) ####################################### diff --git a/libraries/Time/library.json b/libraries/Time/library.json new file mode 100644 index 0000000..6603650 --- /dev/null +++ b/libraries/Time/library.json @@ -0,0 +1,26 @@ +{ + "name": "Time", + "description": "Time keeping library", + "keywords": "Time, date, hour, minute, second, day, week, month, year, RTC", + "authors": [ + { + "name": "Michael Margolis" + }, + { + "name": "Paul Stoffregen", + "email": "paul@pjrc.com", + "url": "http://www.pjrc.com", + "maintainer": true + } + ], + "repository": { + "type": "git", + "url": "https://github.com/PaulStoffregen/Time" + }, + "version": "1.5", + "homepage": "http://playground.arduino.cc/Code/Time", + "frameworks": "Arduino", + "examples": [ + "examples/*/*.ino" + ] +} diff --git a/libraries/Time/library.properties b/libraries/Time/library.properties new file mode 100644 index 0000000..49b1e2a --- /dev/null +++ b/libraries/Time/library.properties @@ -0,0 +1,10 @@ +name=Time +version=1.5 +author=Michael Margolis +maintainer=Paul Stoffregen +sentence=Timekeeping functionality for Arduino +paragraph=Date and Time functions, with provisions to synchronize to external time sources like GPS and NTP (Internet). This library is often used together with TimeAlarms and DS1307RTC. +category=Timing +url=http://playground.arduino.cc/code/time +architectures=* +