[Solved] RTC NTP update problem

Hi,

I have a RTC in my project and I am trying to update it via NTP. It updates fine but it stops providing data to my program once I perform the update. Has anyone ever experienced anything like this? Code is as follows. It is a simple temperature sensor that also serves up a web page.

// Import needed libraries
#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
#include <DHT.h>
#include <RTClib.h>
#include <Time.h>
#include <LiquidCrystal_I2C.h>
#include <EthernetUdp.h>

// Set the MAC address for the network shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

unsigned int localPort = 8888;      // local port to listen for UDP packets

byte timeServer[] = {128, 101, 101, 101}; //ns.nts.umn.edu

const int NTP_PACKET_SIZE = 48; // NTP Time stamp is in the first 48 bytes of the message
byte pb[NTP_PACKET_SIZE]; // Buffer to hold incoming & outgoing packets

EthernetUDP udp;

// Set the pins used for the LCD
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

// Instantiate our EthernetServer
EthernetServer server(80);

// Instantiate our global variables
RTC_DS1307 rtc;
float humidity = 0.0;
float temperature = 0.0;

// Define our constants
#define DHTTYPE DHT22
#define DHTPIN 14

// Instantiate DHT
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  // Startup serial communications
  Serial.begin(9600);
 
  // Startup the LCD
  lcd.begin(20,4);
 
  // Startup the Ethernet
  Ethernet.begin(mac);

  // Startup the server
  server.begin();

  // Startup the DHT sensor
  dht.begin();
  
  Wire.begin();
  rtc.begin();
  humidity = dht.readHumidity();
  temperature = dht.readTemperature(true);
  //adjust the date & time to the compile date & time
  //rtc.adjust(DateTime(__DATE__, __TIME__));
}

void loop()
{
  // Print the server information to the serial port
  Serial.print("Server is at ");
  Serial.println(Ethernet.localIP());
  DateTime now = rtc.now();
  Serial.println(GetDateTime(now));

  if (now.unixtime() % 10 == 0)
  {
    humidity = dht.readHumidity();
    temperature = dht.readTemperature(true);
  }
  
  if (now.unixtime() % 3600 == 0)
  {
    sendNTPpacket(timeServer);
    delay (1000);
    if (udp.available())
    {
      udp.read(pb, NTP_PACKET_SIZE);
      // NTP contains four timestamps with an integer part and a fraction part
      // we only use the integer part here
      unsigned long t1, t2, t3, t4;
      t1 = t2 = t3 = t4 = 0;
      for (int i=0; i< 4; i++)
      {
        t1 = t1 << 8 | pb[16+i];      
        t2 = t2 << 8 | pb[24+i];      
        t3 = t3 << 8 | pb[32+i];      
        t4 = t4 << 8 | pb[40+i];
      }
      // part of the fractional part
      // could be 4 bytes but this is more precise than the 1307 RTC 
      // which has a precision of ONE second
      // in fact one byte is sufficient for 1307 
      float f1,f2,f3,f4;
      f1 = ((long)pb[20] * 256 + pb[21]) / 65536.0;      
      f2 = ((long)pb[28] * 256 + pb[29]) / 65536.0;      
      f3 = ((long)pb[36] * 256 + pb[37]) / 65536.0;      
      f4 = ((long)pb[44] * 256 + pb[45]) / 65536.0;
      // NOTE:
      // one could use the fractional part to set the RTC more precise
      // 1) at the right (calculated) moment to the NEXT second! 
      //    t4++;
      //    delay(1000 - f4*1000);
      //    RTC.adjust(DateTime(t4));
      //    keep in mind that the time in the packet was the time at
      //    the NTP server at sending time so one should take into account
      //    the network latency (try ping!) and the processing of the data
      //    ==> delay (850 - f4*1000);
      // 2) simply use it to round up the second
      //    f > 0.5 => add 1 to the second before adjusting the RTC
      //   (or lower threshold eg 0.4 if one keeps network latency etc in mind)
      // 3) a SW RTC might be more precise, => ardomic clock :)

      // convert NTP to UNIX time, differs seventy years = 2208988800 seconds
      // NTP starts Jan 1, 1900
      // Unix time starts on Jan 1 1970.
      const unsigned long seventyYears = 2208988800UL;
      t1 -= seventyYears;
      t2 -= seventyYears;
      t3 -= seventyYears;
      t4 -= seventyYears;
      // Adjust timezone and DST... in my case substract 4 hours for Chile Time
      // or work in UTC?
      if (IsDST(now.day(), now.month(), now.dayOfWeek()))
        t4 -= (-5 * 3600L);
      else
        t4 -= (-6 * 3600L);     // Notice the L for long calculations!!
      t4 += 1;               // adjust the delay(1000) at begin of loop!
      if (f4 > 0.4) t4++;    // adjust fractional part, see above
      rtc.adjust(DateTime(t4));
      rtc.begin();
    }
  }
  
  String IP = "";
  for (byte thisByte = 0; thisByte < 4; thisByte++)
  {
    IP += String(Ethernet.localIP()[thisByte], DEC);
    if (thisByte < 3) IP += '.';
  }
  UpdateLCD(IP, temperature, humidity, now);

  // Instante a new client
  EthernetClient client = server.available();
  // If the client has connected start sending it info
  if (client)
  {
    // Write out that a new client has connected via serial
    Serial.println("New client connected");
    boolean currentLineIsBlank = true;
    // Loop while a client is connected
    while (client.connected())
    {
      // Only continue if a client is available
      if (client.available())
      {
        // Read a character
        char c = client.read();
        // Write the character out via Serial
        Serial.write(c);
        // If the character is a new line & the current line is blank, continue
        if (c == '\n' && currentLineIsBlank)
        {
          // Write a HTTP response
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          client.println("Refresh: 5");
          client.println();
          // Start writing the HTML page
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // Write information from the sensor if it is good
          client.print("Humidity: ");
          client.print(humidity, 2);
          client.print("%\n
\nTemperature: ");
          client.print(temperature, 2);
          client.print("F\n
");
          // Write the current time
          client.print("\nTime: ");
          client.print(GetDateTime(now));
          // Close the HTML page
          client.print("\n</html>");
          // Break out
          break;
        }
        if (c == '\n')
        {
          currentLineIsBlank = true;
        }
        else if (c != '\r')
        {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
    Serial.println("client disonnected");
  }
  // Wait ~1 seconds before looping
  delay(1000);
}

String GetDateTime(DateTime now)
{
  String retVal = "";
  if (now.month() < 10) retVal += '0';
  retVal += String(now.month()) + '/';
  if (now.day() < 10) retVal += '0';
  retVal += String(now.day()) + '/';
  retVal += String(now.year()) + ' ';
  if (now.hour() < 10) retVal +='0';
  retVal += String(now.hour()) + ':';
  if (now.minute() < 10) retVal +='0';
  retVal += String(now.minute()) + ':';
  if (now.second() < 10) retVal +='0';
  retVal +=String(now.second());
  return retVal;
}

void UpdateLCD(String IP, float temp, float humidity, DateTime now)
{
  lcd.setCursor(0, 0);
  lcd.print(IP);
  lcd.setCursor(0, 1);
  lcd.print(temp, 2);
  lcd.print('F');
  lcd.setCursor(0, 2);
  lcd.print(humidity, 2);
  lcd.print('%');
  lcd.setCursor(0,3);
  lcd.print(GetDateTime(now));
}

// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(byte *address)
{
  // set all bytes in the buffer to 0
  memset(pb, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  pb[0] = 0b11100011;   // LI, Version, Mode
  pb[1] = 0;     // Stratum, or type of clock
  pb[2] = 6;     // Polling Interval
  pb[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  pb[12]  = 49; 
  pb[13]  = 0x4E;
  pb[14]  = 49;
  pb[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp: 
  // IDE 1.0 compatible:
  udp.beginPacket(address, 123); //NTP requests are to port 123
  udp.write(pb,NTP_PACKET_SIZE);
  udp.endPacket();
}

bool IsDST(int dayVal, int monthVal, int dow)
{
  //January, february, and december are out.
  if (monthVal < 3 || monthVal > 11) { return false; }
  //April to October are in
  if (monthVal > 3 && monthVal < 11) { return true; }
  int previousSunday = dayVal - dow;
  //In march, we are DST if our previous sunday was on or after the 8th.
  if (monthVal == 3) { return previousSunday >= 8; }
  //In november we must be before the first sunday to be dst.
  //That means the previous sunday must be before the 1st.
  return previousSunday <= 0;
}

t updates fine but it stops providing data to my program once I perform the update.

What does that mean? Does it stop acting as a HTTP server? Does it freeze? Show the serial output till the point it stops.

Also provide a link to the RTC library you used because there are dozends of them and maybe your's has a problem with calling the begin() method repeatedly. Usually it's expected to be called just once in the setup routine.

Sorry. Everything responds correctly but the time update. the second rtc.begin() was not in the code, I added that to try to solve it. I'm using this RTC Library.
http://jeelabs.org/2010/02/05/new-date-time-rtc-library/

I still don't understand where exactly the problem is. And I ask again for the complete serial output until where you have the problem.

Sorry it took me so long to get this to you, real life got in the way. Anyway, it is completely locking up when I send the NTP request out.

Serial output

Server is at 172.16.6.108
03/11/2014 16:19:21
1
Server is at 172.16.6.108
03/11/2014 16:19:22
2
Server is at 172.16.6.108
03/11/2014 16:19:23
3
Server is at 172.16.6.108
03/11/2014 16:19:24
4
Server is at 172.16.6.108
03/11/2014 16:19:25
5
Server is at 172.16.6.108
03/11/2014 16:19:26
6
Server is at 172.16.6.108
03/11/2014 16:19:27
7
Server is at 172.16.6.108
03/11/2014 16:19:28
8
Server is at 172.16.6.108
03/11/2014 16:19:29
9
Server is at 172.16.6.108
03/11/2014 16:19:30
0

And looking at the NTP example, I found the problem. I was missing udp.begin(localPort); before I tried to use the EthernetUdp object I was instantiating. Working great now and should continue to keep decent time for a while.