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)