Introduction: Build a Network Clock (NCLK) With Microduino-RTC

About: Microduino: small, smart, stackable Arduino compatible boards https://www.microduino.cc http://wiki.Microduino.cc https://www.facebook.com/Microduino http://www.twitter.com/Microduino

The resolvent of clock synchronization over internet. by PKJ,

The web−based clock management system allows you to monitor clock status from wherever they are and centrally change settings. and this small device is built with PoE technology, thus IP clocks get their time, data and power from the same network that supports your other IP endpoints.

Author: https://www.facebook.com/pan.kejia
Editor: https://www.facebook.com/Microduino

Main features:
- Set automatically by SNTP (Simple Network Time Protocol)
- DHCP or static IP addressable
- Power over Ethernet (IEEE 802.3af) using the same network components as IP telephones
- Time synchronization with PCF8563
- OLED display component

Hardware partlists:
1. Microduino-Core+
2. Microduino-FT232R
3. 【Microduino-ENC28J60】 + 【Microduino-RJ45】
4. Microduino-OLED
5. Microduino-RTC

Please check technical details in http://wiki.Microduino.cc

Step 1: Microduino-RTC

Microduino-RTC is a RTC module in Microduino series.
- the main chip is PCF8563
- use I2C interface
- on-board EEPROM AT24C32 
- open source files [check]


use below codes to drive and test Microduino-RTC module.
necessary library [download]

#include <Wire.h>
#include <Rtc_Pcf8563.h>

//init the real time clock
Rtc_Pcf8563 rtc;

void setup()
{
  Serial.begin(9600);
  //clear out the registers
  rtc.initClock();
  //set a time to start with.
  //day, weekday, month, century(1=1900, 0=2000), year(0-99)
  rtc.setDate(29, 4, 8, 0, 13);
  //hr, min, sec
  rtc.setTime(00, 21, 0);
}

void loop()
{
  //both format functions call the internal getTime() so that the
  //formatted strings are at the current time/date.
  Serial.println("CODE_1:");
  Serial.print(rtc.formatTime());
  Serial.print("     ");
  Serial.print(rtc.formatDate());
  Serial.print("\r\n");

  Serial.println("CODE_2:");
  Serial.print("20");
  Serial.print(rtc.getYear());
  Serial.print("/");
  Serial.print(rtc.getMonth());
  Serial.print("/");
  Serial.print(rtc.getDay());
  Serial.print("     ");
  Serial.print(rtc.getHour());
  Serial.print(":");
  Serial.print(rtc.getMinute());
  Serial.print(":");
  Serial.print(rtc.getSecond());
  Serial.print("\r\n");

  delay(1000);
  Serial.print("\r\n");
}

}

-----
Microduino is open-source hardware, compatible with Arduino System, the most popular ecosystem where designers can get everything to build their own applications.  All opensource codes can be downloaded from http://wiki.Microduino.cc

Currently, Microduino series already had 3 core modules and around 20 extension boards developed, all modules are designed and tested within Microduino community, and around 700 Microduino fans contribute effort to further develop Microduino series.

Step 2: Hardware Partlist

Step 3: Software Part

Software part:
upload program onto your Microdino-Core+ through Microduino-FT232R. 

----------------------------------

#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);        // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//-------font size setting, big|medium|small
#define setFont_L u8g.setFont(u8g_font_7x13)
#define setFont_M u8g.setFont(u8g_font_fixed_v0r)
#define setFont_S u8g.setFont(u8g_font_chikitar)
/*
font:
u8g.setFont(u8g_font_7x13)
u8g.setFont(u8g_font_fixed_v0r);
u8g.setFont(u8g_font_chikitar);
u8g.setFont(u8g_font_osb21);
*/

#include <Wire.h>
#include <Rtc_Pcf8563.h>

Rtc_Pcf8563 rtc;
int time_nian,time_yue,time_ri,time_shi,time_fen,time_miao,time_zhou;

#include <EtherCard.h>

#define SECONDS_IN_DAY          86400
#define START_YEAR              1900
#define TIME_ZONE               +8
static int days_in_month[] = {
  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

static byte mymac[] = {
  0x00,0x1A,0x4B,0x38,0x0C,0x5C};
byte Ethernet::buffer[700];

static byte ntpServer[] = {
  193,204,114,232};
static byte srcPort = 0;

uint32_t timeStamp;

boolean NET_TIME_reply;

#define NET_TIME_INTERVAL    1000
#define TIME_OUT             10000
#define INTERVAL             100000
unsigned long lastTime = 0,TIME_cache = 0;


void setup () {
  Serial.begin(57600);

  volcdsetup("Load NETWORK",0,15);
  delay(1000);
  if (!ether.begin(sizeof Ethernet::buffer, mymac))
    Serial.println( "Failed to access Ethernet controller");
  else
    Serial.println("Ethernet controller initialized");
  if (!ether.dhcpSetup())
  {
    Serial.println("Failed to get configuration from DHCP");
    volcdsetup("DHCP Error",0,15);
    delay(1000);
  }
  else
  {
    Serial.println("DHCP configuration done");
    volcdsetup("DHCP Succeed",0,15);
    delay(1000);
  }
  ether.printIp("IP Address:\t", ether.myip);
  ether.printIp("Netmask:\t", ether.mymask);
  ether.printIp("Gateway:\t", ether.gwip);

  //-------------------------------------------------------
  volcdsetup("Load Net Time",0,15);
  delay(1000);
  NET_TIME_reply = true;
  vonettime();
  if(NET_TIME_reply)
  {
    volcdsetup("Time Sync. Error",0,15);
    delay(1000);
  }
  else
  {
    vosettime();
    volcdsetup("Time Sync. Succeed",0,15);
    delay(1000);
  }

  //-------------------------------------------------------
  Serial.println();
}

void loop() {
  if(millis() - lastTime > INTERVAL)
  {
    NET_TIME_reply = true;
    vonettime();
    if(!NET_TIME_reply)
    {
      vosettime();
    }
    lastTime = millis();
  }

  volcd();

}

void volcd()
{
  u8g.firstPage();
  do {
    setFont_M;
    u8g.setPrintPos(0, 9);
    u8g.print("TIME:");
    u8g.print(rtc.formatDate());

    u8g.setPrintPos(0, 20);
    u8g.print(rtc.formatTime());

    //-----------------------------------------
    u8g.setPrintPos(0, 34);
    u8g.print("TIME:");
    u8g.print("20");
    u8g.print(rtc.getYear());
    u8g.print("/");
    u8g.print(rtc.getMonth());
    u8g.print("/");
    u8g.print(rtc.getDay());

    u8g.setPrintPos(0, 45);
    u8g.print(rtc.getHour());
    u8g.print(":");
    u8g.print(rtc.getMinute());
    u8g.print(":");
    u8g.print(rtc.getSecond());

    String WEEK="";
    switch(rtc.getWeekday())
    {
    case 1:
      WEEK="Monday";
      break;
    case 2:
      WEEK="Tuesday";
      break;
    case 3:
      WEEK="Wednesday";
      break;
    case 4:
      WEEK="Thursday";
      break;
    case 5:
      WEEK="Friday";
      break;
    case 6:
      WEEK="Saturday";
      break;
    case 7:
      WEEK="Sunday";
      break;
    }
    u8g.setPrintPos(60, 45);
    u8g.print(WEEK);

    setFont_S;
    u8g.drawFrame(0, 54,128,10);
    u8g.setPrintPos(3, 62);
    u8g.print("Microduino-RTC v1.0  201307");
  }
  while( u8g.nextPage() );
}

void vosettime()
{
  rtc.initClock();  //set a time to start with.
  rtc.setDate(time_ri, time_zhou, time_yue, 0, time_nian%100);  //day, weekday, month, century(1=1900, 0=2000), year(0-99)
  rtc.setTime(time_shi, time_fen, time_miao); //hr, min, sec

}

void volcdsetup(char* zi,unsigned int x,unsigned int y)
{
  u8g.firstPage();
  do {
    setFont_L;  
    u8g.setPrintPos(x, y);
    u8g.print(zi);
  }
  while( u8g.nextPage() );
}


void vonettime()
{
  uint32_t timeout = millis();    // 
  while(NET_TIME_reply == true && millis() - timeout < TIME_OUT)   // 
  {
    ether.packetLoop(ether.packetReceive());
    if(millis() - TIME_cache > NET_TIME_INTERVAL)     //
    {
      ether.ntpRequest(ntpServer, srcPort);
      TIME_cache = millis();
      NET_TIME_reply = true;   //标记发送
    }

    if(NET_TIME_reply && ether.ntpProcessAnswer(&timeStamp, srcPort))    // 
    {
      printDate(timeStamp + 3600 * TIME_ZONE);    // 
      TIME_cache = millis();
      NET_TIME_reply = false;    // 
    }
  }
}


void printDate(uint32_t timeStamp) {

  unsigned long week = (((timeStamp/3600/24)+1)%7);

  Serial.print("Current date and time:");
  Serial.println(timeStamp);

  unsigned int year = START_YEAR;
  while(1) {
    uint32_t seconds;
    if(isLeapYear(year)) seconds = SECONDS_IN_DAY * 366;
    else seconds = SECONDS_IN_DAY * 365;
    if(timeStamp >= seconds) {
      timeStamp -= seconds;
      year++;
    }
    else break;
  }

  unsigned int month = 0;
  while(1) {  
    uint32_t seconds = SECONDS_IN_DAY * days_in_month[month];
    if(isLeapYear(year) && month == 1) seconds = SECONDS_IN_DAY * 29;
    if(timeStamp >= seconds) {
      timeStamp -= seconds;
      month++;
    }
    else break;
  }
  month++;

  unsigned int day = 1;
  while(1) {
    if(timeStamp >= SECONDS_IN_DAY) {
      timeStamp -= SECONDS_IN_DAY;
      day++;
    }
    else break;
  }

  unsigned int hour = timeStamp / 3600;
  unsigned int minute = (timeStamp - (uint32_t)hour * 3600) / 60;
  unsigned int second = (timeStamp - (uint32_t)hour * 3600) - minute * 60;


  Serial.print("week: ");
  Serial.println(week);

  if(day < 10) Serial.print("0");
  Serial.print(day);
  Serial.print("/");

  if(month < 10) Serial.print("0");
  Serial.print(month);
  Serial.print("/");

  Serial.println(year);


  if(hour < 10) Serial.print("0");
  Serial.print(hour);
  Serial.print(":");

  if(minute < 10) Serial.print("0");
  Serial.print(minute);
  Serial.print(":");

  if(second < 10) Serial.print("0");
  Serial.println(second);

  Serial.println();

  time_nian=year;
  time_yue=month;
  time_ri=day;
  time_shi=hour;
  time_fen=minute;
  time_miao=second;
  time_zhou=week;
}

boolean isLeapYear(unsigned int year) {

  return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}
---------------------------

Microcontroller Contest

Participated in the
Microcontroller Contest

Arduino Contest

Participated in the
Arduino Contest