Difference between revisions of "Arduino: RTC DS3231 NTP Sync"

From OnnoWiki
Jump to navigation Jump to search
(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...")
 
 
Line 2: Line 2:
  
  
#include "Wire.h"
+
#include "Wire.h"
#include <Time.h>
+
#include <Time.h>
#include <SPI.h>
+
#include <SPI.h>
#include <Ethernet.h>
+
#include <Ethernet.h>
#include <EthernetUdp.h>
+
#include <EthernetUdp.h>
 
+
#define DS3231_I2C_ADDRESS 0x68
+
#define DS3231_I2C_ADDRESS 0x68
 
+
// Ethernet library configuration
+
// Ethernet library configuration
byte mac[] = { 0x24, 0x7B, 0xA2, 0x4A, 0x52, 0x10 };
+
byte mac[] = { 0x24, 0x7B, 0xA2, 0x4A, 0x52, 0x10 };
IPAddress timeServer(128, 138, 140, 44 ); // time.nist.gov
+
IPAddress timeServer(128, 138, 140, 44 ); // time.nist.gov
 
+
unsigned int localPort = 8888;
+
unsigned int localPort = 8888;
const int NTP_PACKET_SIZE= 48;     
+
const int NTP_PACKET_SIZE= 48;     
byte packetBuffer[NTP_PACKET_SIZE];  
+
byte packetBuffer[NTP_PACKET_SIZE];  
EthernetUDP Udp;
+
EthernetUDP Udp;
 
+
void setup()
+
void setup()
{
+
{
  // Setup Communication
+
  // Setup Communication
  Wire.begin();
+
  Wire.begin();
  Serial.begin(9600);
+
  Serial.begin(9600);
  Serial.print("OK Serial\n");
+
  Serial.print("OK Serial\n");
  Ethernet.begin(mac);
+
  Ethernet.begin(mac);
  Serial.print("OK LAN\n");
+
  Serial.print("OK LAN\n");
  Udp.begin(localPort);
+
  Udp.begin(localPort);
 
+
  Serial.print("OK Comm\n");
+
  Serial.print("OK Comm\n");
  setSyncInterval(10); // Set seconds between re-sync
+
  setSyncInterval(10); // Set seconds between re-sync
  setSyncProvider(getNtpTime);
+
  setSyncProvider(getNtpTime);
  getNtpTime;
+
  getNtpTime;
    Serial.print("OK NTP\n");
+
  Serial.print("OK NTP\n");
 
+
  // set the initial time here:
+
  // set the initial time here:
  // DS3231 seconds, minutes, hours, day, date, month, year
+
  // DS3231 seconds, minutes, hours, day, date, month, year
  // setDS3231time(30,33,9, 2 ,28,11,16);
+
  // setDS3231time(30,33,9, 2 ,28,11,16);
}
+
}
 
+
void loop()
+
void loop()
{
+
{
  setSyncProvider(getNtpTime);
+
  setSyncProvider(getNtpTime);
  // set the initial time here:
+
  // set the initial time here:
  // DS3231 seconds, minutes, hours, day, date, month, year
+
  // DS3231 seconds, minutes, hours, day, date, month, year
  setDS3231time(second(), minute(), hour()+7, 5 , 7, 6, 18);
+
  setDS3231time(second(), minute(), hour()+7, 5 , 7, 6, 18);
 
+
 
  displayTime(); // display the real-time clock data on the Serial Monitor,
+
  displayTime(); // display the real-time clock data on the Serial Monitor,
  getNtpTime;
+
  getNtpTime;
  // delay(1000);   
+
  // delay(1000);   
}
+
}
 
+
 
+
/*----------------- DS3231 ----------------------*/
 
+
/*----------------- DS3231 ----------------------*/
+
// Convert normal decimal numbers to binary coded decimal
 
+
byte decToBcd(byte val)
// Convert normal decimal numbers to binary coded decimal
+
{
byte decToBcd(byte val)
+
  return ( (val / 10 * 16) + (val % 10) );
{
+
}
  return ( (val / 10 * 16) + (val % 10) );
+
// Convert binary coded decimal to normal decimal numbers
}
+
byte bcdToDec(byte val)
// Convert binary coded decimal to normal decimal numbers
+
{
byte bcdToDec(byte val)
+
  return ( (val / 16 * 10) + (val % 16) );
{
+
}
  return ( (val / 16 * 10) + (val % 16) );
+
}
+
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
 
+
                    dayOfMonth, byte month, byte year)
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);
  // sets time and date data to DS3231
+
  Wire.write(0); // set next input to start at the seconds register
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
+
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(0); // set next input to start at the seconds register
+
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(second)); // set seconds
+
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(minute)); // set minutes
+
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(hour)); // set hours
+
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
+
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
+
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.write(decToBcd(month)); // set month
+
  Wire.endTransmission();
  Wire.write(decToBcd(year)); // set year (0 to 99)
+
}
  Wire.endTransmission();
+
void readDS3231time(byte *second,
}
+
                    byte *minute,
void readDS3231time(byte *second,
+
                    byte *hour,
                    byte *minute,
+
                    byte *dayOfWeek,
                    byte *hour,
+
                    byte *dayOfMonth,
                    byte *dayOfWeek,
+
                    byte *month,
                    byte *dayOfMonth,
+
                    byte *year)
                    byte *month,
+
{
                    byte *year)
+
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
{
+
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
+
  Wire.endTransmission();
  Wire.write(0); // set DS3231 register pointer to 00h
+
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  Wire.endTransmission();
+
  // request seven bytes of data from DS3231 starting from register 00h
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
+
  *second = bcdToDec(Wire.read() & 0x7f);
  // request seven bytes of data from DS3231 starting from register 00h
+
  *minute = bcdToDec(Wire.read());
  *second = bcdToDec(Wire.read() & 0x7f);
+
  *hour = bcdToDec(Wire.read() & 0x3f);
  *minute = bcdToDec(Wire.read());
+
  *dayOfWeek = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
+
  *dayOfMonth = bcdToDec(Wire.read());
  *dayOfWeek = bcdToDec(Wire.read());
+
  *month = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
+
  *year = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
+
}
  *year = bcdToDec(Wire.read());
+
void displayTime()
}
+
{
void displayTime()
+
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
{
+
  // retrieve data from DS3231
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
+
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  // retrieve data from DS3231
+
                  &year);
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
+
  // send it to the serial monitor
                &year);
+
  Serial.print(hour, DEC);
  // send it to the serial monitor
+
  // convert the byte variable to a decimal number when displayed
  Serial.print(hour, DEC);
+
  Serial.print(":");
  // convert the byte variable to a decimal number when displayed
+
  if (minute < 10)
  Serial.print(":");
+
  {
  if (minute < 10)
+
    Serial.print("0");
  {
+
  }
    Serial.print("0");
+
  Serial.print(minute, DEC);
  }
+
  Serial.print(":");
  Serial.print(minute, DEC);
+
  if (second < 10)
  Serial.print(":");
+
  {
  if (second < 10)
+
    Serial.print("0");
  {
+
  }
    Serial.print("0");
+
  Serial.print(second, DEC);
  }
+
  Serial.print(" ");
  Serial.print(second, DEC);
+
  Serial.print(dayOfMonth, DEC);
  Serial.print(" ");
+
  Serial.print("/");
  Serial.print(dayOfMonth, DEC);
+
  Serial.print(month, DEC);
  Serial.print("/");
+
  Serial.print("/");
  Serial.print(month, DEC);
+
  Serial.print(year, DEC);
  Serial.print("/");
+
  Serial.print(" Day of week: ");
  Serial.print(year, DEC);
+
  switch (dayOfWeek) {
  Serial.print(" Day of week: ");
+
    case 1:
  switch (dayOfWeek) {
+
      Serial.println("Sunday");
    case 1:
+
      break;
      Serial.println("Sunday");
+
    case 2:
      break;
+
      Serial.println("Monday");
    case 2:
+
      break;
      Serial.println("Monday");
+
    case 3:
      break;
+
      Serial.println("Tuesday");
    case 3:
+
      break;
      Serial.println("Tuesday");
+
    case 4:
      break;
+
      Serial.println("Wednesday");
    case 4:
+
      break;
      Serial.println("Wednesday");
+
    case 5:
      break;
+
      Serial.println("Thursday");
    case 5:
+
      break;
      Serial.println("Thursday");
+
    case 6:
      break;
+
      Serial.println("Friday");
    case 6:
+
      break;
      Serial.println("Friday");
+
    case 7:
      break;
+
      Serial.println("Saturday");
    case 7:
+
      break;
      Serial.println("Saturday");
+
  }
      break;
+
}
  }
+
}
+
 
+
/*-------- NTP code ----------*/
 
+
 
+
unsigned long getNtpTime()
 
+
{
/*-------- NTP code ----------*/
+
  sendNTPpacket(timeServer); // send an NTP packet to a time server
 
+
    delay(500);
unsigned long getNtpTime()
+
 
{
+
    if ( Udp.parsePacket() ) {
  sendNTPpacket(timeServer); // send an NTP packet to a time server
+
      Udp.read(packetBuffer,NTP_PACKET_SIZE);
    delay(500);
+
      unsigned long hi = word(packetBuffer[40], packetBuffer[41]);
 
+
      unsigned long low = word(packetBuffer[42], packetBuffer[43]);
    if ( Udp.parsePacket() ) {
+
      unsigned long secsSince1900 = hi << 16 | low;  
    Udp.read(packetBuffer,NTP_PACKET_SIZE);
+
      const unsigned long seventyYears = 2208988800UL;     
    unsigned long hi = word(packetBuffer[40], packetBuffer[41]);
+
      unsigned long epoch = secsSince1900 - seventyYears;
    unsigned long low = word(packetBuffer[42], packetBuffer[43]);
+
      return epoch;
    unsigned long secsSince1900 = hi << 16 | low;  
+
  }
    const unsigned long seventyYears = 2208988800UL;     
+
  return 0; // return 0 if unable to get the time
    unsigned long epoch = secsSince1900 - seventyYears;
+
}  
    return epoch;
+
  }
+
unsigned long sendNTPpacket(IPAddress& address)
  return 0; // return 0 if unable to get the time
+
{
}
+
  memset(packetBuffer, 0, NTP_PACKET_SIZE);  // set all bytes in the buffer to 0
 
+
unsigned long sendNTPpacket(IPAddress& address)
+
  // Initialize values needed to form NTP request
{
+
  packetBuffer[0] = B11100011;  // LI, Version, Mode
  memset(packetBuffer, 0, NTP_PACKET_SIZE);  // set all bytes in the buffer to 0
+
  packetBuffer[1] = 0;    // Stratum
 
+
  packetBuffer[2] = 6;    // Max Interval between messages in seconds
  // Initialize values needed to form NTP request
+
  packetBuffer[3] = 0xEC;  // Clock Precision
  packetBuffer[0] = B11100011;  // LI, Version, Mode
+
  // bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset
  packetBuffer[1] = 0;    // Stratum
+
  packetBuffer[12]  = 49;  // four-byte reference ID identifying
  packetBuffer[2] = 6;    // Max Interval between messages in seconds
+
  packetBuffer[13]  = 0x4E;
  packetBuffer[3] = 0xEC;  // Clock Precision
+
  packetBuffer[14]  = 49;
  // bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset
+
  packetBuffer[15]  = 52;  
  packetBuffer[12]  = 49;  // four-byte reference ID identifying
+
  packetBuffer[13]  = 0x4E;
+
  // send the packet requesting a timestamp:
  packetBuffer[14]  = 49;
+
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  packetBuffer[15]  = 52;
+
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
 
+
  Udp.endPacket();
  // send the packet requesting a timestamp:
+
}
  Udp.beginPacket(address, 123); //NTP requests are to port 123
 
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
 
  Udp.endPacket();
 
}
 

Latest revision as of 07:56, 7 June 2018

Source

#include "Wire.h"
#include <Time.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

#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();
}