Arduino: RTC DS3231 NTP Sync

From OnnoWiki
Revision as of 07:51, 7 June 2018 by Onnowpurbo (talk | contribs) (Created page with "==Source== #include "Wire.h" #include <Time.h> #include <SPI.h> #include <Ethernet.h> #include <EthernetUdp.h> #define DS3231_I2C_ADDRESS 0x68 // Ethernet library configur...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Source

  1. include "Wire.h"
  2. include <Time.h>
  3. include <SPI.h>
  4. include <Ethernet.h>
  5. include <EthernetUdp.h>
  1. define DS3231_I2C_ADDRESS 0x68

// Ethernet library configuration byte mac[] = { 0x24, 0x7B, 0xA2, 0x4A, 0x52, 0x10 }; IPAddress timeServer(128, 138, 140, 44 ); // time.nist.gov

unsigned int localPort = 8888; const int NTP_PACKET_SIZE= 48; byte packetBuffer[NTP_PACKET_SIZE]; EthernetUDP Udp;

void setup() {

 // Setup Communication
 Wire.begin();
 Serial.begin(9600);
 Serial.print("OK Serial\n");
 Ethernet.begin(mac);
 Serial.print("OK LAN\n");
 Udp.begin(localPort);
 Serial.print("OK Comm\n");
 setSyncInterval(10); // Set seconds between re-sync
 setSyncProvider(getNtpTime);
 getNtpTime;
   Serial.print("OK NTP\n");
 // set the initial time here:
 // DS3231 seconds, minutes, hours, day, date, month, year
 // setDS3231time(30,33,9, 2 ,28,11,16);

}

void loop() {

 setSyncProvider(getNtpTime);
 // set the initial time here:
 // DS3231 seconds, minutes, hours, day, date, month, year
 setDS3231time(second(), minute(), hour()+7, 5 , 7, 6, 18);
 
 displayTime(); // display the real-time clock data on the Serial Monitor,
 getNtpTime;
 // delay(1000);  

}


/*----------------- DS3231 ----------------------*/

// Convert normal decimal numbers to binary coded decimal byte decToBcd(byte val) {

 return ( (val / 10 * 16) + (val % 10) );

} // Convert binary coded decimal to normal decimal numbers byte bcdToDec(byte val) {

 return ( (val / 16 * 10) + (val % 16) );

}

void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte

                  dayOfMonth, byte month, byte year)

{

 // sets time and date data to DS3231
 Wire.beginTransmission(DS3231_I2C_ADDRESS);
 Wire.write(0); // set next input to start at the seconds register
 Wire.write(decToBcd(second)); // set seconds
 Wire.write(decToBcd(minute)); // set minutes
 Wire.write(decToBcd(hour)); // set hours
 Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
 Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
 Wire.write(decToBcd(month)); // set month
 Wire.write(decToBcd(year)); // set year (0 to 99)
 Wire.endTransmission();

} void readDS3231time(byte *second,

                   byte *minute,
                   byte *hour,
                   byte *dayOfWeek,
                   byte *dayOfMonth,
                   byte *month,
                   byte *year)

{

 Wire.beginTransmission(DS3231_I2C_ADDRESS);
 Wire.write(0); // set DS3231 register pointer to 00h
 Wire.endTransmission();
 Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
 // request seven bytes of data from DS3231 starting from register 00h
 *second = bcdToDec(Wire.read() & 0x7f);
 *minute = bcdToDec(Wire.read());
 *hour = bcdToDec(Wire.read() & 0x3f);
 *dayOfWeek = bcdToDec(Wire.read());
 *dayOfMonth = bcdToDec(Wire.read());
 *month = bcdToDec(Wire.read());
 *year = bcdToDec(Wire.read());

} void displayTime() {

 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
 // retrieve data from DS3231
 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
                &year);
 // send it to the serial monitor
 Serial.print(hour, DEC);
 // convert the byte variable to a decimal number when displayed
 Serial.print(":");
 if (minute < 10)
 {
   Serial.print("0");
 }
 Serial.print(minute, DEC);
 Serial.print(":");
 if (second < 10)
 {
   Serial.print("0");
 }
 Serial.print(second, DEC);
 Serial.print(" ");
 Serial.print(dayOfMonth, DEC);
 Serial.print("/");
 Serial.print(month, DEC);
 Serial.print("/");
 Serial.print(year, DEC);
 Serial.print(" Day of week: ");
 switch (dayOfWeek) {
   case 1:
     Serial.println("Sunday");
     break;
   case 2:
     Serial.println("Monday");
     break;
   case 3:
     Serial.println("Tuesday");
     break;
   case 4:
     Serial.println("Wednesday");
     break;
   case 5:
     Serial.println("Thursday");
     break;
   case 6:
     Serial.println("Friday");
     break;
   case 7:
     Serial.println("Saturday");
     break;
 }

}



/*-------- NTP code ----------*/

unsigned long getNtpTime() {

 sendNTPpacket(timeServer); // send an NTP packet to a time server
   delay(500);
 
   if ( Udp.parsePacket() ) {
    Udp.read(packetBuffer,NTP_PACKET_SIZE);
    unsigned long hi = word(packetBuffer[40], packetBuffer[41]);
    unsigned long low = word(packetBuffer[42], packetBuffer[43]);
    unsigned long secsSince1900 = hi << 16 | low; 
    const unsigned long seventyYears = 2208988800UL;     
    unsigned long epoch = secsSince1900 - seventyYears;
    return epoch;
 }
 return 0; // return 0 if unable to get the time

}

unsigned long sendNTPpacket(IPAddress& address) {

 memset(packetBuffer, 0, NTP_PACKET_SIZE);  // set all bytes in the buffer to 0
 // Initialize values needed to form NTP request
 packetBuffer[0] = B11100011;   // LI, Version, Mode
 packetBuffer[1] = 0;     // Stratum
 packetBuffer[2] = 6;     // Max Interval between messages in seconds
 packetBuffer[3] = 0xEC;  // Clock Precision
 // bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset
 packetBuffer[12]  = 49;  // four-byte reference ID identifying
 packetBuffer[13]  = 0x4E;
 packetBuffer[14]  = 49;
 packetBuffer[15]  = 52;
 // send the packet requesting a timestamp:
 Udp.beginPacket(address, 123); //NTP requests are to port 123
 Udp.write(packetBuffer,NTP_PACKET_SIZE);
 Udp.endPacket();

}