Now that we've successfully read temperature, humidity, and air pressure from a BME280, we turn to the problem of making this data available without having to use a serial monitor. Our first solution is to use a tiny OLED display. In this tutorial we will: Install the Correct Library Add the Display to the Breadboard Test the Display Show Sensor Data in the Display Install the Correct Library A wide variety of tiny OLED displays are available, and for this tutorial we'll be using a 0.96 inch, monochrome, 128 x 64 pixel screen that is driven by the SSD1306, and that has an I2C interface. As it goes, this device has I2C address 0x3c. There are several libraries for the SSD1306, and we will use the one entitled "ESP8266 and ESP32 Oled Driver for SSD1306 display by Daniel Eichhorn, Fabrice Weinberg". To install this library: In the Arduino IDE, choose the menu Sketch | Include Library | Manage Libraries... Enter SSD1306, click the right one, and install the latest version of that library (currently version 3.2.7). Add the Display to the Breadboard Along the top of the display there will be four pins that read something like GND, VCC, SCL, and SDA or GND, VDD, SCK, and SDA First disconnect the BME280, then wire the display as follows: ESP8266 <--> OLED 3V3 <--> VCC GND <--> GND SCL <--> D5 SDA <--> D6 If there isn't room on the breadboard to add the display, either use a full-size breadboard or use a second half-sized breadboard! Test the Display Ignoring the BME280 for a minute, the following sketch tests the features we will be using when we display data from the BME280. The library works as follows: We initialize it in the setup() function, and we flip the screen vertically. The end result is to create a memory buffer Drawing commands will be written to this buffer - they will NOT be immediately visible When we are ready, write the buffer to the display using the command: display.display(); We will be using the following commands in the final sketch: display.setFont(fontName); display.drawString(x, y, message); display.display(); display.clear(); There are many other commands in this library - check out the sample code! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 /* * Simple-OLED-Test * * By: Mike Klepper * Date: 29 March 2017 * * This program demonstrates a VERY few simple commands from the * "ESP8266 Oled driver library for SSD1306 display" library * by Daniel Eichhorn, Fabrice Weinberg. * * Connections: * Display VCC --> NodeMCU 3V3 * Display GND --> NodeMCU GND * Display SCL --> NodeMCU D5 * Display SDA --> NodeMCU D6 */ #include "SSD1306.h" SSD1306 display(0x3c, D6, D5); void setup() { display.init(); display.flipScreenVertically(); } void loop() { display.clear(); display.drawRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); display.setFont(ArialMT_Plain_16); display.drawString(20, 7, "Hello, world!"); display.setFont(ArialMT_Plain_10); display.drawString(8, 30, "DISPLAY_WIDTH = " + String(DISPLAY_WIDTH)); display.drawString(8, 45, "DISPLAY_HEIGHT = " + String(DISPLAY_HEIGHT)); display.display(); yield(); delay(2000); } 18 Include the library we downloaded earlier 20 Create a display with I2C address 0x3c, the SDA connected to D6, and the SCL connected to D5 24 Initialize the display (this creates the buffer) 25 Change the orientation of the display 30 Clear the buffer 32 Draw a border around the screen - notice that the library makes two constants available to us: DISPLAY_WIDTH and DISPLAY_HEIGHT 34 Set the font we'll be using. 35 Print "Hello, world!" at x = 20 and y = 7 37 Change font to ArialMT_Plain_10 38 - 39 Print the screen width - note that this value is available in the constants DISPLAY_WIDTH and DISPLAY_HEIGHT 41 Copy the buffer to the physical display 43-44 Wait for a bit before doing it all again The library includes three fonts: ArialMT_Plain_10, ArialMT_Plain_16, and ArialMT_Plain_24. Additional fonts can be created using the tools found at: http://oleddisplay.squix.ch/#/home https://github.com/squix78/esp8266-oled-ssd1306-font-converter Show Sensor Data on the Display Now we will show the temperature, humidity and barometric pressure on the display. To make this a little more interesting, we will alternate showing British units and metric units. You would think that pulling this off would be simply a matter combining the above code with the sketch from the last tutorial - after all, there is no pin overlap, right? As it goes, restoring the jumper wires as follows WILL NOT WORK! The ESP8266 has exactly one I2C bus, so the two devices (the BME280 and the OLED display) must be on that one I2C bus! Here's what the connections will look like on a full-sized breadboard. Once the connections are correct, the code is very easy! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 /** * BME280-OLED * * By: Mike Klepper * Date: 31 March 2017 * * This program reads data from the BMP280 and shows it on a * SSD1306 OLED display. It will alternte between British and * metric units. * * See blog post on patriot-geek.blogspot.com * for connections. */ #include "Wire.h" #include "Adafruit_Sensor.h" #include "Adafruit_BME280.h" #include "SSD1306.h" const float SEA_LEVEL_PRESSURE_HPA = 1013.25; const int DELAY = 3000; const int STARTUP_DELAY = 500; Adafruit_BME280 bme; SSD1306 display(0x3c, D6, D5); void setup() { Serial.begin(115200); if(!bme.begin()) { Serial.println("Could not find a valid BME280 sensor, check wiring!"); while (1) { yield(); delay(DELAY); } } delay(STARTUP_DELAY); display.init(); display.flipScreenVertically(); } void loop() { float tempC = bme.readTemperature(); float humidity = bme.readHumidity(); float pressurePascals = bme.readPressure(); // Print to serial monitor printToSerial(tempC, humidity, pressurePascals); // Display data on screen in British units drawWithBritishUnits(tempC, humidity, pressurePascals); yield(); delay(DELAY); // Display data on screen in metric units drawWithMetricUnits(tempC, humidity, pressurePascals); yield(); delay(DELAY); } void drawWithBritishUnits(float tempC, float humidity, float pressurePascals) { float tempF = 9.0/5.0 * tempC + 32.0; float pressureInchesOfMercury = 0.000295299830714 * pressurePascals; display.clear(); display.drawRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); display.setFont(ArialMT_Plain_16); display.drawString(35, 3, "BME280"); display.setFont(ArialMT_Plain_10); display.drawString(5, 22, "Temperature = " + String(tempF) + " *F"); display.drawString(5, 35, "Humidity = " + String(humidity) + "%"); display.drawString(5, 48, "Pressure = " + String(pressureInchesOfMercury) + " inHg"); display.display(); } void drawWithMetricUnits(float tempC, float humidity, float pressurePascals) { float pressureHectoPascals = pressurePascals / 100.0; display.clear(); display.drawRect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); display.setFont(ArialMT_Plain_16); display.drawString(35, 3, "BME280"); display.setFont(ArialMT_Plain_10); display.drawString(5, 22, "Temperature = " + String(tempC) + " *C"); display.drawString(5, 35, "Humidity = " + String(humidity) + "%"); display.drawString(5, 48, "Pressure = " + String(pressureHectoPascals) + " h,Pa"); display.display(); } void printToSerial(float tempC, float humidity, float pressurePascals) { // Temperature float tempF = 9.0/5.0 * tempC + 32.0; Serial.println("Temperature:"); printValueAndUnits(tempC, "*C"); printValueAndUnits(tempF, "*F"); //printValueAndUnits(tempC, "°C"); //printValueAndUnits(tempF, "°F"); Serial.println(""); // Barometric pressure float pressureHectoPascals = pressurePascals / 100.0; float pressureInchesOfMercury = 0.000295299830714 * pressurePascals; Serial.println("Pressure:"); printValueAndUnits(pressurePascals, "Pa"); printValueAndUnits(pressureHectoPascals, "hPa"); printValueAndUnits(pressureInchesOfMercury, "inHg"); Serial.println(""); // Humidity Serial.println("Humidity:"); printValueAndUnits(humidity, "%"); Serial.println(""); // Approximate altitude float altitudeMeters = bme.readAltitude(SEA_LEVEL_PRESSURE_HPA); float altitudeFeet = 3.28 * altitudeMeters; Serial.println("Approx. Altitude:"); printValueAndUnits(altitudeMeters, "m"); printValueAndUnits(altitudeFeet, "ft"); Serial.println(); } void printValueAndUnits(float value, String units) { Serial.print(" "); Serial.print(value); Serial.print(" "); Serial.println(units); } This completes our attempt to display sensor data using hardware. Although we were successful, we did not use the WiFi capabilities of the ESP8266! That's what the next tutorial will be about!