- Compare character LCD and graphical OLED displays.
- Wire a verified I²C display to Uno R3.
- Install the display and graphics libraries.
- Explain a display buffer and refresh operation.
- Label sensor values honestly and troubleshoot a blank screen.
Before you begin
Use the working LDR divider from ARD05. This lesson requires the specified Adafruit display; generic OLED modules may need different voltage, pins, address or controller library.
A dashboard translates data for a reader
Serial Monitor is useful at a workbench, but a sensor project may need to show its state without a computer. A display turns internal measurements into information that a person can inspect. The design question is not only whether text appears, but whether the reader knows what it means.
A character LCD commonly presents a fixed grid of characters, such as two rows of sixteen. A graphical OLED controls individual pixels, allowing text and simple shapes. OLED pixels emit light, while many LCD modules use a backlight. Neither display type makes a measurement more accurate.
We will show one large numerical reading with the explicit label Raw light. The number remains ADC counts, not lux or a percentage of scientifically defined brightness. Clear units and status messages prevent a polished interface from exaggerating what a prototype measures.
Choose the exact display and wire it
The reference is the Adafruit 0.91-inch 128×32 SSD1306 I²C OLED breakout, product 931, with its documented regulator and level shifting. It is not a bare OLED panel or an SH1106 module. Review the manufacturer’s wiring guide before connecting another revision.
Disconnect USB. Connect display VIN to Uno 5V, GND to GND, SDA to A4, SCL to A5 and RST to D4. If the breakout has an additional unused pin, leave it unconnected according to the board’s own labelled diagram. Do not substitute a generic board’s VCC rating for this breakout’s VIN rating.
Retain the LDR divider: 5V → LDR → A0 junction → 10 kΩ → GND. The display and sensor share ground. Power the complete small circuit from USB, with no motor supply attached. Headers must be properly soldered or supplied preassembled; loose header pins are unreliable electrical contacts.
| Part | Purpose |
|---|---|
| Uno R3 with USB cable | Controller and power |
| Adafruit product 931, 128×32 SSD1306 I²C OLED | Dashboard |
| LDR and 10 kΩ resistor | Light divider feeding A0 |
| Breadboard and jumpers | A4 SDA, A5 SCL, D4 reset connections |
Load the libraries and draw the reading
In Arduino IDE Library Manager install Adafruit SSD1306 and Adafruit GFX Library, accepting their declared dependencies. Wire is the Arduino I²C library supplied with the board package. SSD1306 speaks to the display controller; GFX provides text and drawing operations.
Upload this Arduino C/C++ sketch. Its selected address, 0x3C, matches the specified 128×32 reference display. Hexadecimal notation represents a number; it is not a text password or an Internet address.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 screen(128, 32, &Wire, 4);
void setup() {
Serial.begin(9600);
if (!screen.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("Display allocation failed");
while (true) {}
}
screen.setTextColor(SSD1306_WHITE);
}
void loop() {
int reading = analogRead(A0);
screen.clearDisplay();
screen.setTextSize(1);
screen.setCursor(0, 0);
screen.print("Raw light: ADC counts");
screen.setTextSize(2);
screen.setCursor(0, 14);
screen.print(reading);
screen.display();
delay(250);
}The constructor specifies width, height, I²C connection and reset pin. begin() initializes the library and display. Drawing calls change a buffer in memory; display() transfers that buffer to the OLED. clearDisplay() removes the previous digits, preventing remnants when a number becomes shorter. The refresh occurs about four times per second.
Expected result: A label and raw number appear. Covering the LDR usually lowers the number for the specified divider orientation. A successful begin() alone does not prove that the screen is physically responding.
Memory and refresh rate matter
A monochrome 128×32 image contains 4,096 pixels. At one bit per pixel, its framebuffer occupies 512 bytes, before other program memory needs. On a small controller, a larger screen can consume a substantial part of available RAM. Avoid adding large images and long dynamic strings without checking memory use.
The program draws a whole frame in memory before transferring it. This separation helps avoid showing partially updated text. It also explains a common surprise: print() can run correctly while nothing changes onscreen if display() is never called.
Four updates per second is enough for this slow light indicator. Faster refresh uses more communication time and may cause visible flicker without making the sensor more useful. A motor-control loop should not depend on spending excessive time redrawing decorative elements.
A useful next addition is a state label such as Dark or Bright with thresholds derived in ARD05. Keep the raw value available during calibration. Once you hide all raw measurements behind a single cheerful icon, it becomes harder to explain incorrect decisions.
Bring the screen up in stages
First disconnect the sensor and verify a static test message using the library’s example for the exact 128×32 I²C display. Then reconnect the sensor with power off and upload the dashboard. Compare the display’s value with a serial version of the sensor reading before trusting the screen.
For a blank screen, check VIN, ground, SDA, SCL and reset. Confirm controller type, resolution and address. The library may allocate memory even if no display acknowledges on the bus, so absence of its allocation error is not proof of correct wiring.
For stale or overlapping text, inspect clearDisplay(), setCursor() and display(). For a dim or damaged panel, disconnect power and check electrical compatibility before trying software changes. Generic online examples frequently assume a different display controller or supply voltage.
The finish condition is a stable, legible reading that changes with the sensor and retains an honest unit label. This small dashboard becomes a useful diagnostic panel on a future robot.
Important terms
- OLED
- A display technology whose pixels emit light.
- I²C
- A short-distance bus using data and clock signals.
- Address
- A number used to select a device on a bus.
- Framebuffer
- Memory containing an image before it is sent to a display.
- Pixel
- An individual picture element.
- Refresh
- Updating a display with current content.
Mini project: Make the dashboard readable at a glance
- Verify the exact display identity and inspect unpowered wiring.
- Run the matching library example before adding the sensor.
- Upload the complete dashboard and compare bright and covered readings.
- Check that shorter numbers leave no old digits behind.
- Finish by asking another person to identify what the displayed number measures.
Common mistakes and debugging
- Buying by screen size alone: controller, interface and supply compatibility all matter.
- Forgetting display(): drawing in the buffer does not immediately update the panel.
- Labeling ADC counts as lux: preserve the real units.
- Treating begin() as a full wiring test: also verify visible output and bus connectivity.
Independent challenge
Add a second text line with a calibrated light-state label while preserving the raw count. Explain how you will handle values between the hysteresis thresholds.
Check your understanding: 10 questions
Which Uno pins carry hardware I²C here?
Why clear the display before redrawing?
What does screen.display() do?
How many bytes store 128×32 monochrome pixels at one bit each?
Does the number represent calibrated illumination in lux?
In your own words, what does “OLED” mean?
In your own words, what does “I²C” mean?
In your own words, what does “Address” mean?
In your own words, what does “Framebuffer” mean?
In your own words, what does “Pixel” mean?
Quiz answers
Reveal all 10 answers after your attempt
- A4 is SDA and A5 is SCL.
- To remove remnants of the previous frame, such as extra digits.
- It transfers the framebuffer to the screen.
- 512 bytes.
- No. It is a raw ADC reading from the LDR divider.
- A display technology whose pixels emit light.
- A short-distance bus using data and clock signals.
- A number used to select a device on a bus.
- Memory containing an image before it is sent to a display.
- An individual picture element.
Summary
A useful dashboard combines compatible hardware, correct bus settings and clear information design. Displaying raw values honestly makes both learning and troubleshooting easier.
Continue learning
ARD08 compares the communication methods behind displays, computers and wireless modules.
- Arduino Sensors: Light, Temperature, Distance, and Motion
- Arduino Communication: Serial, I²C, SPI, Bluetooth, and Wi-Fi
- Build an AI Sensor Dashboard
Sources and further reading
Prepared 2026-09-18. Editorial draft; primary documentation consulted. Hardware build not bench-tested; code has not been executed on the reference board.