Arduino 網絡時鐘client

網絡時鐘1

 

升級!php

添加了12h/24h 的開關,還有標準/ 夏令時開關!見步驟7 & 步驟8。html

你是否曾想要一個和辦公室時間來源全然準確的表?git

這就有一個網絡的辦公時間server,你可以根據它並同步你的時間。網絡

大多數人用電腦來進行設置,現在Arduino也可以相同作到。app

(GPS時間client。詳見 http://arduinotronics.blogspot.com/2014/03/gps-on-lcd.htmloop

你僅僅需要一個Arduino和一個以太網插板,但是咱們也加一個LCD顯示屏。隨後可能還添加鬧鐘功能。post

Arduino UNO
Arduino Ethernet Shieldui

可選:this

串口 LCD 顯示屏 spa

步驟1:鏈接硬件

網絡時鐘2

 

 

首先,記下印在以太網插板頂端的MAC地址。你接下來會用到。

看起來像 90 A2 DA 00 23 36,但是在代碼中插入需要變成 0×90,0xA2,0xDA。0×00,0×23,0×36.

將以太網插板查到Arduino UNO頂部。用一根網線把它連到路由器上。

步驟2:代碼

僅僅需要在Arduino庫目錄下額外安裝一個庫。那就是 Time Library。可找 http://www.pjrc.com/teensy/td_libs_Time.html

你講需要以太網插板頂部的那個MAC地址。但是IP,網關。子網掩碼都可以經過DHCP得到。你還需要時間server地址(見如下步驟)。

需要下載到Arduino上的程序例如如下:

//sample code originated at http://www.openreefs.com/ntpServer
//modified by Steve Spence, http://arduinotronics.blogspot.com

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

/* ******** Ethernet Card Settings ******** */
// Set this to your Ethernet Card Mac Address
byte mac[] = { 0×90, 0xA2, 0xDA, 0×00, 0×23, 0×36 };

/* ******** NTP Server Settings ******** */
/* us.pool.ntp.org NTP server
(Set to your time server of choice) */
IPAddress timeServer(216, 23, 247, 62);

/* Set this to the offset (in seconds) to your local time
This example is GMT – 4 */
const long timeZoneOffset = -14400L;

/* Syncs to NTP server every 15 seconds for testing,
set to 1 hour or more to be reasonable */
unsigned int ntpSyncTime = 3600;

/* ALTER THESE VARIABLES AT YOUR OWN RISK */
// local port to listen for UDP packets
unsigned int localPort = 8888;
// NTP time stamp is in the first 48 bytes of the message
const int NTP_PACKET_SIZE= 48;
// Buffer to hold incoming and outgoing packets
byte packetBuffer[NTP_PACKET_SIZE];
// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
// Keeps track of how long ago we updated the NTP server
unsigned long ntpLastUpdate = 0;
// Check last time clock displayed (Not in Production)
time_t prevDisplay = 0;

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

// Ethernet shield and NTP setup
int i = 0;
int DHCP = 0;
DHCP = Ethernet.begin(mac);
//Try to get dhcp settings 30 times before giving up
while( DHCP == 0 && i < 30){
delay(1000);
DHCP = Ethernet.begin(mac);
i++;
}
if(!DHCP){
Serial.println(「DHCP FAILED」);
for(;;); //Infinite loop because DHCP Failed
}
Serial.println(「DHCP Success」);

//Try to get the date and time
int trys=0;
while(!getTimeAndDate() && trys<10) {
trys++;
}
}

// Do not alter this function, it is used by the system
int getTimeAndDate() {
int flag=0;
Udp.begin(localPort);
sendNTPpacket(timeServer);
delay(1000);
if (Udp.parsePacket()){
Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer
unsigned long highWord, lowWord, epoch;
highWord = word(packetBuffer[40], packetBuffer[41]);
lowWord = word(packetBuffer[42], packetBuffer[43]);
epoch = highWord << 16 | lowWord;
epoch = epoch – 2208988800 + timeZoneOffset;
flag=1;
setTime(epoch);
ntpLastUpdate = now();
}
return flag;
}

// Do not alter this function, it is used by the system
unsigned long sendNTPpacket(IPAddress& address)
{
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011;
packetBuffer[1] = 0;
packetBuffer[2] = 6;
packetBuffer[3] = 0xEC;
packetBuffer[12]  = 49;
packetBuffer[13]  = 0x4E;
packetBuffer[14]  = 49;
packetBuffer[15]  = 52;
Udp.beginPacket(address, 123);
Udp.write(packetBuffer,NTP_PACKET_SIZE);
Udp.endPacket();
}

// Clock display of the time and date (Basic)
void clockDisplay(){
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(」 「);
Serial.print(day());
Serial.print(」 「);
Serial.print(month());
Serial.print(」 「);
Serial.print(year());
Serial.println();
}

// Utility function for clock display: prints preceding colon and leading 0
void printDigits(int digits){
Serial.print(「:」);
if(digits < 10)
Serial.print(’0′);
Serial.print(digits);
}

// This is where all the magic happens…
void loop() {
// Update the time via NTP server as often as the time you set at the top
if(now()-ntpLastUpdate > ntpSyncTime) {
int trys=0;
while(!getTimeAndDate() && trys<10){
trys++;
}
if(trys<10){
Serial.println(「ntp server update success」);
}
else{
Serial.println(「ntp server update failed」);
}
}

// Display the time if it has changed by more than a second.
if( now() != prevDisplay){
prevDisplay = now();
clockDisplay();
}
}

步驟3:時鐘server地址

網絡時鐘4

 

假設你知道一個工做時間serverIP地址,在你的代碼中鍵入它。

/* ******** NTP Server Settings ******** */
/* us.pool.ntp.org NTP server
(Set to your time server of choice) */
IPAddress timeServer(216, 23, 247, 62);

Otherwise, run this sketch to get a valid time server ip. If you really want to get techy, merge the following code into the main sketch so that it finds a valid time server on every update. Don’t forget to update your MAC address below.

/*
DHCP-based IP printer

This sketch uses the DHCP extensions to the Ethernet library
to get an IP address via DHCP and print the address obtained.
using an Arduino Wiznet Ethernet shield.

Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13

created 12 April 2011
by Tom Igoe

*/

#include <SPI.h>
#include <Ethernet.h>
#include <Dns.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0×00, 0xAA, 0xBB, 0xCC, 0xDE, 0×02 };

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

void setup() {
// start the serial library:
Serial.begin(9600);

pinMode(4,OUTPUT);
digitalWrite(4,HIGH);

// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println(「Failed to configure Ethernet using DHCP」);
// no point in carrying on, so do nothing forevermore:
for(;;)
;
}
// print your local IP address:
Serial.print(「My IP address: 「);
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print(「.」);
}
Serial.println();
IPAddress testIP;

DNSClient dns;
dns.begin(Ethernet.dnsServerIP());
dns.getHostByName(「pool.ntp.org」,testIP);
Serial.print(「NTP IP from the pool: 「);
Serial.println(testIP);

}

void loop() {
}

步驟4:時間偏移

網絡時鐘5

 

你需要增長你的時區的時間偏移量。

就像我當前在East Coast DayLight Saving Time,我需要-14400。這是和GMT(世界時)實際那相差的秒數。可參看下錶:

http://www.epochconverter.com/epoch/timezones.php

在代碼中找到這部分:

/* Set this to the offset (in seconds) to your local time
This example is GMT – 4 */
const long timeZoneOffset = -14400L;

步驟5:它能工做了嗎?

網絡時鐘6

 

至此。硬件已鏈接好(UNO和以太網插板),鏈接路由器,把你的MAC地址和時鐘server地址輸入到Arduino中,你應該能看到相似例如如下:

步驟6:加LCD屏

網絡時鐘7

 

假設你正使用串口LCD屏,現在就能連上。

這有一個額外的庫,是I2C(接口)LCD庫。你可以在這找到:

http://arduinotronics.blogspot.com/2014/02/sainsmart-i2c-lcd.html

LCD       Arduino UNO

SCL        A5
SDA       A4
VCC       +5v
GND       Gnd

上述帶有LCD添加項的NTP代碼例如如下:

//sample code originated at http://www.openreefs.com/ntpServer
//modified by Steve Spence, http://arduinotronics.blogspot.com

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <Time.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

//LCD Settings

#define I2C_ADDR    0x3F // <<—– Add your address here.  Find it from I2C Scanner
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

/* ******** Ethernet Card Settings ******** */
// Set this to your Ethernet Card Mac Address
byte mac[] = { 0×90, 0xA2, 0xDA, 0×00, 0×23, 0×36 };

/* ******** NTP Server Settings ******** */
/* us.pool.ntp.org NTP server
(Set to your time server of choice) */
IPAddress timeServer(216, 23, 247, 62);

/* Set this to the offset (in seconds) to your local time
This example is GMT – 4 */
const long timeZoneOffset = -14400L;

/* Syncs to NTP server every 15 seconds for testing,
set to 1 hour or more to be reasonable */
unsigned int ntpSyncTime = 3600;

/* ALTER THESE VARIABLES AT YOUR OWN RISK */
// local port to listen for UDP packets
unsigned int localPort = 8888;
// NTP time stamp is in the first 48 bytes of the message
const int NTP_PACKET_SIZE= 48;
// Buffer to hold incoming and outgoing packets
byte packetBuffer[NTP_PACKET_SIZE];
// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
// Keeps track of how long ago we updated the NTP server
unsigned long ntpLastUpdate = 0;
// Check last time clock displayed (Not in Production)
time_t prevDisplay = 0;

void setup() {
lcd.begin (16,2);

lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);

Serial.begin(9600);

// Ethernet shield and NTP setup
int i = 0;
int DHCP = 0;
DHCP = Ethernet.begin(mac);
//Try to get dhcp settings 30 times before giving up
while( DHCP == 0 && i < 30){
delay(1000);
DHCP = Ethernet.begin(mac);
i++;
}
if(!DHCP){
Serial.println(「DHCP FAILED」);
for(;;); //Infinite loop because DHCP Failed
}
Serial.println(「DHCP Success」);

//Try to get the date and time
int trys=0;
while(!getTimeAndDate() && trys<10) {
trys++;
}
}

// Do not alter this function, it is used by the system
int getTimeAndDate() {
int flag=0;
Udp.begin(localPort);
sendNTPpacket(timeServer);
delay(1000);
if (Udp.parsePacket()){
Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer
unsigned long highWord, lowWord, epoch;
highWord = word(packetBuffer[40], packetBuffer[41]);
lowWord = word(packetBuffer[42], packetBuffer[43]);
epoch = highWord << 16 | lowWord;
epoch = epoch – 2208988800 + timeZoneOffset;
flag=1;
setTime(epoch);
ntpLastUpdate = now();
}
return flag;
}

// Do not alter this function, it is used by the system
unsigned long sendNTPpacket(IPAddress& address)
{
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011;
packetBuffer[1] = 0;
packetBuffer[2] = 6;
packetBuffer[3] = 0xEC;
packetBuffer[12]  = 49;
packetBuffer[13]  = 0x4E;
packetBuffer[14]  = 49;
packetBuffer[15]  = 52;
Udp.beginPacket(address, 123);
Udp.write(packetBuffer,NTP_PACKET_SIZE);
Udp.endPacket();
}

// Clock display of the time and date (Basic)
void clockDisplay(){
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(」 「);
Serial.print(day());
Serial.print(」 「);
Serial.print(month());
Serial.print(」 「);
Serial.print(year());
Serial.println();

lcd.setCursor (0,0);
if (hour() < 10){
lcd.print(「0″); }
if (hour() > 12){
lcd.print(「0″);
lcd.print(hour()-12); } else {
lcd.print(hour()); }
lcd.print(「:」);
if (minute() < 10){
lcd.print(「0″); }
lcd.print(minute());
lcd.print(「:」);
if (second() < 10){
lcd.print(「0″); }
lcd.print(second());
if (hour() > 12){
lcd.print(」 PM」); }
else {
lcd.print(」 AM」); }

lcd.setCursor (0,1);
if (month() < 10){
lcd.print(「0″); }
lcd.print(month());
lcd.print(「/」);
if (day() < 10){
lcd.print(「0″); }
lcd.print(day());
lcd.print(「/」);
lcd.print(year());
}

// Utility function for clock display: prints preceding colon and leading 0
void printDigits(int digits){
Serial.print(「:」);
if(digits < 10)
Serial.print(’0′);
Serial.print(digits);
}

// This is where all the magic happens…
void loop() {
// Update the time via NTP server as often as the time you set at the top
if(now()-ntpLastUpdate > ntpSyncTime) {
int trys=0;
while(!getTimeAndDate() && trys<10){
trys++;
}
if(trys<10){
Serial.println(「ntp server update success」);
}
else{
Serial.println(「ntp server update failed」);
}
}

// Display the time if it has changed by more than a second.
if( now() != prevDisplay){
prevDisplay = now();
clockDisplay();
}
}

步驟7:12h vs. 24h 時間

網絡時鐘8

 

 

 

起初,我用的是24小時的例程。所下面午一點顯示爲13.不少其它人喜歡12h的始終。帶有AM/PM,因此我終於替換了例程。我再三考慮,加了一個可以選擇格式的開關。

首先,咱們需要讀取開關來決定格式,而後咱們需要基於讀到的結果來控制代碼。

開關需要5個引腳。以太網插板自己需要引腳4,10,11,12&13.

將開關鏈接在引腳5和地之間。你不需要上拉點入,因爲咱們將使用INPUT_PULLUP命令在Arduino內部實現。

這是眼下需要改動的代碼:

lcd.setCursor (0,0);
if (hour() < 10){
lcd.print(「0″); }
if (hour() > 12){
lcd.print(「0″);
lcd.print(hour()-12); } else {
lcd.print(hour()); }
lcd.print(「:」);
if (minute() < 10){
lcd.print(「0″); }
lcd.print(minute());
lcd.print(「:」);
if (second() < 10){
lcd.print(「0″); }
lcd.print(second());
if (hour() > 12){
lcd.print(」 PM」); }
else {
lcd.print(」 AM」); }

Here is how the new code with the option of switching back and forth would look like:

//12h_24h (at top of sketch before void setup
int timeFormatPin = 5;   // switch connected to digital pin 5
int timeFormatVal= 0;     // variable to store the read value

//put in void setup replaceing the original code listed above

lcd.setCursor (0,0);
if (hour() < 10){
lcd.print(「0″); }

//12h/24h
pinMode(timeFormatPin, INPUT_PULLUP);      // sets the digital pin 5 as input and activates pull up resistor
timeFormatVal= digitalRead(timeFormatPin);   // read the input pin
if (timeFormatVal == 1) {
lcd.print(hour());
} else {
if (hour() > 12){
lcd.print(「0″);
lcd.print(hour()-12); } else {
lcd.print(hour()); }
}

lcd.print(「:」);
if (minute() < 10){
lcd.print(「0″); }
lcd.print(minute());
lcd.print(「:」);
if (second() < 10){
lcd.print(「0″); }
lcd.print(second());
if (timeFormatVal == 1){
lcd.print(「 24″);
} else {
if (hour() > 12){
lcd.print(」 PM」); }
else {
lcd.print(」 AM」); }
}

升級中我考慮的內容:

  • 本身主動找尋可用時間server功能
  • 本身主動開關夏令時時間(Daylight Saving Time)
  • 鬧鐘功能。帶有漸亮等,或者繼電器。

  • 沒有網絡啓動電源故障的RTC

你想添加什麼呢?

相關文章
相關標籤/搜索