Use this forum to chat about hardware specific topics for the ESP8266 (peripherals, memory, clocks, JTAG, programming)

User avatar
By sprinkfitter
#72458 I am wanting to use an esp8266 12e with a RTC and LCD 20x4 display. I want my relay to work by time of day. I am looking for examples of i2c working with the clock and the lcd or another way to get the clock and LCD in my projects. Thanks again for the help

Sprinkfitter :) :)
User avatar
By rudy
#72462 One problem I had with using the I2C 20x4 lcd with 3.3v powered processors is that the lcd (with the I2C PCF8574) is powered from 5 volts and the high level output from the 3.3 v processor often is not high enough for the PCF8574. I include a 3-5 volt level converter to make the levels compatible.

My preference is the DS3231 for the RTC. 3.3 volt compatible.

One other display option I have used with the ESP8266 is the 128x64 OLED.

IMG3.jpg


IMG_1.jpg
You do not have the required permissions to view the files attached to this post.
User avatar
By rudy
#72463 I looked into my RTC directory and I found a program that was interesting. I added I2C LCD to it. It is an ugly hack but it works. Reads the time from the RTC and displays it on the LCD. There also is a web page that can be used to change the time. Not in English but easy enough to figure out.

I'm not sure where the original program was from.
maybe here - https://jmloureiro77.blogspot.ca/2017/0 ... s3231.html

https://github.com/Makuna/Rtc RTC library
https://github.com/agnunez/ESP8266-I2C-LCD1602 I2C LCD library

I have a led on GPIO15,
I2C lines are on 0 and 1. see code

I use a supercap in place of the battery for the RTC.

Code: Select all//  I'm not sure where the original program was from.
// maybe here  -  https://jmloureiro77.blogspot.ca/2017/04/esp8266-rtc-ds3231.html
// https://github.com/Makuna/Rtc   RTC library
// https://github.com/agnunez/ESP8266-I2C-LCD1602   I2C LCD library 

// CONNECTIONS:
// DS3231 SDA --> SDA=============nodemcu D1
// DS3231 SCL --> SCL=============nodemcu D2
// DS3231 VCC --> 3.3v or 5v
// DS3231 GND --> GND

#include <ESP8266WiFi.h>
//#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>

#include <Wire.h> // must be included here so that Arduino library object file references work
#include <RtcDS3231.h>
RtcDS3231<TwoWire> Rtc(Wire);

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); //I2C address, columns, lines

const int ledPin =  15;              // the number of the LED pin
// Variables will change:
int ledState = LOW;             // ledState used to set the LED

const char* host = "esp8266";

const char* ssid = "2WIRE865";
const char* password = "xxxxxxxxxxxxxxx";

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change:
const long interval = 1000;           // interval at which to blink (milliseconds)


char datestring[20];
String message, javaScript, XML;

ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;

RtcDateTime now;

//=============================================================================================
void buildJavascript() {
  //=============================================================================================
  javaScript = "<SCRIPT>\n";
  javaScript += "var xmlHttp=createXmlHttpObject();\n";

  javaScript += "function createXmlHttpObject(){\n";
  javaScript += " if(window.XMLHttpRequest){\n";
  javaScript += "    xmlHttp=new XMLHttpRequest();\n";
  javaScript += " }else{\n";
  javaScript += "    xmlHttp=new ActiveXObject('Microsoft.XMLHTTP');\n"; // code for IE6, IE5
  javaScript += " }\n";
  javaScript += " return xmlHttp;\n";
  javaScript += "}\n";

  javaScript += "function process(){\n";
  javaScript += " if(xmlHttp.readyState==0 || xmlHttp.readyState==4){\n";
  javaScript += "   xmlHttp.open('PUT','xml',true);\n";
  javaScript += "   xmlHttp.onreadystatechange=handleServerResponse;\n"; // no brackets?????
  javaScript += "   xmlHttp.send(null);\n";
  javaScript += " }\n";
  javaScript += " setTimeout('process()',1000);\n";
  javaScript += "}\n";

  javaScript += "function handleServerResponse(){\n";
  javaScript += " if(xmlHttp.readyState==4 && xmlHttp.status==200){\n";
  javaScript += "   xmlResponse=xmlHttp.responseXML;\n";

  javaScript += "   xmldoc = xmlResponse.getElementsByTagName('rYear');\n";
  javaScript += "   message = xmldoc[0].firstChild.nodeValue;\n";
  javaScript += "   document.getElementById('year').innerHTML=message;\n";

  javaScript += "   xmldoc = xmlResponse.getElementsByTagName('rMonth');\n";
  javaScript += "   message = xmldoc[0].firstChild.nodeValue;\n";
  javaScript += "   document.getElementById('month').innerHTML=message;\n";

  javaScript += "   xmldoc = xmlResponse.getElementsByTagName('rDay');\n";
  javaScript += "   message = xmldoc[0].firstChild.nodeValue;\n";
  javaScript += "   document.getElementById('day').innerHTML=message;\n";

  javaScript += "   xmldoc = xmlResponse.getElementsByTagName('rHour');\n";
  javaScript += "   message = xmldoc[0].firstChild.nodeValue;\n";
  javaScript += "   document.getElementById('hour').innerHTML=message;\n";

  javaScript += "   xmldoc = xmlResponse.getElementsByTagName('rMinute');\n";
  javaScript += "   message = xmldoc[0].firstChild.nodeValue;\n";
  javaScript += "   document.getElementById('minute').innerHTML=message;\n";

  javaScript += "   xmldoc = xmlResponse.getElementsByTagName('rSecond');\n";
  javaScript += "   message = xmldoc[0].firstChild.nodeValue;\n";
  javaScript += "   document.getElementById('second').innerHTML=message;\n";

  javaScript += "   xmldoc = xmlResponse.getElementsByTagName('rTemp');\n";
  javaScript += "   message = xmldoc[0].firstChild.nodeValue;\n";
  javaScript += "   document.getElementById('temp').innerHTML=message;\n";

  javaScript += " }\n";
  javaScript += "}\n";
  javaScript += "</SCRIPT>\n";
}
//=============================================================================================
void buildXML() {
  //=============================================================================================
  RtcDateTime now = Rtc.GetDateTime();
  RtcTemperature temp = Rtc.GetTemperature();
  XML = "<?xml version='1.0'?>";
  XML += "<t>";
  XML += "<rYear>";
  XML += now.Year();
  XML += "</rYear>";
  XML += "<rMonth>";
  XML += now.Month();
  XML += "</rMonth>";
  XML += "<rDay>";
  XML += now.Day();
  XML += "</rDay>";
  XML += "<rHour>";
  if (now.Hour() < 10) {
    XML += "0";
    XML += now.Hour();
  } else {
    XML += now.Hour();
  }
  XML += "</rHour>";
  XML += "<rMinute>";
  if (now.Minute() < 10) {
    XML += "0";
    XML += now.Minute();
  } else {
    XML += now.Minute();
  }
  XML += "</rMinute>";
  XML += "<rSecond>";
  if (now.Second() < 10) {
    XML += "0";
    XML += now.Second();
  } else {
    XML += now.Second();
  }
  XML += "</rSecond>";
  XML += "<rTemp>";
  XML += temp.AsFloat();
  XML += "</rTemp>";
  XML += "</t>";
}
//=============================================================================================
void handleRoot() {
  //=============================================================================================
  buildJavascript();
  IPAddress ip = WiFi.localIP();
  String ipStr = (String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]));

  // message="<!DOCTYPE HTML>\n";
  message = "<html>";
  //  message = "<html><head><meta http-equiv='refresh' content='5'/>";
  message = "<head>";
  message = javaScript;
  message += "<title>ESP8266 Demo</title>";
  message += "<style> body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }";
  message += "h1 {text-align:center;}";
  message += "h2 {text-align:center;}";
  message += "p {text-align:center;}";
  message += "table.center { width:80%; margin-left:10%; margin-right:10%;}";
  message += "</style>";
  message += "  </head>";
  message += "  <body onload='process()'>";
  message += "<table class='center'>";
  message += "  <tr>";
  message += "    <th>";
  message += "<h1>Fecha y Hora</h1>";
  message += "    </th> ";
  message += "  </tr>";
  message += "  <tr>";
  message += "    <td align='center'>";
  message += "    </td>";
  message += "  </tr>";


  message += "  <tr>";
  message += "    <td align='center'>";
  message += "<A id='year'></A>/<A id='month'></A>/<A id='day'></A>   <A id='hour'></A>:<A id='minute'></A>:<A id='second'></A><BR>";
  message += "    </td>";
  message += "  </tr>";

  message += "  <tr>";
  message += "    <td align='center'>";
  message += "Temp =<A id='temp'></A>C<BR>";
  message += "    </td>";
  message += "  </tr>";

  message += "  <tr>";
  message += "    <td>";
  message += "<H2><a href='/setTime'>Cambiar fecha y hora</a></H2>";
  message += "    </td>";
  message += "  </tr>";

  message += "  <tr>";
  message += "    <td align='center'>";
  message += "<BR>IP  ";
  message += ipStr;
  message += "    </td>";
  message += "  </tr>";
  message += "</table>";

  message += "<BR>";

  message += "";

  message += "</body></html>";

  httpServer.send ( 404 , "text/html", message );
}

//=============================================================================================
void setTime() {
  //=============================================================================================
  buildJavascript();
  // message="<!DOCTYPE HTML>\n";
  message = "<html>";
  //  message = "<html><head><meta http-equiv='refresh' content='5'/>";
  message = "<head>";
  message = javaScript;
  message += "<title>ESP8266 set time</title>";
  message += "<style> body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }";
  message += "h1 {text-align:center;}";
  message += "h2 {text-align:center;}";
  message += "p {text-align:center;}";
  message += "table.center { width:80%; margin-left:10%; margin-right:10%;}";
  message += "</style>";
  message += "  </head>";
  message += "  <body onload='process()'>";/////////////////////////////////////////

  message += "";

  message += "<table class='center'>";
  message += "  <tr>";
  message += "    <th>";
  message += "<h1>Cambiar fecha y hora</h1>";
  message += "    </th> ";
  message += "  </tr>";
  message += "  <tr>";
  message += "    <td align='center'>";
  message += "Fecha Atual  ";
  message += " <BR>   </td>";
  message += "  </tr>";
  message += "  <tr>";
  message += "    <td align='center'>";
  message += "<A id='year'></A>/<A id='month'></A>/<A id='day'></A><BR>";
  message += "    </td>";
  message += "  </tr>";
  message += "  <tr>";
  message += "    <td align='center'>";

  message += "<form >";
  message += "Pon fecha posterior a 2017-03-20<br><br>";
  message += "<input type='date' name='date' min='2017-03-20' style='height:75px; width:200px'><br><br>";
  message += "<input type='submit' value='Actualizar Fecha' style='height:75px; width:200px'> ";
  message += "</form>";


  message += "    </td>";
  message += "  </tr>";
  message += "  <tr>";
  message += "    <td align='center'>";
  message += "Hora Actal<BR><A id='hour'></A>:<A id='minute'></A>:<A id='second'></A><BR><BR>";
  message += "    </td>";
  message += "  </tr>";
  message += "  <tr>";
  message += "    <td align='center'>";
  message += "<form >";
  message += "Nueva hora<br>";
  message += "<input type='TIME' name='time' style='height:75px; width:200px'><br><br>";
  message += "<input type='submit' value='Actualizar Hora' style='height:75px; width:200px'> ";
  message += "</form>";
  message += "    </td>";
  message += "  </tr>";
  message += "  <tr>";
  message += "    <td>";
  message += "<H2><a href='/'>ATRAS</a></H2>";
  message += "    </td>";
  message += "  </tr>";
  message += "</table>";


  message += "";

  message += "</body></html>";

  httpServer.send ( 404 , "text/html", message );

  // Fecha--------------------------------------------------------------------
  if (httpServer.hasArg("date")) {

    uint16_t ano;
    uint8_t mes;
    uint8_t dia;
    Serial.print("ARGdate");
    Serial.println(httpServer.arg("date"));
    String sd = httpServer.arg("date");
    String lastSd;
    //   int someInt = someChar - '0';
    ano = ((sd[0] - '0') * 1000) + ((sd[1] - '0') * 100) + ((sd[2] - '0') * 10) + (sd[3] - '0');
    mes = ((sd[5] - '0') * 10) + (sd[6] - '0');
    dia = ((sd[8] - '0') * 10) + (sd[9] - '0');
    if (sd != lastSd) {
      RtcDateTime now = Rtc.GetDateTime();
      uint8_t hour = now.Hour();
      uint8_t minute = now.Minute();
      Rtc.SetDateTime(RtcDateTime(ano, mes, dia, hour, minute, 0));
      lastSd = sd;
    }
    // Serial.println(fa);

    httpServer.send ( 404 , "text", message );
  }//if has date
  // Hora ------------------------------------------------
  if (httpServer.hasArg("time")) {
    Serial.println(httpServer.arg("time"));
    String st = httpServer.arg("time");
    String lastSt;
    //   Serial.print("st ");
    //   Serial.println(st);
    //int someInt = someChar - '0';
    uint8_t hora = ((st[0] - '0') * 10) + (st[1] - '0');
    uint8_t minuto = ((st[3] - '0') * 10) + (st[4] - '0');
    if (st != lastSt) {
      RtcDateTime now = Rtc.GetDateTime();
      uint16_t year = now.Year();
      uint8_t month = now.Month();
      uint8_t day = now.Day();
      Rtc.SetDateTime(RtcDateTime(year, month, day, hora, minuto, 0));
      lastSt = st;
    }
    httpServer.send ( 404 , "text", message );

  }//if has time
}
//=============================================================================================
void handleXML() {
  //=============================================================================================
  buildXML();
  httpServer.send(200, "text/xml", XML);
}
//=============================================================================================
void handleNotFound() {
  //=============================================================================================
  String message = "<html><head>";
  message += "<title>ESP8266 Not Found</title>";
  message += "<style> body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }";
  message += "h1 {text-align:center;}";
  message += "h2 {text-align:center;}";
  message += "</style>";
  message += "  </head>";
  message += "  <body>";
  message += "<table style='width:80%'>";
  message += "<tr>";//fila
  message += "<th>";//columna encavezado
  message += "<h1>Not Found</h1>";
  message += "</th>";
  message += "<tr>";//fila 2
  message += "<td>";//columna normal
  message += "<H2><a href='/'>Back</a></H2>";
  message += "<td>";
  message += "</tr>";
  message += "</table>";
  message += "</body></html>";
  message += "";

  httpServer.send ( 404 , "text", message );
}

//=============================================================================================
void setup(void) {
  //=============================================================================================
  pinMode(ledPin, OUTPUT);
 
  Serial.begin(115200);
  Serial.println();
  Serial.println("Booting Sketch...ESP_RTC3231.ino");

  lcd.begin(0, 2);        // In ESP8266-01, SDA=0, SCL=2
  lcd.clear();
  lcd.setCursor(0, 3);    // column 0, row 0
  lcd.print("lcd setup");

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
    Serial.println("WiFi failed, retrying.");
  }
  if ( MDNS.begin ( "host" ) ) {
    Serial.println ( "MDNS responder started" );
  }
  //MDNS.begin(host);

  httpUpdater.setup(&httpServer);


  httpServer.on ( "/", handleRoot );
  httpServer.on ( "/setTime", setTime );
  httpServer.on ( "/xml", handleXML) ;


  httpServer.onNotFound ( handleNotFound );

  Serial.println ( "HTTP server started" );

  httpServer.begin();

  MDNS.addService("http", "tcp", 80);
  Serial.printf("HTTPUpdateServer ready!\n Open http://%s.local/update in your browser\n", host);

  Serial.println(WiFi.localIP());
  Serial.println("-----------------------");

  // RTC ---------------------------------------------------------------------------------------
  Rtc.Begin();

  // if you are using ESP-01 then uncomment the line below to reset the pins to
  // the available pins for SDA, SCL
  Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL

  //   RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
  if (!Rtc.GetIsRunning()) {
    //     Serial.println("RTC was not actively running, starting now");
    Rtc.SetIsRunning(true);
  }
  //RtcDateTime now = Rtc.GetDateTime();
  // never assume the Rtc was last configured by you, so
  // just clear them to your needed state
  Rtc.Enable32kHzPin(false);
  Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);

  lcd.setCursor(0, 3);    // column 0, row 0
  lcd.print("           "); 
}

//=============================================================================================
void loop(void) {
  //=============================================================================================
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);

    // RTC ---------------------------------------------------------------------------------------
    RtcDateTime now = Rtc.GetDateTime();
    printDateTime(now);
    Serial.println();

    RtcTemperature temp = Rtc.GetTemperature();
    Serial.print(temp.AsFloat());
    Serial.println("C");

/*
    lcd.setCursor(0, 0);    // column 0, row 0
    lcd.println(dt.Hour());
    lcd.println(":");
    lcd.println(dt.Minute());
    lcd.println(":");
    lcd.println(dt.Second());
    */
  }

  httpServer.handleClient();
}

//=======================================================

#define countof(a) (sizeof(a) / sizeof(a[0]))

void printDateTime(const RtcDateTime& dt)
{
  char datestring[20];

  snprintf_P(datestring,
             countof(datestring),
             PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
             dt.Month(),
             dt.Day(),
             dt.Year(),
             dt.Hour(),
             dt.Minute(),
             dt.Second() );
  Serial.print(datestring);

    lcd.setCursor(0, 0);    // column 0, row 0
    lcd.print(datestring);
    lcd.print("  ");
}
//----------------------------------------------------------
Last edited by rudy on Tue Dec 12, 2017 12:09 am, edited 1 time in total.
User avatar
By rudy
#72464 Here is a simpler program but derived from the same RTC library. Also puts time on LCD. No WiFi.

Code: Select all// Rtc_by_Makuna library


// CONNECTIONS:
// DS3231 SDA --> SDA
// DS3231 SCL --> SCL
// DS3231 VCC --> 3.3v or 5v
// DS3231 GND --> GND

#if defined(ESP8266)
#include <pgmspace.h>
#else
#include <avr/pgmspace.h>
#endif


#include <Wire.h> // must be included here so that Arduino library object file references work
#include <RtcDS3231.h>
RtcDS3231<TwoWire> Rtc(Wire);

#include <LiquidCrystal_I2C.h>

  LiquidCrystal_I2C lcd(0x27,20,4); // Check I2C address of LCD, normally 0x27 or 0x3F


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

    Serial.print("compiled: ");
    Serial.print(__DATE__);
    Serial.println(__TIME__);
   
  lcd.begin(0,2);      // In ESP8266-01, SDA=0, SCL=2               
  lcd.backlight();
  lcd.home();                // At column=0, row=0
  lcd.print("Starting");   
 //   lcd.setCursor(0, 1);
   
    //--------RTC SETUP ------------
    Rtc.Begin();

    // if you are using ESP-01 then uncomment the line below to reset the pins to
    // the available pins for SDA, SCL
    Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL

    RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
    printDateTime(compiled);
    Serial.println();

    if (!Rtc.IsDateTimeValid())
    {
        // Common Cuases:
        //    1) first time you ran and the device wasn't running yet
        //    2) the battery on the device is low or even missing

        Serial.println("RTC lost confidence in the DateTime!");

        // following line sets the RTC to the date & time this sketch was compiled
        // it will also reset the valid flag internally unless the Rtc device is
        // having an issue

        Rtc.SetDateTime(compiled);
    }

    if (!Rtc.GetIsRunning())
    {
        Serial.println("RTC was not actively running, starting now");
        Rtc.SetIsRunning(true);
    }

    RtcDateTime now = Rtc.GetDateTime();
    if (now < compiled)
    {
        Serial.println("RTC is older than compile time!  (Updating DateTime)");
        Rtc.SetDateTime(compiled);
    }
    else if (now > compiled)
    {
        Serial.println("RTC is newer than compile time. (this is expected)");
    }
    else if (now == compiled)
    {
        Serial.println("RTC is the same as compile time! (not expected but all is fine)");
    }

    // never assume the Rtc was last configured by you, so
    // just clear them to your needed state
    Rtc.Enable32kHzPin(false);
    Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
}

//===================================================
void loop ()
{
    if (!Rtc.IsDateTimeValid())
    {
        // Common Cuases:
        //    1) the battery on the device is low or even missing and the power line was disconnected
        Serial.println("RTC lost confidence in the DateTime!");
    }

    RtcDateTime now = Rtc.GetDateTime();
    printDateTime(now);
    Serial.println();

    RtcTemperature temp = Rtc.GetTemperature();
    Serial.print(temp.AsFloat());
    Serial.println("C");


    LCDprintDateTime(now);
   
    lcd.setCursor(0, 2);   
    lcd.print("  ");   
    lcd.print(temp.AsFloat());
    lcd.print("C");

    delay(1000); // one seconds
}

//====================================================
#define countof(a) (sizeof(a) / sizeof(a[0]))

void printDateTime(const RtcDateTime& dt)
{
    char datestring[20];

    snprintf_P(datestring,
            countof(datestring),
            PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
            dt.Month(),
            dt.Day(),
            dt.Year(),
            dt.Hour(),
            dt.Minute(),
            dt.Second() );
    Serial.print(datestring);
}

//-----------------------------------------------------------
void LCDprintDateTime(const RtcDateTime& dt)
{
    char datestring[20];

    snprintf_P(datestring,
            countof(datestring),
            PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
            dt.Month(),
            dt.Day(),
            dt.Year(),
            dt.Hour(),
            dt.Minute(),
            dt.Second() );


    lcd.setCursor(0, 1);
    lcd.print(datestring);
}