OLED Display and
ESP8266
All Displays
Where to get:
https://www.aliexpress.com
Library
esp8266-oled-ssd1306
https://github.com/ThingPulse/esp8266-oled-ssd1306
Documentation
In the README.md file included with the library.
README.md
Get IIC Address
/*
* i2c_port_address_scanner
* Scans ports D0 to D7 on an ESP8266 and searches for I2C device.
based on the original
* code available on Arduino.cc and later improved by user Krodal
and Nick Gammon
* (www.gammon.com.au/forum/?id=10896)
* D8 throws exceptions thus it has been left out
*
*/
#include <Wire.h>
void setup() {
Serial.begin(9600);
while
(!Serial);
// Leonardo: wait for serial monitor
Serial.println("\n\nI2C Scanner to scan for devices on each
port pair D0 to D7");
scanPorts();
}
uint8_t portArray[] = {16, 5, 4, 0, 2, 14, 12, 13};
String portMap[] = {"D0", "D1", "D2", "D3", "D4", "D5", "D6",
"D7"}; //for Wemos
//String portMap[] = {"GPIO16", "GPIO5", "GPIO4", "GPIO0",
"GPIO2", "GPIO14", "GPIO12", "GPIO13"};
void scanPorts() {
for (uint8_t i = 0; i < sizeof(portArray); i++) {
for (uint8_t j = 0; j < sizeof(portArray);
j++) {
if (i != j){
Serial.print("Scanning
(SDA : SCL) - " + portMap[i] + " : " + portMap[j] + " - ");
Wire.begin(portArray[i], portArray[j]);
check_if_exist_I2C();
}
}
}
}
void check_if_exist_I2C() {
byte error, address;
int nDevices;
nDevices = 0;
for (address = 1; address < 127; address++ ) {
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the 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.print(address, HEX);
Serial.println(" !");
nDevices++;
} else if (error == 4) {
Serial.print("Unknow error at
address 0x");
if (address < 16)
Serial.print("0");
Serial.println(address, HEX);
}
} //for loop
if (nDevices == 0)
Serial.println("No I2C devices found");
else
Serial.println("**********************************\n");
//delay(1000);
// wait 1 seconds for next scan, did not find it necessary
}
void loop() {
}
...
Scanning (SDA : SCL) - D2 : D7 - No I2C devices found
Scanning (SDA : SCL) - D3 : D0 - No I2C devices found
Scanning (SDA : SCL) - D3 : D1 - No I2C devices found
Scanning (SDA : SCL) - D3 : D2 - No I2C devices found
Scanning (SDA : SCL) - D3 : D4 - No I2C devices found
Scanning (SDA : SCL) - D3 : D5 - I2C device found at address
0x3C !
**********************************
Scanning (SDA : SCL) - D3 : D6 - No I2C devices found
Scanning (SDA : SCL) - D3 : D7 - No I2C devices found
Scanning (SDA : SCL) - D4 : D0 - No I2C devices found
Scanning (SDA : SCL) - D4 : D1 - No I2C devices found
...
Demo Code
- But First the form:
- >>Short will change the demo to cycle through only 2
displays: Temperature/Voltage and Entered Text
- >>Long will cycle through all 8 displays
- >>Rand will cycle through: Temperature/Voltage and a
random saying (Murphy's Law).
- Any other text will be displayed.
/*
The MIT License (MIT)
Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
Copyright (c) 2018 by Fabrice Weinberg
See complete copyright notice at the bottom of the
file
Modified from the demo program by the above authors by Deid
Reimer (Jan 2019) to:
- Simplify to the specific application
- Add wifi and web server
- Add temperature and voltage
- Add request and display Murphy saying e.g.:
"Real
programmers don't comment their code. If it was hard to
write it should
be hard to
understand."
*/
// Include wifi web server and web client libraries
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
// Include DS18B20 temperature sensor libraries.
#include <OneWire.h>
#include <DallasTemperature.h>
// Include the display library and custom images
#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"`
#include "images.h"
// Definitions and initialization
// Read battery voltage on ADC.
ADC_MODE(ADC_VCC);
// Temperature data wire is connected to D6/GPIO 12
#define ONE_WIRE_BUS D6
// Setup a oneWire instance to communicate with any OneWire
devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// and pass our oneWire instance reference to the Dallas
Temperature routine
DallasTemperature DS18B20(&oneWire);
// Create variables to hold the temperature and voltage
measurements
char temperatureCString[8];
char voltageCString[8];
// Create a variable type to hold the display function addresses
typedef void (*Demo)(void);
// Delay time. This will be changed by each display
function.
int delayNow = 5;
// Which of the n functions is current
int demoMode = 0;
// Text from the web form
String inputText;
// Which of the several display lists choosen by >>...
is current
int displayType = 2;
// Break out of delay loop when true.
bool doBreak = false;
// Instantiate and tell the web server to listen on port 80
ESP8266WebServer server(80);
// Initialize the OLED display using Wire library
// 0x3C is the display address
// D3 is SDA - data line
// D5 is SCL - clock line
SSD1306Wire display(0x3c, D3, D5);
// -----------------------------------------
// Wifi and web functions
// Convert IP to String.
String ipToString(IPAddress ip) {
String ips = String(ip[0]) + "." + String(ip[1]) + "." +
String(ip[2]) + "." + String(ip[3]);
return ips;
// Function to request an IP address.
bool getIP(IPAddress ip, IPAddress gateway, IPAddress subnet,
char* ssid, char* password) {
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
WiFi.disconnect();
WiFi.config(ip, gateway, subnet);
WiFi.begin(ssid, password);
// Loop until a connection or 20 tries
int j = 0;
while (WiFi.status() != WL_CONNECTED and j < 20) {
delay(500);
Serial.print(j);
Serial.println(ssid);
display.clear();
display.drawString(0, 0, String(j));
display.drawString(0, 20, ssid);
display.display();
j++;
}
// Display the connection information if connected and
return status
if (WiFi.status() == WL_CONNECTED) {
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
display.clear();
display.drawString(0, 0, "IP address: ");
display.drawString(0, 15,
ipToString(WiFi.localIP()));
Serial.print("Connected to ");
Serial.println(ssid);
display.drawString(0, 30, "Connected to");
display.drawString(0, 45, ssid);
display.display();
delay(10000);
return true;
} else {
return false;
}
}
// Function to build amd display the web page.
void showPage() {
String webPage00 = "<html><head><meta
charset=\"UTF-8\"><meta name=viewport
content=\"width=device-width,
initial-scale=1.5\"><title>OLDisplay</title>";
String webPage000 = "<meta name = \"viewport\" content =
\"width = device-width, initial-scale = 1.0, maximum-scale = 1.0,
user-scalable=0\">";
String webPage01 = "</head><body>";
String webPage0 = "<h3>Message for OLED
...</h3>";
String webPage02 = "<FORM METHOD=\"get\"
action=\"/getForm\"> <input type=\"text\"
name=\"getText\">";
String webPage03 = "<input type=\"submit\"
value=\"Submit\"></form>" ;
String webPage99 = "</body></html>";
String webPage = webPage00 + webPage000 + webPage01 +
webPage0 + webPage02 + webPage03 + webPage99;
server.send(200, "text/html", webPage);
Serial.println("sent new page");
delay(2000);
}
// Function to get the data from the web form
void handleForm() {
showPage();
doBreak = true;
String formText = server.arg("getText");
if (formText.length() >=150) {
formText = formText.substring(0,149);
}
// Check for short/long command, or just new text.
if (formText == ">>Short") {
displayType = 1;
demoMode = 0;
} else if (formText == ">>Long") {
displayType = 2;
demoMode = 0;
} else if (formText == ">>Rand") {
displayType = 3;
demoMode = 0;
} else {
inputText = formText;
demoMode = 1;
}
Serial.println("Text received. Contents: ");
Serial.println(formText);
Serial.println(inputText);
delay(2);
}
//
------------------------------------------------------------
// Oled display functions
Demo longDemos[] = {drawTempVolt, drawFontFaceDemo,
drawTextFlowDemo, drawMurphy, drawTextAlignmentDemo, drawRectDemo,
drawCircleDemo, drawProgressBarDemo, drawImageDemo};
Demo shortDemos[] = {drawTempVolt, drawTextFlowDemo};
Demo randDemos[] = {drawTempVolt, drawMurphy};
int longDemoLength = (sizeof(longDemos) / sizeof(Demo));
int shortDemoLength = (sizeof(shortDemos) / sizeof(Demo));
int randDemoLength = (sizeof(randDemos) / sizeof(Demo));
//Get and display a murphy saying
void drawMurphy() {
HTTPClient http;
http.begin("http://drsol.com/~deid/murphy/murphy.php");
int stat = http.GET();
if (stat > 0) {
String text = http.getString();
delayNow = 10;
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawStringMaxWidth(0, 0, 128, text);
} else {
display.setFont(ArialMT_Plain_16);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawStringMaxWidth(0, 0, 128, "Oops -
No Web!");
}
http.end();
}
// Display temperature and voltage.
void drawTempVolt() {
delayNow = 3;
float tempC;
int battVolt;
//float tempF;
// Loop until the temperature is on out of range
do {
DS18B20.requestTemperatures();
tempC = DS18B20.getTempCByIndex(0);
delay(1000);
} while (tempC == (-127.0));
tempC = tempC + 1;
dtostrf(tempC, 6, 2, temperatureCString);
// tempF = DS18B20.getTempFByIndex(0);
// dtostrf(tempF, 6, 2, temperatureFString)
String t = temperatureCString;
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, t + " C");
int voltage = analogRead(A0);
float v = voltage / 65536.0 * 3.3;
Serial.println (v);
display.drawString(16, 18, String(v) + " V");
}
// Display different font sizes
void drawFontFaceDemo() {
delayNow = 5;
// create more fonts at http://oleddisplay.squix.ch/
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
display.drawString(0, 0, "Hello PiMakers");
display.setFont(ArialMT_Plain_16);
display.drawString(0, 10, "Hello World");
display.setFont(ArialMT_Plain_24);
display.drawString(0, 26, "Nice Day!");
}
// Display the text retrieved from the "web"
void drawTextFlowDemo() {
delayNow = 9;
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawStringMaxWidth(0, 0, 128, inputText);
}
// Display text in different horizontal alignments
void drawTextAlignmentDemo() {
delayNow = 5;
// Text alignment demo
display.setFont(ArialMT_Plain_10);
// The coordinates define the left starting point of the
text
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 10, "Left aligned (0,10)");
// The coordinates define the center of the text
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(64, 22, "Center aligned (64,22)");
// The coordinates define the right end of the text
display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.drawString(128, 33, "Right aligned (128,33)");
}
// Display drawing on the screen - a rectangle.
void drawRectDemo() {
delayNow = 5;
// Draw a pixel at given position
for (int i = 0; i < 10; i++) {
display.setPixel(i, i);
display.setPixel(10 - i, i);
}
display.drawRect(12, 12, 20, 20);
// Fill the rectangle
display.fillRect(14, 14, 17, 17);
// Draw a line horizontally
display.drawHorizontalLine(0, 40, 20);
// Draw a line vertically
display.drawVerticalLine(40, 0, 20);
}
// Display a couple of circles.
void drawCircleDemo() {
delayNow = 5;
for (int i = 1; i < 8; i++) {
display.setColor(WHITE);
display.drawCircle(32, 32, i * 3);
if (i % 2 == 0) {
display.setColor(BLACK);
}
display.fillCircle(96, 32, 32 - i * 3);
}
}
// Display a progress bar
void drawProgressBarDemo() {
int counter = 1;
int progress;
delayNow = 0;
while (counter < 100) {
display.clear();
progress = (counter) % 100;
// draw the progress bar
display.drawProgressBar(0, 32, 120, 10,
progress);
// draw the percentage as String
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(64, 15, String(progress) +
"%");
display.display();
// Count for the progress bar
counter++;
delay(60);
Serial.println(counter);
}
}
// Display an image.
void drawImageDemo() {
delayNow = 5;
// see
http://blog.squix.org/2015/05/esp8266-nodemcu-how-to-create-xbm.html
// on how to create xbm files
// display.drawXbm(34, 14, WiFi_Logo_width,
WiFi_Logo_height, WiFi_Logo_bits);
display.drawXbm(34, 14, noobs_width, noobs_height,
noobs_bits);
}
//
-----------------------------------------------------------
// Setup
void setup() {
// Reserve space for the web form input variable
inputText.reserve(150);
inputText = "There is nothing to see here yet";
// Set up serial interface
Serial.begin(9600);
Serial.println();
// Initialise the UI, this will init the display too.
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
delay(500);
// Connect to WiFi. Try each Access Point
below and give up if none.
WiFi.mode(WIFI_STA);
//bool stat = getIP ({0,0,0,0},{0,0,0,0},{0,0,0,0},
"Steele", "Piwehavelotsof.");
bool stat = getIP ({10, 10, 45, 10}, {10, 10, 45, 254},
{255, 255, 255, 0}, "Steele", "verysecret");
if (!stat) {
Serial.println("try makiki");
stat = getIP ({0, 0, 0, 0}, {0, 0, 0, 0}, {0,
0, 0, 0}, "Makiki", "secret");
} if (!stat) {
Serial.println("try lalala6");
stat = getIP ({192, 168, 78, 39}, {192, 168,
78, 1}, {255, 255, 255, 0}, "lalala6", "mostlysecret");
} if (!stat) {
Serial.println("try lalala");
stat = getIP ({192, 168, 0, 39}, {192, 168, 0,
1}, {255, 255, 255, 0}, "lalala", "hopefully secret");
}
if (!stat) {
// Continue without an an internet connection.
Serial.println("Continuing without IP");
display.clear();
display.drawString(0, 10, "No IP");
display.display();
delay(5000);
}
// Start the web server.
server.begin();
// Set up the responder for the web request.
server.on("/getForm", handleForm);
server.on("/", showPage);
//server.onNotFound(showPage);
}
//-----------------------------------
// Loop
void loop() {
// Look for and handle a web request.
server.handleClient();
// Create a display and show it.
display.clear();
// Choose which set of displays to run one of.
if ( displayType == 1) {
shortDemos[demoMode]();
demoMode = (demoMode + 1) %
shortDemoLength;
} else if (displayType == 2) {
longDemos[demoMode]();
demoMode = (demoMode + 1) %
longDemoLength;
} else if (displayType == 3) {
randDemos[demoMode]();
demoMode = (demoMode +1) % randDemoLength;
}
display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.display();
// Delay for a while, but break up the delay so that web
requests are handled
// in a reasonable length of time
int delaySlice = delayNow * 100;
int j = 0;
while (++j <= 10) {
server.handleClient();
delay(delaySlice);
if (doBreak) {
doBreak = false;
break;
}
}
}
/**
The MIT License (MIT)
Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
Copyright (c) 2018 by Fabrice Weinberg
Permission is hereby granted, free of charge, to any
person obtaining a copy
of this software and associated documentation files
(the "Software"), to deal
in the Software without restriction, including
without limitation the rights
to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is
furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE
SOFTWARE.
ThingPulse invests considerable time and money to
develop these open source libraries.
Please support us by buying our products (and not the
clones) from
https://thingpulse.com
*/
Then I added Time: