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