ESP8266-ESP01 Local Time Internet Clock with OLED SSD1306

8,953 views

Introduction

In this tutorial, we are going to make an “ESP8266-ESP01 Local Time Internet Clock With OLED SSD1306”.

I was looking for a straightforward clock to use with a 128×64 OLED I got from Adafruit but found that a lot of the implementations were too cumbersome, involved a ton of code, weren’t clear on what NTP servers to use and how, and basically offered very little in terms of making a clock with the LOCAL time (not UTC, which is easy enough to get). So I set about doing my own research and ended up with this simple clock that leverages already-made libraries to minimize the code footprint while offering some interesting tweaks in displaying the time (like AM/PM, 12-hour format, names for months, days, etc). We assume you have ESP-01 programming experience so Let’s Get Started!

This Project is sponsored by PCBWay. They have an open-source community, people can share their design projects with each other. Moreover, every time people place an order for your board, PCBWay will donate 10% of the cost of PCB to you, for your contribution to the Open Source Community.

Hardware Component

The following components are required to make the ESP01 Internet Clock Circuit

S.noComponentValueQty
1.WiFi ModuleESP011
2.OLED DisplaySSD13061
3.Connecting Wires
4.Power Supply 3.3V1
5.Push Button1
6.Resistor10K1

ESP01 Internet Clock Circuit

ESP8266-Internet-Clock-OLED-circuit-diagram-schematic

Program the ESP-01

This step can be frustrating if you haven’t done it before, but once you get the hang of how the ESP boards work and have the correct drivers and libraries installed in Arduino, you can go ahead and use the following code. But first, you will need to download and install the following libraries:

You may need to modify some of the code according to what OLED you’re using (as long as it’s SSD1306 it’ll work but you may need to update the hex I2C address) and then you may have to change some of the Timezone rules depending on your timezone and daylight savings time rules. Then upload the code attached and you should be done!

Once you have programmed the ESP, plugged everything in, make sure you have 3.3V going into the setup, and then power it on and see your correct time on the tiny display!

Code for ESP01

// 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 = "TP-LINK_CD2ED6";   // insert your own ssid 
const char* password = "20244064";              // 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 += " ";
    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(10000);    //Send a request to update every 10 sec (= 10,000 ms)
}