Categories
ESP8266 Examples

ESP8266 Web API Based Digital Clock with OLED Display

Today we are going to cover web API based digital clock using esp8266 nodemcu in Arduino. In this post I would mention two kind of codes, first one is to implement a digital clock without the API and second one with API. When we will use the pure native digital clock implemented in ESP8266, it means that we are using the Arduino built in millis() function which will be used to store the time stamp. In that code I used a variable to store the starting time information which will hold the starting time so we can use this as a reference to set the actual time.

NodeMCU digital Clock using Arduino Millis() function

This code would help us to interface the OLED with Arduino and using Arduino built in millis() function we will see how the digital Clock logics works. Later on we can combine the both of the codes to reduce the API calls to webserver so it would reduce the cost of API callings as well as network load. So here are the list of components we required to built the hardware.

  • Node MCU esp8266 based
  • 0.91 inch OLED screen I2C based (in my case the address is 0x3C)
  • Battery
  • lithium battery charger kit

Let’s wire up everything which is pretty straight forward. All you have to do is to connect he 0.91 inch oled screen’s SCL and SDA pins with the ESP8266 NodeMCU respective pins which is D1 and D2 on the NodeMCU board.

Scan i2c address of the OLED screen

First of All you need to findout your OLED Screen’s address which you can reference in your final code to interface the OLED Screen with your NodeMCU esp8266. Here is the code which will detect the i2c device attached with NodeMCU esp8266 and print the address on Serial Terminal.

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(115200);
}
 
void loop() {
  byte Error, address;
  int DeviceCount;
  Serial.println("Scanning I2C devices...");
  DeviceCount = 0;
  for(address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    Error = Wire.endTransmission();
    if (Error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
      DeviceCount++;
    }
    else if (Error==4) {
      Serial.print("Unknown Error at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
    }    
  }
  if (DeviceCount == 0) {
    Serial.println("No I2C devices found!");
  }
  else {
    Serial.println("Success!\n");
  }
  delay(5000);          
}
Code language: PHP (php)

Digital Clock Code

Here is the complete code we used to implement the OLED display based digital clock without the Web API calling and using the pure millis() function without any network load.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Set the starting time in milliseconds (e.g., 10:30:00 AM = 10 hours, 30 minutes, 0 seconds)
unsigned long startingTime = 10 * 3600000 + 30 * 60000;

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

  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }

  display.display();
  delay(2000);
  display.clearDisplay();
}

void loop() {
  display.clearDisplay();
  
 // Get the current time in milliseconds
  unsigned long currentTime = millis() + startingTime; // Add the starting time

  // Convert milliseconds to hours, minutes, and seconds
  int hours = currentTime / 3600000;
  int minutes = (currentTime % 3600000) / 60000;
  int seconds = (currentTime % 60000) / 1000;

  // Display hours and minutes with text size 3
  display.setTextSize(3);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(5, 10); // Adjust the position as needed
  if (hours < 10) {
    display.print("0"); // Add leading zero for single-digit minutes
  }
  display.print(hours);
  display.print(":");
  if (minutes < 10) {
    display.print("0"); // Add leading zero for single-digit minutes
  }
  display.print(minutes);

  // Display seconds with text size 2
  display.setTextSize(2);
  
  display.setCursor(100, 15); // Adjust the position as needed
  if (seconds < 10) {
    display.print("0"); // Add leading zero for single-digit seconds
  }
  display.print(seconds);

  display.display();
}Code language: PHP (php)

NodeMCU ESP8266 Digital Clock with Web API

Here is the complete code which use the Web API to fetch the time. The API returned the time in json format which we decode using the jsondocument library and used one function which will convert the string of datetime into the hour, minute, second format. We pass variables by reference to this function and later display these variables to the 0.91 inch OLED Screen. For the OLED screen we used the Adafruit GFX libraries. Here is the complete code


#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// WiFi credentials
const char* ssid = "EVO-Charji-5BBF";
const char* password = "75JKRjGA";

// Time API endpoint
const char* timeApiUrl = "http://worldtimeapi.org/api/timezone/Asia/Karachi";

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

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }

  display.display();
  delay(2000);
  display.clearDisplay();
}

void loop() {
  display.clearDisplay();

  // Fetch current time from the time API
  String currentTimeStr = getTimeFromApi();
  
  // Parse the JSON response
  const size_t capacity = JSON_OBJECT_SIZE(2) + 100;
  DynamicJsonDocument doc(capacity);
  deserializeJson(doc, currentTimeStr);

  // Extract time values
  String datetime = doc["datetime"];
  String timezone = doc["timezone"];
  Serial.println(datetime);

  // Adjust the time to the Karachi time zone (GMT+5)
  const char* karachiTimeZone = "Asia/Karachi";
  
//    int hours = datetime.substring(11, 13).toInt();
//    int minutes = datetime.substring(14, 16).toInt();
//    int seconds = datetime.substring(17, 19).toInt();


    int hours, minutes, seconds;
parseTime(datetime, hours, minutes, seconds);
Serial.print("Hours: ");
Serial.println(hours);
Serial.print("Minutes: ");
Serial.println(minutes);
Serial.print("Seconds: ");
Serial.println(seconds);




    // Display hours and minutes with text size 3
    display.setTextSize(3);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(5, 10); // Adjust the position as needed
    if (hours < 10) {
      display.print("0"); // Add leading zero for single-digit hours
    }
    display.print(hours);
    display.print(":");
    if (minutes < 10) {
      display.print("0"); // Add leading zero for single-digit minutes
    }
    display.print(minutes);

    // Display seconds with text size 2
    display.setTextSize(2);
    display.setCursor(100, 15); // Adjust the position as needed
    if (seconds < 10) {
      display.print("0"); // Add leading zero for single-digit seconds
    }
    display.print(seconds);
  

  display.display();
  delay(1000); // Update the display every second
}

String getTimeFromApi() {
  WiFiClient client;

  // Make a GET request to the time API
  HTTPClient http;
  http.begin(client, timeApiUrl); // Use begin with WiFiClient
  int httpCode = http.GET();
  if (httpCode > 0) {
    if (httpCode == HTTP_CODE_OK) {
      String payload = http.getString();
      http.end();
      return payload;
    }
  } else {
    Serial.println("Failed to connect to time API");
  }
  http.end();
  return "";
}



void parseTime(const String &timeStr, int &hours, int &minutes, int &seconds) {
  // Find the position of 'T' in the string
  int tIndex = timeStr.indexOf('T');
  
  if (tIndex != -1) {
    // Extract the time substring after 'T'
    String timeSubStr = timeStr.substring(tIndex + 1);
    
    // Find the position of '+' in the time substring
    int plusIndex = timeSubStr.indexOf('+');
    
    if (plusIndex != -1) {
      // Extract the time part before '+'
      String timePart = timeSubStr.substring(0, plusIndex);
      
      // Split the time part into hours, minutes, and seconds
      hours = timePart.substring(0, 2).toInt();
      minutes = timePart.substring(3, 5).toInt();
      seconds = timePart.substring(6, 8).toInt();
    }
  }
}Code language: PHP (php)

By Abdul Rehman

My name is Abdul Rehman and I love to do Reasearch in Embedded Systems, Artificial Intelligence, Computer Vision and Engineering related fields. With 10+ years of experience in Research and Development field in Embedded systems I touched lot of technologies including Web development, and Mobile Application development. Now with the help of Social Presence, I like to share my knowledge and to document everything I learned and still learning.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.