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)

Advertisement

Nokia 5110 display on Arduino

The Nokia 5110 LCD module is a small and cheap LCD with a lot of graphical possibilities and is quick to add to projects that need a display. The programming of the display is a bit difficult but there are a number of very good libraries available. Adafruit ofcourse has a library that is available here: here you will also need to install the GFX library that library is a bit slow but a faster hardware SPI library by Snigelen is available here: here.
Some additions to the Adafruit library have been made by avdweb
The arduino playground has a library: here
A library is also available: here
A further fast libray is available here with explanation here
Also a library by Henning Karlsen

The display driver is a PCD8544 chip, and it runs at 3.3V so you will need a 3.3V supply handy. Logic levels must be 3.3V to prevent damage so you must use some kind of level shifter (such as a 4050) or some resistors. It is possible to use a number of different lines to hook up the LCD. Normally it is 5 lines, but a configuration with 4 or even 3 lines is possible The Nokia 5110 LCD has 5 control lines; the interface is of the type SPI.

For a good understanding of how to hook up the Nokia LCD, it is good to understand that it is an SPI device.
Apart from power and ground (and power to the LED backlight if there is one) There are four basic signal lines to an SPI device. They are

  • MOSI (Master Out Slave In) also known as SIMO and SDI; DI, DIN, SI: because it is Serial Data In. It lets the master send data to slave.
  • MISO  (Master In Slave Out) aka SDO; DO, DOUT, SO which allows the slave to send data to the master. It isn’t always there.
  • SS  (Slave Select) also known as SCE, nCS, CS, CSB, CSN, nSS, STE which switches sending between master and slave.
  • SCLK  which is the clock pulse.

The Nokia5110 LCD has no MISO signal, but it has a:

  • D/C which selects between data and commands being sent.

and ofcourse:

  • RST  (Reset)
  • GND
  • Vcc which needs 3.3V

As long as you are using the Nokia LCD stand alone you are rather flexible in choosing what pins to use, however, if you want to use it in combination with another SPI device on the hardware SPI bus, you must use the proper SPI pins and you cannot use the MISO for any of the Nokia LCD pins as it has no MISO
The proper connection would be:
MOSI ->  MISO  (D12)
SCLK -> SCK (D13)
SS -> an available pin on Arduino, other than D11, traditionally D10 or D8 are used
D/C -> an available pin on Arduino, other than D11
RST -> an available pin on Arduino, other than D11, or an auto reset

Mostly, when no other SPI devices are used, the chip select can be connected to the GND, so 4 control lines remain. As said, it is possible to use only 3 control lines, by connecting the Nokia reset pin to the Arduino reset. This works only when the serial monitor is used, not with a standalone Arduino.

Another possibility is to generate a reset pulse on power up automatically, with a RC combination, to save one control line to the Arduino. This solution doesnt seem to be reliable though. The proper functioning seems to also depend on the capacitor across the 3.3V supply. Using only 4 or 3 lines of course only makes sense if your library allows that, otherwise the pins may not be connected but will be in use by your program. The Device  can tolerate a Vcc of 5 Volt, but it works best at 3.3Volt. When using it with a 5 Volt device, it is best to either have a level adapter or  resistors between the two devices.

 

nokia5510-4050

Example of connection with resistors and 4 control lines

 

handy article

7 Segment display on Arduino with 595

7_segment_display7 Segment displays are easy to attach to an arduino (or other microprocessor). Just connect the digital Outputs of the Arduino with a segment of the display (via a current limiting 470-560 ohm resistor: the IC can in total only deliver 70mA) and fire away.

Nothing wrong with that except for normally needing 8 digital pins for that (if you are using the point as well), and in some cases that might just be too much.

It is possible to use only 3 output pins if you are using a serial shift register like the 74HC595.
This chip will take a base-10 number and translate that into a binary number on its 8 output pins. So if I send  ‘0’ the output will be ‘00000000’ and if I send ‘255’ the output will be ‘11111111’ so with the proper connections to the pins of the display, the correct segments can be made to lit up.

When you get a 7 segment display it is not always clear what the pin configuration of that chip is. Sometimes it is not even clear if it is a common anode or a common cathode display, so that is what we need to figure out first. Ofcourse if you have a datasheet, that helps, but it can’t hurt to check, just to make sure. If you look at the picture below, it is already clear what the common pins are. Use a simple multimeter, keep  one probe on the common pin and see what segments light up  when you touch a pin with the other probe

7seg_dispA simple way  to set up the proper connections is to follow the more or less standardized connections below:
Q0 ->A  (or, to be more precise, the pin that lights up segment ‘A’)
Q1->B
Q2->C
Q3->D
Q4->E
Q5->F
Q6->G
Q7->DP
It is obvious that  sending ‘0’  to the display will not light up any segments while sending ‘255’ to the display will light up all the segments, including the DP.
As the DP is connected to Q7 it is clear that sending 127 will light up all the segments except DP, which means it will form an ‘8’.

For the ‘0’ you need all the elements to light except G. As G is connected to  Q6, you will need ‘11111100’ on the 595, which is ’63’
With the chosen connections, the following numbers will make the ‘0’ til ‘9’:

63, 6, 91,79, 102, 109, 125,7, 127,111.

(192,249,164,176,153,146,130,248,128,144  for common anode)
If for whatever reason (easier in yr print design perhaps), just set up a truth table and determine the base numbers you need to send

After you have those base-numbers that represent a specific number, store those in an array, from where you can send them to the HCT595.

Your connections between Arduino, 74HC595 and 7 segment will look like this:

Arduino pin 5 => 74HC595 pin 12 (latch)
Arduino pin 6 => 74HC595 pin 14 (data)
Arduino pin 7 => 74HC595 pin 11 (clock)

74HC595 pin 1  (Q1)   => LED Pin 5  (B)
74HC595 pin 2  (Q2)   => LED Pin 9  (C)
74HC595 pin 3  (Q3)   => LED Pin 7  (D)
74HC595 pin 4  (Q4)   => LED Pin 6  (E)
74HC595 pin 5  (Q5)   => LED Pin 2  (F)
74HC595 pin 6  (Q6)   => LED Pin 1 (G)
74HC595 pin 7  (Q7)   => LED Pin 10  (DP)
74HC595 pin 8  (GND)  => Ground
74HC595 pin 9  (Q7S)  => Not connected
74HC595 pin 10 (MR)   => Vcc (High)
74HC595 pin 11 (SHCP) => Arduino pin 7
74HC595 pin 12 (STCP) => Arduino pin 5
74HC595 pin 13 (OE)   => Ground (Low)
74HC595 pin 14 (DS)   => Arduino pin 6
74HC595 pin 15 (Q0)   => LED Pin 4  (A)
74HC595 pin 16 (Vcc)  => Vcc

the choice for the arduino pins connecting to the 595 lines… that is  randomly chosen. they could have been other pins

LED pin 3 or 8 => 470 Ohm resistor => Vcc  (for a common anode display)  or  => Ground (for a common cathode display)
With regard to the last line there is some debate whether with a 7 segment display it would be enough to use only one resistor in the common anode or cathode or that they each should have their own resistor. Obviously, displaying a ‘1’ involves only 2 segments to light up, whereas a ‘0’ requires 6 segments to light up and therefore would be less bright. For testing purposes you could use 1 resistor of say 330 ohm in the common lead. For final circuit I would advise separate resistors.

7segment

7_segmentPrint

7segm_action

Program:

/*
Using a 7-segment display with the 74HC595 shift register
*/

int latchpin = 5;// connect to pin 12 on the '595
int clockpin = 7; // connect to pin 11 on the '595
int datapin = 6; // connect to pin 14 on the '595
// the array contains the binary value to make digits 0-9
// for the number '11'  use code '31' for CC and '224' for CA
int segment[10] = {63,6,91,79,102,109,125,7,127,111 }; // for common cathode
//int segment[10] = {192,249,164,176,153,146,130,248,128,144 }; // for common anode

void setup()
{
pinMode(latchpin, OUTPUT);
pinMode(clockpin, OUTPUT);
pinMode(datapin, OUTPUT);
}
void loop()
{

digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0); // clears the display
digitalWrite(latchpin, HIGH);
delay(1000);

for (int lus=0; lus<10; lus++)
// counts from 0 to 9, using the values in the array
// whose values correspond to the binary outputs 0~9
// add 128 for digital point
{
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, segment[lus]+128);
digitalWrite(latchpin, HIGH);
delay(500);
}

digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 0); // clear the display
digitalWrite(latchpin, HIGH);
delay(1000);

digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, MSBFIRST, 128); // light the decimal point
digitalWrite(latchpin, HIGH);
delay(1000);

}

mind you that it is possible to count to ’11’ on the display. just write ’31’ (‘00011111’) to the 595

VQB 27 E
VQB 27 E

A popular 7 segment matrix is the VQB 27 E Y3. The pin out is a bit different. You will find it in the image