Adding an RTC and OLED to ESP8266-01

dsc_0024Adding an RTC and OLED to ESP8266-01 is fairly easy with I2C. The ESP8266-01 has 4 I/O pins that can be used for  I2C. using the GPIO0 and GPIO2 for sda resp scl is more or less standard.

esp8266-rtcoledI presume you do know how to program the ESP8266. In short: Connect Tx<->Rx (meaning the Tx of your ESP to the Rx of your USB-TTL converter)
Connect Rx<->Tx Connect CH_PD<->Vcc Connect GPIO0 <->Grnd
As both modules already had pull up resistors, I didnt need to add those. If your modules do not, add 4k7 resistors as pull up on the SDA and SCL lines.

/* ************************************
 Read the time from RTC and display on OLED
 with an ESP8266<br> sda=0, scl=2
* *************************************/

// Libraries
#include <Wire.h>
#include "SSD1306.h" // alias for `#include "SSD1306Wire.h"`
#include "RTClib.h" //  Lady Ada
//Object declarations
RTC_DS1307 rtc;            // RTC
SSD1306  display(0x3c, 0, 2);//0x3C being the usual address of the OLED

//Month and Day Arrays. Put in Language of your choice, omitt the 'day' part of the weekdays
char *maand[] =
{
  "Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"
};
char *dagen[] = {"Zon", "Maan", "Dins", "Woens", "Donder", "Vrij", "Zater" };


// date and time variables
byte m = 0;    // contains the minutes, refreshed each loop
byte h = 0;    // contains the hours, refreshed each loop
byte s = 0;    // contains the seconds, refreshed each loop
byte mo = 0;   // contains the month, refreshes each loop
int j = 0;     // contains the year, refreshed each loop
byte d = 0;    // contains the day (1-31)
byte dag = 0;  // contains day of week (0-6)

void setup() {
  Wire.pins(0, 2);// yes, see text
  Wire.begin(0,2);// 0=sda, 2=scl
  rtc.begin();

// reading of time here only necessary if you want to use it in setup
  DateTime now = rtc.now();
  dag = now.dayOfTheWeek();
  j = now.year();
  mo = now.month();
  d = now.day();
  h = now.hour();
  m = now.minute();
  s = now.second();
  DateTime compiled = DateTime(__DATE__, __TIME__);
  if (now.unixtime() < compiled.unixtime())
  {
    Serial.print(F("Current Unix time"));
    Serial.println(now.unixtime());
    Serial.print(F("Compiled Unix time"));
    Serial.println(compiled.unixtime());
    Serial.println("RTC is older than compile time! Updating");
    // following line sets the RTC to the date & time this sketch was compiled<br>   // uncomment to set the time
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  // Initialise the display.
  display.init();
  display.flipScreenVertically();// flipping came in handy for me with regard 
                                                                // to screen position
  display.setFont(ArialMT_Plain_10);

}


void loop() {
  display.clear();
  DateTime now = rtc.now();
  dag = now.dayOfTheWeek();
  j = now.year();
  mo = now.month();
  d = now.day();
  h = now.hour();
  m = now.minute();
  s = now.second();

  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setFont(ArialMT_Plain_16);
  String t = String(h) + ":" + String(m) + ":" + String(s);
  String t2 = String(d) + ":"  + String(mo) + ":" + String(j);
  display.drawString(0, 10, t);//
  display.drawString(0, 24, t2);
  display.drawString(0, 38, maand[mo - 1]);
  String d = dagen[dag];
  d = d + "dag";//adding the word 'dag' (=day)  to the names of the days
  display.drawString(0, 52, d);
  // write the buffer to the display
  display.display();
  delay(10);
}

The code is fairly straightforward but it does contain some peculiarities.
I make a call to ‘Wire.pins(sda,scl)’. That seems redundant and in fact the call was deprecated, but apparently if any other library would make a call to ‘Wire()’ the proper definition of the pins for the sda and scl can get lost. So I left them both in for safety.
If you still have an old RTCLib you may get an error on ‘dayOfTheWeek’. That is because it used to be called ‘dayOfWeek’ but it got changed: update your library.

The last line, with the day on it, may be just a bit too much size for your OLED: set the font smaller (say ‘Plain_10’) and alter the print positions (the second digits in the display.drawString(0, x, string); statements)

Advertisements

Adding 433MHz RC to ESP8266-01

esp266-433Currently I have a homeautomation system on an Arduino. It uses 433 Mhz to switch lamps and stuff. It works fully automatic and if i want to intervene I use bluetooth to give commands.
It works well, but if I am away from home, I cannot intervene or check anything anymore. So I started to transfer the entire Arduino based system to an ESP8266.
Obviously that is a big overhaul and one of the first things I wanted to check is how well my 433 Mhz switches could be integrated with an ESP8266.
As such code might be beneficial to others, I thought I’d publish it here.
The 433 Mhz library I use is the enhanced RemoteSwitch library. I find that a bit more pleasant than the RCSwitch library because for many (not for all) remote switch sockets you do not need to sniff any code. Just knowing what type of Switch you have is enough.
The example below switches 4 sockets. I have explained the use of those switches with the RemoteSwitch library in another post. Obviously I switch many more in my house, but I wanted to keep things in this example simple. I am using an ESP8266-01, the simplest of the ESP8266 modules. I use GPIO2 to connect to the signal pin of a 433 MHz transmitter and feed everything with 3.3 Volt. As the ESP8266 is working on 3.3Volt, the transmitter is also working on 3.3Volt. I didnt notice any problem with that, but it is better to use a decent antenna that is easy to make, rather than just a 1/4 wavelength rod. Under no circumstance put 5 volt on any of your ESP8266 pins. If for whatever reason you need or want to feed the transmitter with a higher voltage, then I presume it is ok to still connect the GPIO2 pin to the data pin of the transmitter, as I presume that doesnt carry a voltage (but better do not risk it), but the transmitter may not recognize the ESP8266 output as HIGH. Adding a levelconverter may be necessary then, but to be clear: It works well with 3.3 Volt for the transmitter
The Sketch is quite straightforward. I included 4 switches as example. Therefore there are 8 buttons defined (ON and OFF for each channel.
If you want to add more switches, add the names for these in the Array. The program will automatically generate the required buttons. Add the On and Off codes for yr switch to code for the pages via a Switch /case statement.
When you start the program the relevant connection data is printed in the serialmonitor but the IP that you need can also be checked in the DHCPclient list of your router

/*
    This Sketch demonstrates the use of the Extended RemoteSwitch Library  with an ESP8266-01 WiFi module
    The setup is as follows:
    Supply module with 3.3 Volt
    Attach  pin GPIO2 with the signal pin of a 433 Mhz transmitter module
    The names you want to attach to the Buttons are defined in  the array "socketnames"
    the number of sockets can be extended. Pages are dynamically generated based on the
    size of the array as calculated by "ARRAY_SIZE"
    The use of  4 different modules is demonstrated:
    ELRO AB440
    Blokker /SelectRemote 1728029
    EverFlourish EMW203
    Eurodomest 972080
    Basic idea from Alexbloggt
    23-09-2016 DIY_bloke
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <RemoteSwitch.h> //FuzzyLogic extended lib

/************************************************
            Object Declarations
 ***********************************************/
ElroAb440Switch ab440Switch(2);
BlokkerSwitch3 blokkerTransmitter(2);// SelectRemote 1728029
EverFlourishSwitch everswitch(2);  // EverFlourish EMW203
Ener002Switch enerswitch(2);      // Eurodomest 972080
//  Fill out the base address of YOUR Eurodomest switch
const unsigned long euro  = 823149;  // base adres eurodomest  : 11001000111101101101  Supply the baseaddress of YOUR Eurodomest
#define ElroAAN ab440Switch.sendSignal(29, 'A', true)
#define ElroUIT ab440Switch.sendSignal(29, 'A', false)
#define BlokkerAAN blokkerTransmitter.sendSignal(1, true)
#define BlokkerUIT blokkerTransmitter.sendSignal(1, false)
#define EverFlourishAAN everswitch.sendSignal('A', 1, true)
#define EverFlourishUIT everswitch.sendSignal('A', 1, false)
#define EnerAAN enerswitch.sendSignal(euro, 1, true)
#define EnerUIT enerswitch.sendSignal(euro, 1, false)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
MDNSResponder mdns;
// Replace with your network credentials
const char* ssid = "YourSSID";
const char* password = "YourPassword";
ESP8266WebServer server(80);
// Define names of your buttons here, number of buttons will be  automatically adapted
char* socketnames[] = {"ELROAB440", "Blokker", "EverFlourish", "ActionSwitch"};
int numofsockets = ARRAY_SIZE (socketnames);//bevat de grootte van het Array
// sample css and html code
String css = "body {background-color:#ffffff; color: #000000; font-family: 'Century Gothic', CenturyGothic, AppleGothic, sans-serif;}h1 {font-size: 2em;}";
String head1 = "<!DOCTYPE html> <html> <head> <title>RemoteSwitch Demo</title> <style>";
String head2 = "</style></head><body><center>";
String header = head1 + css + head2;
String body = "";
String website(String h, String b) {
  String complete = h + b;
  return complete;
}
void setup(void) {
  // adapt body part of html if necessary
  body = "<h1>RemoteSwitch Demo</h1>";
  // socket names and buttons are created dynamical
  for (int i = 0; i < numofsockets; i++) {
    String namesocket = socketnames[i];
    body = body + "<p>" + namesocket + " <a href=\"socket" + String(i) + "On\"><button>ON</button></a> <a href=\"socket" + String(i) + "Off\"><button>OFF</button></a></p>";
  }
  body += "</center></body>";
  delay(1000);
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // serial output of connection details
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  if (mdns.begin("esp8266", WiFi.localIP())) {
    Serial.println("MDNS responder started");
  }
  // this page is loaded when accessing the root of esp8266´s IP
  server.on("/", []() {
    String webPage = website(header, body);
    server.send(200, "text/html", webPage);
  });

  /************************************************
                        Dynamically creating pages
   *********************************************** */
  for (int i = 0; i < numofsockets; i++) {
    String pathOn = "/socket" + String(i) + "On";
    const char* pathOnChar = pathOn.c_str();
    String pathOff = "/socket" + String(i) + "Off";
    const char* pathOffChar = pathOff.c_str();
    //content ON page
    server.on(pathOnChar, [i]() {
      String webPage = website(header, body);
      server.send(200, "text/html", webPage);

      switch (i)
      {
        case 0:
          ElroAAN;
          break;
        case 1:
          BlokkerAAN;
          break;
        case 2:
          EverFlourishAAN;
          break;
        case 3:
          EnerAAN;
          break;
        default:
          break;

      }
      delay(500);
    });
    //content OFF page
    server.on(pathOffChar, [i]() {
      String webPage = website(header, body);
      server.send(200, "text/html", webPage);

      switch (i)
      {
        case 0:
          ElroUIT;
          break;
        case 1:
          BlokkerUIT;
          break;
        case 2:
          EverFlourishUIT;
          break;
        case 3:
          EnerUIT;
          break;
        default:
          break;

      }
      delay(500);
    });
  }
  server.begin();
  Serial.println("HTTP server started");
}
void loop(void) {
  server.handleClient();
}