Lesson 7: OLED Display
Present data to a display
Pre-requisites:
- It is recommended that you have successfully completed all the previous lessons
Objectives:
- Breadboard the final circuit with an oLED
- Create a device that logs data such as pressure, altitude and temperature and displays onto a oLED display.
What you will be using:
What you will be learning:
- How to connect multiple different sensors or devices to the Arduino at the same time
- How to write to an oLED display
- Connecting multiple I2C modules
- Putting together all of the other lessons in order to make a final product
Wiring all the sensors and devices to the Arduino
- Remember you do not have to use the same color of jumper wire as this, but insure that your connections are the same.
- In this lesson, we will be sharing the A4/A5 wires as the devices are I2C. Take note of the common wire up.
- Unplug the Arduino from the computer while you are wiring it up
Wiring the Arduino to the Breadboard
Module/Controller Pin |
BB/Arduino Pins |
oLED Display |
|
GND |
BB Ground (-) |
VCC |
BB Power (+) |
SCL |
Common SCL (Arduino A5) |
SDA |
Common SDA (Arduino A4) |
GPS Sensor |
|
VCC |
BB Power (+) |
GND |
BB Ground (-) |
PPS |
N/A |
TXD |
3 |
RXD |
4 |
Pressure Temperature Sensor |
|
VIN |
BB Power (+) |
GND |
BB Ground (-) |
SCL |
Common SCL (Arduino A5) |
SDA |
Common SDA (Arduino A4) |
Arduino |
|
5V |
BB Power (+) |
GND |
BB Ground (-) |
Full wire up
Common SCL/SDA
The BMP180 and oLED Display will share the SCL/SDA A5/A4 spot on the Arduino. I2C addresses are used to differentiate between the two modules.
Validate Libraries
Make sure that all the libraries below are installed in the IDE. Without these libraries the code below will not function and will error out.
- Adafruit bmp085 library
- BusIO
- TinyGPSPlus
NOTE: A new library is needed for this build. Install Adafruit SSD1306
library through the Arduino IDE by going to Sketch -> Include Library -> Manage Libraries -> then search for Adafruit SSD1306
. Install the depending Adafruit GFX
library as well.
Working Code - Copy and paste this into your sketch
```java
#include
#include "Adafruit_BMP085.h"
#include
#include
#include
#include
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library.
// On an arduino UNO: A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO: 2(SDA), 3(SCL), ...
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int chipSelect = 10;
const bool bypassGPS = true;
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps;
// map software serial to gps
SoftwareSerial serialgps(TXPin, RXPin);
Adafruit_BMP085 bmp;
void setup() {
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
//Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
bmp.begin();
serialgps.begin(GPSBaud);
delay(2000);
if (!serialgps.available()) {
//Serial.println(F("initialization failed"));
for(;;);
}
}
void loop() {
// make a string for assembling the data to log:
String dataString = "";
bool gpsready = false;
float lat = 0;
float lng = 0;
unsigned long start = millis();
do
{
while (serialgps.available()>0) {
char c;
c=serialgps.read();
gps.encode(c);
}
} while (millis() - start < 5000);
float c = bmp.readTemperature(); // Variable for holding temp in C
float f = c*1.8 + 32.; // Variable for holding temp in F
//float pressure = bmp.readPressure()/3386.3887; //pascals to in of mercury
float p = bmp.readPressure(); //pascals
if ((gps.location.age() < 1000 || gps.location.isUpdated()) && gps.location.isValid()) {
if (gps.satellites.isValid() && (gps.satellites.value() >= 3)) {
lat = gps.location.isValid() ? gps.location.lat() : 0;
lng = gps.location.isValid() ? gps.location.lng() : 0;
gpsready = true;
}
}
if (gpsready || bypassGPS) {
// Clear the buffer
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.print(F("Temperature: "));
display.print(f);
display.print(F(" F"));
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0,9); // Start at top-left corner
display.print(F("Pressure: "));
display.print(p);
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0,18); // Start at top-left corner
display.print(F("Lat: "));
display.print(String(lat, 6));
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0,27); // Start at top-left corner
display.print(F("Lng: "));
display.print(String(lng, 6));
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0,36); // Start at top-left corner
display.print(F("Altidtude: "));
display.print(String((long)gps.altitude.feet(), 6));
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0,45); // Start at top-left corner
display.print(F("Satellites: "));
display.print(String((int)gps.satellites.value()));
// Show the display buffer on the screen. You MUST call display() after
// drawing commands to make them visible on screen!
display.display();
}
delay(2000);
}
```
</details>
## Want more?
If you have finished with the base lesson, check out the items below.
Things to think about, validate, and/or try:
* Is the data being written out correct? 🤔
* What are some things you could do to test all the modules at once?
* Change the order/format of the output display data to your liking.
* Load the demo display code to see the full power of the oLED! 😵 (File > Adafruit SSD1306 > ssd1306_128x64_i2c)
(***HINT:*** Change the ```SCREEN_ADDRESS``` to ```0x3C```)
## Challenge
If you have finished with the extension lesson questions, check out the challenge below.
Create you own custom image, load it into a byte array, and display your image on the the oLED. [External walkthrough here!](https://www.instructables.com/How-to-Display-Images-on-OLED-Using-Arduino/) 🐧 Make sure that the image is appropriate in both size, scale, color...and taste. 😅
Try to write the code on your own. If you get stuck or need some inspiration expand this section.
```java
#include
#include
#include
#include
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library.
// On an arduino UNO: A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO: 2(SDA), 3(SCL), ...
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define LOGO_HEIGHT 16
#define LOGO_WIDTH 16
// 'RickAndMorty', 128x64px
const unsigned char epd_bitmap_RickAndMorty [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0xf0, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x9c, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x0c, 0x14, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x82, 0x42, 0x00, 0x00, 0x10, 0x00, 0x00,
0x21, 0x04, 0x14, 0x80, 0x12, 0x00, 0x00, 0x00, 0x00, 0x82, 0x42, 0x00, 0x00, 0x20, 0x00, 0x00,
0x21, 0x06, 0x14, 0x80, 0x12, 0x00, 0x00, 0x00, 0x01, 0x02, 0x42, 0x00, 0x00, 0x48, 0x00, 0x00,
0x21, 0x02, 0x04, 0x80, 0x12, 0x0c, 0x00, 0x00, 0x01, 0x02, 0x42, 0x00, 0x00, 0x50, 0x00, 0x00,
0x12, 0x02, 0x04, 0x80, 0x12, 0x18, 0x00, 0x00, 0x01, 0x23, 0xc3, 0x00, 0x00, 0xd0, 0x00, 0x00,
0x10, 0x86, 0x23, 0x80, 0x12, 0x24, 0x00, 0x00, 0x01, 0x23, 0x81, 0x00, 0x7c, 0x90, 0x00, 0x00,
0x10, 0x84, 0x23, 0x80, 0x13, 0x74, 0x00, 0x00, 0x01, 0x21, 0x01, 0x09, 0x62, 0x80, 0x00, 0x00,
0x10, 0x84, 0x20, 0x87, 0xf3, 0xc8, 0x00, 0x01, 0x02, 0x21, 0x31, 0x1f, 0x43, 0xb1, 0x40, 0x00,
0x10, 0x8c, 0xc4, 0x88, 0x33, 0x10, 0x18, 0x05, 0x02, 0x31, 0x3d, 0x23, 0x03, 0xd1, 0x40, 0x00,
0x10, 0x58, 0x44, 0xda, 0x62, 0x30, 0x28, 0x05, 0x02, 0x31, 0x39, 0xc1, 0x21, 0x91, 0x20, 0x00,
0x00, 0x70, 0x44, 0xe1, 0xe0, 0x20, 0x2c, 0x3d, 0x02, 0x3d, 0x19, 0xc1, 0x11, 0x11, 0x20, 0x00,
0x00, 0x20, 0x84, 0xe1, 0xe0, 0x20, 0x67, 0xdd, 0x02, 0x39, 0x10, 0x81, 0x31, 0x3b, 0x20, 0x00,
0x08, 0x01, 0x04, 0xf2, 0x20, 0xc0, 0x44, 0xd9, 0x02, 0x39, 0x10, 0xd1, 0x11, 0x3f, 0x20, 0x00,
0x08, 0x03, 0x04, 0xe6, 0x21, 0x80, 0x74, 0xd9, 0x02, 0x29, 0x30, 0x11, 0x01, 0x07, 0x30, 0x00,
0x08, 0x03, 0x04, 0x4c, 0x31, 0x80, 0x14, 0x19, 0x02, 0x2c, 0x30, 0x3d, 0x0e, 0x01, 0x10, 0x00,
0x04, 0x01, 0x04, 0x44, 0x30, 0x80, 0xcc, 0x11, 0x02, 0x24, 0x30, 0x31, 0x8f, 0x21, 0x30, 0x00,
0x04, 0x00, 0xc6, 0x44, 0x30, 0xc0, 0xc4, 0x01, 0x02, 0x24, 0x30, 0x30, 0x07, 0x3d, 0x00, 0x00,
0x04, 0x40, 0xe0, 0x0f, 0xf0, 0x40, 0x80, 0x01, 0x04, 0x44, 0x39, 0x98, 0x07, 0x3f, 0x08, 0x1c,
0x04, 0x70, 0x22, 0x48, 0xb2, 0x20, 0x90, 0x09, 0x04, 0x44, 0xf1, 0x00, 0x27, 0x21, 0x08, 0x24,
0x04, 0x78, 0x12, 0x40, 0x36, 0x50, 0xb0, 0x81, 0x04, 0x46, 0x49, 0x01, 0x23, 0x21, 0x08, 0x4c,
0x04, 0xce, 0x1a, 0xc0, 0x7f, 0x10, 0x30, 0x91, 0x04, 0x42, 0x48, 0x81, 0x33, 0x20, 0x8d, 0x88,
0x04, 0x03, 0x0e, 0xe1, 0xf7, 0x10, 0xbb, 0xe4, 0x04, 0x42, 0x48, 0xe3, 0x33, 0x20, 0xcf, 0x10,
0x04, 0x01, 0x0e, 0xe7, 0x25, 0x00, 0xaa, 0x3c, 0x04, 0x81, 0x4c, 0xff, 0x3b, 0x20, 0x84, 0x20,
0x04, 0x40, 0xc6, 0x96, 0x24, 0x88, 0x00, 0x07, 0x04, 0x81, 0x84, 0x80, 0xcb, 0x20, 0x80, 0xc0,
0x04, 0x40, 0x62, 0x94, 0x28, 0x88, 0x00, 0x00, 0x04, 0x80, 0x04, 0x80, 0x0b, 0x00, 0x83, 0x80,
0x04, 0x40, 0x23, 0x80, 0x28, 0x48, 0x00, 0x00, 0x04, 0x80, 0x04, 0x80, 0x09, 0x40, 0x81, 0x00,
0x00, 0x20, 0x11, 0x00, 0x10, 0x48, 0x00, 0x00, 0x04, 0x80, 0x04, 0x80, 0x01, 0x40, 0xca, 0x00,
0x02, 0x20, 0x08, 0x80, 0x00, 0x48, 0x00, 0x00, 0x04, 0x80, 0x04, 0x80, 0x07, 0x41, 0x8c, 0x00,
0x02, 0x20, 0x0c, 0x80, 0x00, 0x34, 0x00, 0x00, 0x04, 0x80, 0x04, 0xc0, 0x03, 0x43, 0x88, 0x00,
0x01, 0x20, 0x06, 0x80, 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x02, 0x40, 0x00, 0x06, 0x10, 0x00,
0x01, 0x20, 0x02, 0x40, 0x00, 0x28, 0x00, 0x00, 0x01, 0x00, 0x03, 0x40, 0x00, 0x04, 0x30, 0x00,
0x01, 0x20, 0x02, 0x40, 0x00, 0x18, 0x00, 0x00, 0x01, 0x00, 0x01, 0x40, 0x00, 0x0c, 0x60, 0x00,
0x01, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x08, 0xc0, 0x00,
0x01, 0x40, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x60, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void setup() {
Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
//display.display();
//delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
display.drawBitmap(0, 0, epd_bitmap_RickAndMorty, 128, 64, WHITE);
display.display();
}
void loop() {
}
```
</details>
### Review
- Learned how to connect multiple different sensors or devices to the Arduino at the same time
- Breadboarding circuits
- How to display to an oLED Display
- Put all of the other lessons together in order to make a final product
### Trouble shooting
- Unplug/reset the Arduino and check all of the connections and try running it again
- GPS not reading coordinates is likely caused by obstruction of the signal so moving outside may be necessary
- Validate that all libraries are installed for use (BMP180 and GPS)
- No display change? GPS never initialized and code is stuck. Validate GPS is setup correctly.