NTP Clock Using OLED Display

/**/

NTP Clock Using OLED Display

In this project, I am going to demonstrate how you can display clock and temperature on OLED display with the help of the idIoTware shield.

Things used in this project

Hardware components

  • Arduino UNO x 1
  • Idiotware Shield x 1
  • USB-A to B Cable x 1
  • Generic Jumper (0.1″) x 2
  • Espressif ESP8266 ESP-01 x 1
  • 0.96″ I2C OLED display x 1
  • 9V 1A Switching Wall Power Supply x 1

Software apps and online services

  • Arduino IDE
  • Heroku

Story

Working

In this example, we are going to display the time, date and temperature readings on OLED display. We need to setup the timezone first. By using herokuapp.com, we are able to get the current zone of WiFi module. Once we get the timezone, we need to call timeapi.org to get the current time and date. Once we get the data, we are ready to display it on OLED display.

Temp:

We are using the LM35 temperature sensor to monitor the temperature. The idIoTware shield has a built in, on board lm35 sensor; we will post the data over the ThingSpeak website.

  • The sensor has a sensitivity of 10mV/oC.
  • We use a reciprocal conversion factor, that is 100 oC/V.
  • The output voltage varies linearly with temperature.
  • The general equation used to convert output analog voltage (Vout) to temperature is: Temperature (oC) = Vout * (100 oC/V)
  • So if Vout is 0.5V, then Temperature = 50oC

However, on the idIoTware shield, the LM35, temperature sensor is wired such that with a higher temperature we get a higher Analog Voltage on PIn A0.

Esp8266-01 Configuration

You will need to upload esp link firmware to ESP8266-01 module to configure WiFi SSID and password. Visit this link for more information.

Configuring idIoTware Shield

Upload the code and you will be able to see the clock on the display with the current time, date and temperature readings.

With no prior experience in software and hardware, you were able to make your own clock. Go ahead and inspire others to make clock. With the idIoTware shield the sky’s the limit.

Schematics

Code

// Add libraries
#include <ELClient.h>
#include <ELClientRest.h>
#include "U8glib.h"
#include <SPI.h>
#include <Wire.h>
#define BUFLEN 64  
// setup u8g object
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);	// I2C 
//

String monthArray[]= {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
//int  monthIndex[122] ={0,3,6,9,12,15,18,21,24,27,30,33};
String thisMonth = "";
String thisTime = "";
String thisDay="";
String AMorPM = "";
int clockCentreX = 32; // used to fix the centre the analog clock
int clockCentreY = 32; // used to fix the centre the analog clock
int tempPin = A0; 
int date, hours,minutes,seconds;
int hourOffset;
int minuteOffset;

// Initialize a connection to esp-link using the normal hardware serial port both for
// SLIP and for debug messages.
ELClient esp(&Serial, &Serial);

// Initialize a REST client on the connection to esp-link
ELClientRest rest(&esp);

boolean wifiConnected = false;

// Callback made from esp-link to notify of wifi status changes
// Here we print something out and set a global flag
void wifiCb(void *response) 
    {
      ELClientResponse *res = (ELClientResponse*)response;
      if (res->argc() == 1) 
         {
           uint8_t status;
           res->popArg(&status, 1);

           if(status == STATION_GOT_IP) 
             {
               Serial.println("WIFI CONNECTED");
               wifiConnected = true;
             } 
           else 
             {
               Serial.print("WIFI NOT READY: ");
               Serial.println(status);
               wifiConnected = false;
             }
         }
    }

void draw(void)
    {
      // graphic commands to redraw the complete screen should be placed here  
      //u8g.setFont(u8g_font_profont15);
      u8g.setFont(u8g_font_timB14); 
    
      // display time in digital format
      thisTime="";
      thisTime=String(hours) + ":";
      if (minutes < 10)
         { 
           thisTime=thisTime + "0"; // add leading zero if required
         } 
      thisTime=thisTime + String(minutes) +  AMorPM ;
    
      const char* newTime = (const char*) thisTime.c_str();
      u8g.drawStr(65,15, newTime); 
     
      //dispaly date
      String newDate = thisDay + thisMonth;
      const char* today = (const char*) newDate.c_str();
      u8g.drawStr(70,35, today);
     // const char* amORpm = (const char*)AMorPM.c_str();
     //  u8g.drawStr(100,35, amORpm);
      // Now draw the clock face
      u8g.drawCircle(clockCentreX, clockCentreY, 30); // main outer circle
      u8g.drawCircle(clockCentreX, clockCentreY, 31);
      u8g.drawCircle(clockCentreX, clockCentreY, 2);  // small inner circle
      u8g.drawCircle(clockCentreX, clockCentreY, 1);
  
     //hour ticks
     for( int z=0; z < 360;z= z + 30 )
        {
          //Begin at 0° and stop at 360°
          float angle = z ;
          angle=(angle/57.29577951) ; //Convert degrees to radians
          int x2=(clockCentreX+(sin(angle)*26));
          int y2=(clockCentreY-(cos(angle)*26));
          int x3=(clockCentreX+(sin(angle)*(26-5)));
          int y3=(clockCentreY-(cos(angle)*(26-5)));
          u8g.drawLine(x2,y2,x3,y3);
        }
     // display second hand
     float angle = seconds*6 ;
     angle=(angle/57.29577951) ; //Convert degrees to radians  
     int x3=(clockCentreX+(sin(angle)*(22)));
     int y3=(clockCentreY-(cos(angle)*(22)));
     u8g.drawLine(clockCentreX,clockCentreY,x3,y3);
  
     // display minute hand
     angle = minutes * 6 ;
     angle=(angle/57.29577951) ; //Convert degrees to radians  
     x3=(clockCentreX+(sin(angle)*(22-4)));
     y3=(clockCentreY-(cos(angle)*(22-4)));
     u8g.drawLine(clockCentreX,clockCentreY,x3,y3);
  
     // display hour hand
     angle = hours * 30; // + int((initialMinutes / 12) * 6 )   ;
     angle=(angle/57.29577951) ; //Convert degrees to radians  
     x3=(clockCentreX+(sin(angle)*(22-9)));
     y3=(clockCentreY-(cos(angle)*(22-9)));
     u8g.drawLine(clockCentreX,clockCentreY,x3,y3);

     int reading1 = analogRead(tempPin); //delay(10);
     int reading4 = analogRead(tempPin); //delay(10);
     int tempInCelcius = round(( 5.0 * reading4 * 100.0) / 1024.0);    
     String thisTemp1 = String(tempInCelcius) + String(char(176)) +"C";
     const char* thisTemp = (const char*) thisTemp1.c_str();
     u8g.drawStr(70,62,thisTemp); 
   
   }

void setup(void)
    {
      Serial.begin(9600);   // the baud rate here needs to match the esp-link config
      Serial.println("EL-Client starting!");
      // Sync-up with esp-link, this is required at the start of any sketch and initializes the
      // callbacks to the wifi status change callback. The callback gets called with the initial
      // status right after Sync() below completes.
      esp.wifiCb.attach(wifiCb); // wifi status change callback, optional (delete if not desired)
      bool ok;
      do 
        {
          ok = esp.Sync();      // sync up with esp-link, blocks for up to 2 seconds
           if (!ok) Serial.println("EL-Client sync failed!");
        } while(!ok);
      Serial.println("EL-Client synced!");

      // Get immediate wifi status info for demo purposes. This is not normally used because the
      // wifi status callback registered above gets called immediately. 
      esp.GetWifiStatus();
      ELClientPacket *packet;
      if ((packet=esp.WaitReturn()) != NULL) 
         {
           Serial.print("Wifi status: ");
           Serial.println(packet->value);
         }

      getTimeZone();
  
    }



void loop(void) 
    { 
      getTime();
      // picture loop
      u8g.firstPage();  
      do 
        {
          draw();
        } while( u8g.nextPage() );
    }

void getTimeZone()
    {
      //idiotware.herokuapp.com/getTimeZoneOffset?appid=AIzaSyARAKu23k_1vltEKesq6REtMSIflQ3c3jo
      
       // Set up the REST client to talk to www.timeapi.org, this doesn't connect to that server,
      // it just sets-up stuff on the esp-link side
      int err = rest.begin("idiotware.herokuapp.com");
      if (err != 0)
         {
           Serial.print("REST begin failed: ");
           Serial.println(err);
           while(1) ;
         }
      Serial.println("EL-REST ready");
       // process any callbacks coming from esp_link
      esp.Process();

      // if we're connected make an HTTP request
      if(wifiConnected)
        {
          // Request /utc/now from the previously set-up server
          rest.get("/getTimeZoneOffset?appid=AIzaSyARAKu23k_1vltEKesq6REtMSIflQ3c3jo");

          char response[BUFLEN];
          memset(response, 0, BUFLEN);
          uint16_t code = rest.waitResponse(response, BUFLEN);
          if(code == HTTP_STATUS_OK){
          Serial.println("ARDUINO: GET successful:");
          Serial.println(response);
          signed long offsetTime = atoi(response);
          hourOffset = offsetTime/3600;
          minuteOffset = (offsetTime%3600)/60;
          Serial.println(hourOffset);Serial.println(minuteOffset);
          
        }
         else
        {
          Serial.print("ARDUINO: GET failed: ");
          Serial.println(code);
        }
        }
    }
void getTime()
    { 
      // Set up the REST client to talk to www.timeapi.org, this doesn't connect to that server,
      // it just sets-up stuff on the esp-link side
      int err = rest.begin("www.timeapi.org");
      if (err != 0)
         {
           Serial.print("REST begin failed: ");
           Serial.println(err);
           while(1) ;
         }
      Serial.println("EL-REST ready");
      // process any callbacks coming from esp_link
      esp.Process();

      // if we're connected make an HTTP request
      if(wifiConnected)
        {
          // Request /utc/now from the previously set-up server
          rest.get("/utc/now");

          char response[BUFLEN];
          memset(response, 0, BUFLEN);
          uint16_t code = rest.waitResponse(response, BUFLEN);
          if(code == HTTP_STATUS_OK){
          Serial.println("ARDUINO: GET successful:");
          Serial.println(response);
          String data(response);
          thisDay = data.substring(8,10);
         // thisDate = atoi(date.c_str());
          String month = data.substring(5,7);
          int currentMonth = atoi(month.c_str());
          
          switch(currentMonth)
                {
                  case 1: thisMonth = monthArray[currentMonth-1];break;
                  case 2: thisMonth = monthArray[currentMonth-1];break;
                  case 3: thisMonth = monthArray[currentMonth-1];break;
                  case 4: thisMonth = monthArray[currentMonth-1];break;
                  case 5: thisMonth = monthArray[currentMonth-1];break;
                  case 6: thisMonth = monthArray[currentMonth-1];break;
                  case 7: thisMonth = monthArray[currentMonth-1];break;
                  case 8: thisMonth = monthArray[currentMonth-1];break;
                  case 9: thisMonth = monthArray[currentMonth-1];break;
                  case 10: thisMonth = monthArray[currentMonth-1];break;
                  case 11: thisMonth = monthArray[currentMonth-1];break;
                  case 12: thisMonth = monthArray[currentMonth-1];break;
                }  
                  
         
          String hour = data.substring(11,13);
          hours = atoi(hour.c_str());
          String minute = data.substring(14,16);
          minutes = atoi(minute.c_str());
          int hoursInMinutes = hours*60;
         
           hours = hours + hourOffset-1; 
           if(hours>12)
            {
              hours = hours%12;
            }  
          
          minutes = minutes + minuteOffset;
          if(minutes>=60)
            {
              minutes = minutes%60;
              hours += 1;
             }  
          String second = data.substring(17,19);
          seconds = atoi(second.c_str());
              if(((hours - hourOffset)%24) > 12 )// minutes >= minuteOffset)
                {
                  AMorPM = "am"; 
                }
              if(((hours - hourOffset)%24) <= 12)// && minutes >= minuteOffset)
                {
                  AMorPM = "pm";
                }
     
          Serial.println("hours: ");
          Serial.println(hours);
          Serial.println("minutes: ");
          Serial.println(minutes);
          Serial.println("seconds: ");
          Serial.println(seconds);
          
        } 
      else
        {
          Serial.print("ARDUINO: GET failed: ");
          Serial.println(code);
        }
     }
  }

Video