ESP8266 OLED Clock
revised d. bodnar  6-28-2017

The ESP8266 has the ability to connect to the Internet wirelessly.  One of these connections can be to an Internet time server where accurate time information can be used to synchronize a clock.

This project is designed to create a simple clock that displays the time on a small OLED screen.  It connects to the Internet to set the time.

The core of the software is based on two sources.  One that gets the time information and the other that sets up the OLED display.

 
Arduino Code
Clock-8266-12-V2-H-M-S-via-serialOnly-plus-OLED-v2-0-WORKS
D:\shared_stuff\Dropbox\Arduino\ESP8266\Clock-OLED-experiment\Clock-8266-12-V2-H-M-S-via-serialOnly-plus-OLED-v2-0-WORKS
//NOTE:  some reminants from the original clock program remain  
 
// An experiment using the ESP-8266 to lock onto time server and display it on an OLED

//  Using board from BangGood as ESP-12E module
// 6-28-2017 working

// TO GET OLED WORKING I NEEDED TO MAKE CHANGES SHOWN HERE
//  https://github.com/structure7/fridgeTemps
// OLED_RESET=0, etc and it works
// ON OLED/ESP12 pin D1 to SCL  and pin D2 to SDA


//************* Wol Clock by Jon Fuge ******************************
//  http://www.instructables.com/id/Wol-Clock-ESP8266-12E-60-LED-WS2812B-Analogue-Digi/?ALLSTEPS
//************* Declare included libraries ******************************
#include <NTPClient.h>
#include <Time.h>
#include <TimeLib.h>
#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SSD1306_128_64
#define OLED_RESET 0
Adafruit_SSD1306 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

//Set your timezone in hours difference rom GMT
const int hours_Offset_From_GMT = -5;

//Set your wifi details so the board can connect and get the time from the internet
const char *ssid      = "XXXX";    //  your network SSID (name)
const char *password  = "PASSWORD"; // your network password

byte SetClock;

// By default 'time.nist.gov' is used.
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

// Which pin on the ESP8266 is connected to the NeoPixels?
#define PIN            14 // This is the D5 pin

//************* Declare user functions ******************************
void Draw_Clock(time_t t, byte Phase);
int ClockCorrect(int Pixel);
void SetBrightness(time_t t);
void SetClockFromNTP ();
bool IsDst();

//************* Declare NeoPixel ******************************
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

//************* Setup function for Wol_Clock ******************************

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif


void setup() {
  Serial.begin(115200);
  Serial.println("Test of clock!!!!!");
  Serial.println("Test of clock!!!!!");
  Serial.println("Test of clock!!!!!");

  WiFi.begin(ssid, password); // Try to connect to WiFi

  while ( WiFi.status() != WL_CONNECTED )
    delay ( 500 ); // keep waiging until we successfully connect to the WiFi

  SetClockFromNTP(); // get the time from the NTP server with timezone correction

  Wire.begin(4, 5);
  Serial.begin(9600);

  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(12, 9);  // over (X) then down (Y)
  display.println("Syncing V2");
  display.display();
}

void SetClockFromNTP ()
{
  timeClient.update(); // get the time from the NTP server
  setTime(timeClient.getEpochTime()); // Set the system yime from the clock
  if (IsDst())
    adjustTime((hours_Offset_From_GMT + 1) * 3600); // offset the system time with the user defined timezone (3600 seconds in an hour)
  else
    adjustTime(hours_Offset_From_GMT * 3600); // offset the system time with the user defined timezone (3600 seconds in an hour)
}

bool IsDst()
{
  if (month() < 3 || month() > 10)  return false;
  if (month() > 3 && month() < 10)  return true;
  int previousSunday = day() - weekday();
  if (month() == 3) return previousSunday >= 24;
  if (month() == 10) return previousSunday < 24;

  return false; // this line never gonna happend
}

//************* Main program loop for Wol_Clock ******************************
void loop() {

  time_t t = now(); // Get the current time
  SetBrightness(t);
  if (minute(t) == 0) // at the start of each hour, update the time from the time server
    if (SetClock == 1)
    {
      SetClockFromNTP(); // get the time from the NTP server with timezone correction
      SetClock = 0;
    }
    else
    {
      delay(200); // Just wait for 0.1 seconds
      SetClock = 1;
    }
}



//************* Function to set the clock brightness ******************************
void SetBrightness(time_t t)
{
  int NowHour = hour(t);
  int NowMinute = minute(t);
  int NowSecond = second(t);
  Serial.print("Hour = ");
  Serial.print(NowHour);
  Serial.print(" Minute= "); Serial.print(NowMinute);
  Serial.print(" Second= "); Serial.println(NowSecond);

  display.clearDisplay();

  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(12, 9);  // over (X) then down (Y)
  display.print(NowHour);
  display.print(":");
  if (NowMinute <= 9) {
    display.print("0");  // pad #s < 10 with leading zero
  }
  display.print(NowMinute);
  display.print(":");
  if (NowSecond <= 9) {  // pad #s < 10 with leading zero
    display.print("0");
  }
  display.print(NowSecond);

  display.display();
  delay(1000);
}

 

 

A Better Program
After working on the program above I found a better program that includes the day and date - I changed it a bit to show seconds and only P or A for PM / AM.
The pins used also changed-  D3--SDA  and D4 --SCL
If was found here:  http://www.instructables.com/id/Simplest-ESP8266-Local-Time-Internet-Clock-With-OL/
D:\shared_stuff\Dropbox\Arduino\ESP8266\Clock-OLED-experiment\simplestesp8266clock-w-seconds
// simplestesp8266clock.ino
//
// Libraries needed:
//  Time.h & TimeLib.h:  https://github.com/PaulStoffregen/Time
//  Timezone.h: https://github.com/JChristensen/Timezone
//  SSD1306.h & SSD1306Wire.h:  https://github.com/squix78/esp8266-oled-ssd1306
//  NTPClient.h: https://github.com/arduino-libraries/NTPClient
//  ESP8266WiFi.h & WifiUDP.h: https://github.com/ekstrand/ESP8266wifi
//
// 128x64 OLED pinout:
// GND goes to ground
// Vin goes to 3.3V
// Data to I2C SDA (GPIO 0)
// Clk to I2C SCL (GPIO 2)

#include <ESP8266WiFi.h>
#include <WifiUDP.h>
#include <String.h>
#include <Wire.h>
#include <SSD1306.h>
#include <SSD1306Wire.h>
#include <NTPClient.h>
#include <Time.h>
#include <TimeLib.h>
#include <Timezone.h>

// Define NTP properties
#define NTP_OFFSET   60 * 60      // In seconds
#define NTP_INTERVAL 60 * 1000    // In miliseconds
#define NTP_ADDRESS  "ca.pool.ntp.org"  // change this to whatever pool is closest (see ntp.org)

// Set up the NTP UDP client
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_ADDRESS, NTP_OFFSET, NTP_INTERVAL);

// Create a display object
SSD1306  display(0x3c, 0, 2); //0x3d for the Adafruit 1.3" OLED, 0x3C being the usual address of the OLED
 
const char* ssid = "main2";   // insert your own ssid 
const char* password = "Chumley8";              // and password
String date;
String t;
const char * days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} ;
const char * months[] = {"Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"} ;
const char * ampm[] = {"AM", "PM"} ;
 
void setup () 
{
  Serial.begin(115200); // most ESP-01's use 115200 but this could vary
  timeClient.begin();   // Start the NTP UDP client

  Wire.pins(0, 2);  // Start the OLED with GPIO 0 and 2 on ESP-01
  Wire.begin(0, 2); // 0=sda, 2=scl
  display.init();
  display.flipScreenVertically();   

  // Connect to wifi
  Serial.println("");
  Serial.print("Connecting to ");
  Serial.print(ssid);
  display.drawString(0, 10, "Connecting to Wifi...");
  display.display();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi at ");
  Serial.print(WiFi.localIP());
  Serial.println("");
  display.drawString(0, 24, "Connected.");
  display.display();
  delay(1000);
}

void loop() 
{
  if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
  {   
    date = "";  // clear the variables
    t = "";
    
    // update the NTP client and get the UNIX UTC timestamp 
    timeClient.update();
    unsigned long epochTime =  timeClient.getEpochTime();

    // convert received time stamp to time_t object
    time_t local, utc;
    utc = epochTime;

    // Then convert the UTC UNIX timestamp to local time
    TimeChangeRule usEDT = {"EDT", Second, Sun, Mar, 2, -300};  //UTC - 5 hours - change this as needed
    TimeChangeRule usEST = {"EST", First, Sun, Nov, 2, -360};   //UTC - 6 hours - change this as needed
    Timezone usEastern(usEDT, usEST);
    local = usEastern.toLocal(utc);

    // now format the Time variables into strings with proper names for month, day etc
    date += days[weekday(local)-1];
    date += ", ";
    date += months[month(local)-1];
    date += " ";
    date += day(local);
    date += ", ";
    date += year(local);

    // format the time to 12-hour format with AM/PM and no seconds
    t += hourFormat12(local);
    t += ":";
    if(minute(local) < 10)  // add a zero if minute is under 10
      t += "0";
    t += minute(local);
    t += ":";
    if(second(local) < 10)  // add a zero if minute is under 10
      t += "0";
    t+= second(local);
    t += ampm[isPM(local)];

    // Display the date and time
    Serial.println("");
    Serial.print("Local date: ");
    Serial.print(date);
    Serial.println("");
    Serial.print("Local time: ");
    Serial.print(t);

    // print the date and time on the OLED
    display.clear();
    display.setTextAlignment(TEXT_ALIGN_CENTER);
    display.setFont(ArialMT_Plain_24);
    display.drawStringMaxWidth(64, 10, 128, t);
    display.setFont(ArialMT_Plain_10);
    display.drawStringMaxWidth(64, 38, 128, date);
    display.display();
  }
  else // attempt to connect to wifi again if disconnected
  {
    display.clear();
    display.drawString(0, 10, "Connecting to Wifi...");
    display.display();
    WiFi.begin(ssid, password);
    display.drawString(0, 24, "Connected.");
    display.display();
    delay(1000);
  }
    
  delay(1000);    //Send a request to update every 10 sec (= 10,000 ms)
}