Skip to content

10. Output Devices

Group Work

OLED

OLED Display

A 1.3-inch OLED display was used in this project and identified as using the SH1106 controller. It worked correctly with the Adafruit SH110X library, while the SSD1306 library produced incorrect output such as noise and distortion.

Library

A library in embedded programming is a collection of pre-written code that simplifies interaction with hardware components. Libraries reduce development time, minimize errors, and make code more readable.

I used the following libraries for the I2C OLED Display:

  • <Adafruit_GFX.h>: Provides basic drawing functions such as lines, rectangles, circles, triangles, and text rendering.
  • <Adafruit_SH110X.h>: Simplifies controlling SH1106 or SH1107 OLED displays with Arduino.

Testing OLED Properties

// Include required libraries
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

// Display configuration
#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 64

// Create display object
Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);
  delay(2000);  // Wait for Serial Monitor

  Serial.println("=== SH1106 OLED Properties ===");

  // Initialize I2C (SDA = 6, SCL = 7)
  Wire.begin(6, 7);

  // Initialize display
  if (!display.begin(0x3C, true)) {
    Serial.println("SH1106 OLED not found!");
    while (1);  // Halt execution
  }

  Serial.println("OLED detected successfully!");

  // Test drawing on OLED
  display.clearDisplay();
  display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SH110X_WHITE); // border
  display.drawLine(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, SH110X_WHITE); // diagonal
  display.setTextSize(1);
  display.setCursor(0, SCREEN_HEIGHT - 10);
  display.println("Bottom Text Test");
  display.display();

  Serial.println("Check OLED for rectangle, diagonal line, and bottom text");
}

void loop() {
  // Nothing to run continuously
}

Results Example:

=== SH1106 OLED Properties ===
OLED detected successfully!
Screen Width: 128
Screen Height: 64
I2C Address: 0x3C
Text color constant: 1
Max Cursor X: 127
Max Cursor Y: 63
=== Test drawing functions ===
Check OLED for rectangle, diagonal line, and bottom text

OLED Test Result


Display Properties on OLED

// Include required libraries
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 64
Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);
  delay(2000);
  Wire.begin(6, 7);

  if (!display.begin(0x3C, true)) {
    Serial.println("OLED not found!");
    while (1);
  }

  Serial.println("OLED detected successfully!");
  display.clearDisplay();
  display.setTextColor(SH110X_WHITE);
  display.setTextSize(1);

  int y = 0;
  display.setCursor(0, y); display.println("Screen Properties:"); y += 8;
  display.setCursor(0, y); display.print("Width: "); display.println(SCREEN_WIDTH); y += 8;
  display.setCursor(0, y); display.print("Height: "); display.println(SCREEN_HEIGHT); y += 8;
  display.setCursor(0, y); display.print("I2C Addr: "); display.println("0x3C"); y += 8;
  display.setCursor(0, y); display.print("Text Color: "); display.println(SH110X_WHITE); y += 8;
  display.setCursor(0, y); display.print("Max Cursor X: "); display.println(SCREEN_WIDTH - 1); y += 8;
  display.setCursor(0, y); display.print("Max Cursor Y: "); display.println(SCREEN_HEIGHT - 1); y += 8;
  display.setCursor(0, y); display.println("End of Properties");
  display.display();
}

void loop() {
  // Nothing to run continuously
}

OLED Properties Result


Simple Display Example

// Include required libraries
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 64
Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Example sensor values
float flowRate   = 2.5;  // L/min
int waterQuality = 78;   // %
int systemHealth = 85;   // %

void setup() {
  Serial.begin(115200);
  delay(2000);
  Wire.begin(6, 7);

  if (!display.begin(0x3C, true)) {
    Serial.println("OLED not found!");
    while (1);
  }
}

void loop() {
  display.clearDisplay();
  display.setTextColor(SH110X_WHITE);

  // Title
  display.setTextSize(2);
  display.setCursor(5, 0);
  display.println("H2O");
  display.drawLine(0, 20, SCREEN_WIDTH, 20, SH110X_WHITE);

  // Water Quality
  display.setTextSize(1);
  display.setCursor(0, 34);
  display.print("Qual:");
  display.setCursor(65, 34);
  display.print(waterQuality);
  display.println("%");

  // Footer
  display.setCursor(15, 58);
  display.println("System Active");

  display.display();
  delay(1000);
}

OLED Cheat Sheet

OLED Libraries

Cheat Sheet Reference

Output Turbidity readings

alt text

I used the code below

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Turbidity sensor pin
#define TURBIDITY_PIN D1

int turbidityPercent = 0;
int waterQuality = 0;

// ===== Function to stabilize readings =====
int readTurbidity() {
  long sum = 0;

  for (int i = 0; i < 10; i++) {
    sum += analogRead(TURBIDITY_PIN);
    delay(5);
  }

  return sum / 10; // average value
}

void setup() {
  Serial.begin(115200);
  delay(2000);

  Wire.begin(6, 7); // SDA, SCL

  if (!display.begin(0x3C, true)) {
    Serial.println("OLED not found!");
    while (1);
  }

  display.clearDisplay();
  display.setTextColor(SH110X_WHITE);
}

void loop() {
  // ===== READ SENSOR (STABLE) =====
  int rawValue = readTurbidity();

  // ===== MAP VALUES (ADJUSTABLE) =====
  turbidityPercent = map(rawValue, 1000, 3000, 100, 0);
  turbidityPercent = constrain(turbidityPercent, 0, 100);

  // Water quality = same as turbidity scale (clean = high)
  waterQuality = turbidityPercent;

  // ===== SERIAL DEBUG =====
  Serial.print("Raw: "); Serial.print(rawValue);
  Serial.print(" | Turbidity: "); Serial.print(turbidityPercent);
  Serial.print("% | Quality: "); Serial.print(waterQuality);
  Serial.println("%");

  // ===== OLED DISPLAY =====
  display.clearDisplay();

  // Title
  display.setTextSize(2);
  display.setCursor(25, 0);
  display.println("H2O");

  display.drawLine(0, 20, SCREEN_WIDTH, 20, SH110X_WHITE);

  // Data
  display.setTextSize(1);

  display.setCursor(0, 25);
  display.print("Turb:");
  display.setCursor(85, 25);
  display.print(turbidityPercent);
  display.print("%");

  display.setCursor(0, 38);
  display.print("Qual:");
  display.setCursor(85, 38);
  display.print(waterQuality);
  display.print("%");

  display.setCursor(0, 51);
  display.print("Status:");
  display.setCursor(85, 51);

  if (waterQuality > 75) display.print("GOOD");
  else if (waterQuality > 40) display.print("OK");
  else display.print("BAD");

  display.display();

  delay(1000);
}