this sketch has auto update from NTP server using Wifi
needed libraries, all attached:
#include "WiFiEsp.h"
#include "WiFiEspUdp.h"
#include <SPI.h>
#include <Time.h>
#include <LiquidCrystal_I2C.h>
#include <DS3231.h>
sketch code:
- Code: Select all
#include "WiFiEsp.h"
#include "WiFiEspUdp.h"
#include <SPI.h>
#include <Time.h>
#include <LiquidCrystal_I2C.h>
#include <DS3231.h>
// Init the DS3231 using the hardware interface
DS3231 clock;
RTCDateTime dt;
#define build 1
#define revision 1
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
const char custom[][8] PROGMEM = { // Custom character definitions
{ 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 }, // char 1
{ 0x18, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 2
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x07, 0x03 }, // char 3
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 4
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1C, 0x18 }, // char 5
{ 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F }, // char 6
{ 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 7
{ 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F } // char 8
};
// BIG FONT Character Set
// - Each character coded as 1-4 byte sets {top_row(0), top_row(1)... bot_row(0), bot_row(0)..."}
// - number of bytes terminated with 0x00; Character is made from [number_of_bytes/2] wide, 2 high
// - codes are: 0x01-0x08 => custom characters, 0x20 => space, 0xFF => black square
const char bigChars[][8] PROGMEM = {
{ 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Space
{ 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // !
{ 0x05, 0x05, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00 }, // "
{ 0x04, 0xFF, 0x04, 0xFF, 0x04, 0x01, 0xFF, 0x01 }, // #
{ 0x08, 0xFF, 0x06, 0x07, 0xFF, 0x05, 0x00, 0x00 }, // $
{ 0x01, 0x20, 0x04, 0x01, 0x04, 0x01, 0x20, 0x04 }, // %
{ 0x08, 0x06, 0x02, 0x20, 0x03, 0x07, 0x02, 0x04 }, // &
{ 0x05, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // '
{ 0x08, 0x01, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00 }, // (
{ 0x01, 0x02, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00 }, // )
{ 0x01, 0x04, 0x04, 0x01, 0x04, 0x01, 0x01, 0x04 }, // *
{ 0x04, 0xFF, 0x04, 0x01, 0xFF, 0x01, 0x00, 0x00 }, // +
{ 0x20, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //
{ 0x04, 0x04, 0x04, 0x20, 0x20, 0x20, 0x00, 0x00 }, // -
{ 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // .
{ 0x20, 0x20, 0x04, 0x01, 0x04, 0x01, 0x20, 0x20 }, // /
{ 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00 }, // 0
{ 0x01, 0x02, 0x20, 0x04, 0xFF, 0x04, 0x00, 0x00 }, // 1
{ 0x06, 0x06, 0x02, 0xFF, 0x07, 0x07, 0x00, 0x00 }, // 2
{ 0x01, 0x06, 0x02, 0x04, 0x07, 0x05, 0x00, 0x00 }, // 3
{ 0x03, 0x04, 0xFF, 0x20, 0x20, 0xFF, 0x00, 0x00 }, // 4
{ 0xFF, 0x06, 0x06, 0x07, 0x07, 0x05, 0x00, 0x00 }, // 5
{ 0x08, 0x06, 0x06, 0x03, 0x07, 0x05, 0x00, 0x00 }, // 6
{ 0x01, 0x01, 0x02, 0x20, 0x08, 0x20, 0x00, 0x00 }, // 7
{ 0x08, 0x06, 0x02, 0x03, 0x07, 0x05, 0x00, 0x00 }, // 8
{ 0x08, 0x06, 0x02, 0x07, 0x07, 0x05, 0x00, 0x00 }, // 9
{ 0xA5, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // :
{ 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ;
{ 0x20, 0x04, 0x01, 0x01, 0x01, 0x04, 0x00, 0x00 }, // <
{ 0x04, 0x04, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00 }, // =
{ 0x01, 0x04, 0x20, 0x04, 0x01, 0x01, 0x00, 0x00 }, // >
{ 0x01, 0x06, 0x02, 0x20, 0x07, 0x20, 0x00, 0x00 }, // ?
{ 0x08, 0x06, 0x02, 0x03, 0x04, 0x04, 0x00, 0x00 }, // @
{ 0x08, 0x06, 0x02, 0xFF, 0x20, 0xFF, 0x00, 0x00 }, // A
{ 0xFF, 0x06, 0x05, 0xFF, 0x07, 0x02, 0x00, 0x00 }, // B
{ 0x08, 0x01, 0x01, 0x03, 0x04, 0x04, 0x00, 0x00 }, // C
{ 0xFF, 0x01, 0x02, 0xFF, 0x04, 0x05, 0x00, 0x00 }, // D
{ 0xFF, 0x06, 0x06, 0xFF, 0x07, 0x07, 0x00, 0x00 }, // E
{ 0xFF, 0x06, 0x06, 0xFF, 0x20, 0x20, 0x00, 0x00 }, // F
{ 0x08, 0x01, 0x01, 0x03, 0x04, 0x02, 0x00, 0x00 }, // G
{ 0xFF, 0x04, 0xFF, 0xFF, 0x20, 0xFF, 0x00, 0x00 }, // H
{ 0x01, 0xFF, 0x01, 0x04, 0xFF, 0x04, 0x00, 0x00 }, // I
{ 0x20, 0x20, 0xFF, 0x04, 0x04, 0x05, 0x00, 0x00 }, // J
{ 0xFF, 0x04, 0x05, 0xFF, 0x20, 0x02, 0x00, 0x00 }, // K
{ 0xFF, 0x20, 0x20, 0xFF, 0x04, 0x04, 0x00, 0x00 }, // L
{ 0x08, 0x03, 0x05, 0x02, 0xFF, 0x20, 0x20, 0xFF }, // M
{ 0xFF, 0x02, 0x20, 0xFF, 0xFF, 0x20, 0x03, 0xFF }, // N
{ 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00 }, // 0
{ 0x08, 0x06, 0x02, 0xFF, 0x20, 0x20, 0x00, 0x00 }, // P
{ 0x08, 0x01, 0x02, 0x20, 0x03, 0x04, 0xFF, 0x04 }, // Q
{ 0xFF, 0x06, 0x02, 0xFF, 0x20, 0x02, 0x00, 0x00 }, // R
{ 0x08, 0x06, 0x06, 0x07, 0x07, 0x05, 0x00, 0x00 }, // S
{ 0x01, 0xFF, 0x01, 0x20, 0xFF, 0x20, 0x00, 0x00 }, // T
{ 0xFF, 0x20, 0xFF, 0x03, 0x04, 0x05, 0x00, 0x00 }, // U
{ 0x03, 0x20, 0x20, 0x05, 0x20, 0x02, 0x08, 0x20 }, // V
{ 0xFF, 0x20, 0x20, 0xFF, 0x03, 0x08, 0x02, 0x05 }, // W
{ 0x03, 0x04, 0x05, 0x08, 0x20, 0x02, 0x00, 0x00 }, // X
{ 0x03, 0x04, 0x05, 0x20, 0xFF, 0x20, 0x00, 0x00 }, // Y
{ 0x01, 0x06, 0x05, 0x08, 0x07, 0x04, 0x00, 0x00 }, // Z
{ 0xFF, 0x01, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00 }, // [
{ 0x01, 0x04, 0x20, 0x20, 0x20, 0x20, 0x01, 0x04 }, // Backslash
{ 0x01, 0xFF, 0x04, 0xFF, 0x00, 0x00, 0x00, 0x00 }, // ]
{ 0x08, 0x02, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00 }, // ^
{ 0x20, 0x20, 0x20, 0x04, 0x04, 0x04, 0x00, 0x00 } // _
};
byte col,row,nb=0,bc=0; // general
byte bb[8]; // byte buffer for reading from PROGMEM
unsigned long unixtime=0;
int status = WL_IDLE_STATUS;
char ssid[] = "ssssssssssss"; // your network SSID (name)
char pass[] = "xxxxxxxxxxxx"; // your network password
int keyIndex = 0; // your network key Index number (needed only for WEP)
unsigned int localPort = 2390; // local port to listen for UDP packets
IPAddress timeServer(92, 86, 106, 228); // time.nist.gov NTP server // romania 92.86.106.228
// A UDP instance to let us send and receive packets over UDP
WiFiEspUDP Udp;
//adafruit rgb lcd shield
#include <Wire.h>
//const int timeZone = 1; // Central European Time
const int timeZone = 2; // Bucharest
//const int timeZone = -4; // Eastern Daylight Time (USA)
//const int timeZone = -8; // Pacific Standard Time (USA)
//const int timeZone = -7; // Pacific Daylight Time (USA)
void setup()
{
clock.begin();
lcd.init();
lcd.clear();
// Print a message to the LCD.
lcd.backlight();
// initialize serial for debugging
Serial.begin(115200);
// initialize serial for ESP module
Serial1.begin(115200);
// initialize ESP module
WiFi.init(&Serial1);
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
lcd.print("WiFi not present");
delay(5000);
lcd.clear();
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
lcd.clear();
lcd.print("WiFi connecting to: ");
lcd.print(ssid);
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
lcd.clear();
lcd.print("Connected to Wifi!");
delay(1000);
printWifiStatus();
Serial.println("\nStarting connection to server...");
Udp.begin(localPort);
Serial.println("waiting for sync");
lcd.clear();
lcd.print("waiting for sync..");
setSyncProvider(getNtpTime);
//lcd.setCursor(1,0);
//lcd.print(unixtime);
Serial.print("NTP unixtime: ");
Serial.println(unixtime);
// Set from UNIX timestamp
// clock.setDateTime(1397408400);
dt = clock.getDateTime();
Serial.print("Device unixtime: ");
Serial.println(clock.unixtime()+86400);
if (clock.unixtime()+86400!=unixtime) {
clock.setDateTime(unixtime);
lcd.clear();
lcd.print("Time auto-updated!");
Serial.println("Time auto-updated!");
}
else Serial.println("Time is right, sync not needed!");
lcd.clear();
for (nb=0; nb<8; nb++ ) { // create 8 custom characters
for (bc=0; bc<8; bc++) bb[bc]= pgm_read_byte( &custom[nb][bc] );
lcd.createChar ( nb+1, bb );
}
lcd.clear();
/* writeBigString("B G F N T", 0, 0);
lcd.setCursor(0, 3);
lcd.print(F(" [B"));
lcd.print(build);
lcd.print(F("."));
lcd.print(revision);
lcd.print(F(" RAM: "));
lcd.print(freeRam());
lcd.print(F("B]"));
delay(5000);
lcd.clear();*/
}
time_t prevDisplay = 0; // when the digital clock was displayed
void loop()
{
/* if (timeStatus() != timeNotSet) {
if (now() != prevDisplay) { //update the display only if time has changed
prevDisplay = now();
digitalClockDisplay();
}
}*/
dt = clock.getDateTime();
lcd.setCursor(0, 0);
lcd.print(clock.dateFormat(" D -- d-M-Y", dt));
//lcd.setCursor(10,0);
//lcd.print("test2");
writeBigString(clock.dateFormat("H:i:s", dt), 0, 2);
}
void digitalClockDisplay(){
// digital clock display of the time
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);
// lcd.print(rtc.getDOWStr());
lcd.setCursor(10,0);
// lcd.print(rtc.getDateStr());
// writeBigString(hour(), 0, 2);
}
void printDigits(int digits){
// utility for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
/*-------- NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
time_t getNtpTime()
{
while (Udp.parsePacket() > 0) ; // discard any previously received packets
Serial.println("Transmit NTP Request");
sendNTPpacket(timeServer);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Serial.println("Receive NTP Response");
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
unixtime = secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
//return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
return unixtime;
}
}
Serial.println("No NTP Response :-(");
return 0; // return 0 if unable to get the time
}
// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
lcd.clear();
lcd.print("SSID: ");
lcd.print(WiFi.SSID());
delay (1000);
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
lcd.clear();
lcd.print("IP Address: ");
lcd.setCursor(1,0);
lcd.print(ip);
delay (1000);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
// ********************************************************************************** //
// SUBROUTINES
// ********************************************************************************** //
// writeBigChar: writes big character 'ch' to column x, row y; returns number of columns used by 'ch'
int writeBigChar(char ch, byte x, byte y) {
if (ch < ' ' || ch > '_') return 0; // If outside table range, do nothing
nb=0; // character byte counter
for (bc=0; bc<8; bc++) {
bb[bc] = pgm_read_byte( &bigChars[ch-' '][bc] ); // read 8 bytes from PROGMEM
if(bb[bc] != 0) nb++;
}
bc=0;
for (row = y; row < y+2; row++) {
for (col = x; col < x+nb/2; col++ ) {
lcd.setCursor(col, row); // move to position
lcd.write(bb[bc++]); // write byte and increment to next
}
// lcd.setCursor(col, row);
// lcd.write(' '); // Write ' ' between letters
}
return nb/2-1; // returns number of columns used by char
}
// writeBigString: writes out each letter of string
void writeBigString(char *str, byte x, byte y) {
char c;
while ((c = *str++))
x += writeBigChar(c, x, y) + 1;
}
// ********************************************************************************** //
// OPERATION ROUTINES
// ********************************************************************************** //
// FREERAM: Returns the number of bytes currently free in RAM
int freeRam(void) {
extern int __bss_end, *__brkval;
int free_memory;
if((int)__brkval == 0) {
free_memory = ((int)&free_memory) - ((int)&__bss_end);
}
else {
free_memory = ((int)&free_memory) - ((int)__brkval);
}
return free_memory;
}