Back

Activity 2.11: The OLED Display

The Messy Real World — Day 4 of 4

divider

Activity 2.11

The OLED Display

Key Concepts

I²C and Qwiic

Buffered Output

Libraries

Every Reading So Far Went to a Laptop

print() sends text down the USB cable. Unplug the cable and your project goes blind.

A robot on wheels cannot drag a laptop behind it. Before anything can drive away, it needs its own screen.

A Different Kind of Connection

Every part so far got its own pin, wired by hand. The OLED does not. It plugs in with one Qwiic cable that carries power, ground, and two data wires.

Those two data wires are I²C— a shared bus. Many devices can hang off the same pair, each answering to its own address. No breadboard, no resistors, and it only goes in one way.

Somebody Else Wrote the Hard Part

Talking to a screen means sending dozens of specific bytes in a specific order. You are not going to do that by hand, and you do not have to.

SparkFun's library does it. You import it, the same way you imported math and random in Unit 1 — except this one drives hardware.

Ask Before You Assume

if oled.is_connected() == False:
print("No display found. Check the Qwiic cable.")

A pin is always there. A device on a bus might not be — unplugged cable, wrong port, dead board. Checking first turns a confusing silence into a useful message.

Three Steps, Every Time

oled.clear(oled.PAGE) # wipe the buffer
oled.print("Hello") # write into the buffer
oled.display() # push the buffer to the glass

Nothing appears until display(). The first two lines only change a copy in memory — a buffer — and forgetting the third is the classic way to get a blank screen and no error.

Wrap It Once

def show(oled, line1, line2):
oled.clear(oled.PAGE)
oled.print(line1)
oled.print(line2)
oled.display()

Four calls, every single frame. Write them once inside a function and the rest of your program just says show(oled, a, b).

Today's Objectives

  • Connecting a Qwiic device over I²C
  • Using a library to drive hardware you did not wire yourself
  • Printing text and numbers to a small screen
  • Showing a live sensor reading without a laptop attached

Key Terms

I²C
A two-wire bus that lets several devices share the same pair of pins, each with its own address.
Qwiic
SparkFun's solderless connector for I²C — one cable carrying power, ground, and the two data lines.
Buffer
A copy of the screen held in memory. Changes land there first and only appear when pushed to the display.
Library
Someone else's code, imported into yours, handling work you should not have to repeat.

'F' → Fullscreen

divider

Build

Leave the sensors from 2.9 and 2.10 wired. Create a new MicroPython program named 2-11-display.


Task 1: Hello, Screen

  • Plug the OLED into the QWIIC connector — the small white four-pin socket on the top-left corner of the board. It only fits one way.
  • Check the display is actually connected before using it.
  • Clear it, print a word, and push it to the glass.

No breadboard, no resistors, no pins to look up. This is the only part in the whole kit that connects with a single cable.

[PHOTO PLACEHOLDER — Task 1: Qwiic Cable from the Board to the OLED]
The OLED Display
import qwiic_large_oled
oled = qwiic_large_oled.QwiicLargeOled()
if oled.is_connected() == False:
print("No display found. Check the Qwiic cable.")
oled.begin()
oled.clear(oled.PAGE)
oled.print("Hello")
oled.display()

Task 2: A Live Number

  • Bring the temperature sensor and its conversion over from Activity 2.9.
  • Show the temperature on the screen instead of printing it, and refresh twice a second.
  • Warm the sensor with your fingers and watch the screen, not the terminal.

oled.print() wants text, and your temperature is a number, so str() has to convert it first — the same casting you met back in Activity 1.8.

The OLED Display
from machine import Pin, ADC
import qwiic_large_oled
import time
temp_sensor = ADC(Pin(41))
OFFSET = 0.0
oled = qwiic_large_oled.QwiicLargeOled()
if oled.is_connected() == False:
print("No display found. Check the Qwiic cable.")
oled.begin()
def read_average(sensor, samples):
total = 0
for i in range(samples):
total = total + sensor.read_u16()
time.sleep(0.01)
return total // samples
def to_celsius(reading):
volts = reading / 65535 * 3.3
return (volts - 0.5) * 100 + OFFSET
while True:
celsius = to_celsius(read_average(temp_sensor, 10))
oled.clear(oled.PAGE)
oled.print(str(round(celsius, 1)) + "C")
oled.display()
time.sleep(0.5)

Task 3: Wrap the Four Calls

  • Write show(oled, line1, line2) that does clear, print, print, display.
  • Use it to label the reading, so the screen says what the number means.
The OLED Display
from machine import Pin, ADC
import qwiic_large_oled
import time
temp_sensor = ADC(Pin(41))
OFFSET = 0.0
oled = qwiic_large_oled.QwiicLargeOled()
if oled.is_connected() == False:
print("No display found. Check the Qwiic cable.")
oled.begin()
def read_average(sensor, samples):
total = 0
for i in range(samples):
total = total + sensor.read_u16()
time.sleep(0.01)
return total // samples
def to_celsius(reading):
volts = reading / 65535 * 3.3
return (volts - 0.5) * 100 + OFFSET
def show(oled, line1, line2):
oled.clear(oled.PAGE)
oled.print(line1)
oled.print(line2)
oled.display()
while True:
celsius = to_celsius(read_average(temp_sensor, 10))
show(oled, "Temperature", str(round(celsius, 1)) + "C")
time.sleep(0.5)

Task 4: Two Sensors at Once

  • Add the light sensor from 2.10.
  • Show temperature on one line and the light reading on the other.
The OLED Display
from machine import Pin, ADC
import qwiic_large_oled
import time
temp_sensor = ADC(Pin(41))
light_sensor = ADC(Pin(42))
OFFSET = 0.0
oled = qwiic_large_oled.QwiicLargeOled()
if oled.is_connected() == False:
print("No display found. Check the Qwiic cable.")
oled.begin()
def read_average(sensor, samples):
total = 0
for i in range(samples):
total = total + sensor.read_u16()
time.sleep(0.01)
return total // samples
def to_celsius(reading):
volts = reading / 65535 * 3.3
return (volts - 0.5) * 100 + OFFSET
def show(oled, line1, line2):
oled.clear(oled.PAGE)
oled.print(line1)
oled.print(line2)
oled.display()
while True:
celsius = to_celsius(read_average(temp_sensor, 10))
light = read_average(light_sensor, 10)
show(oled, str(round(celsius, 1)) + "C", "light " + str(light))
time.sleep(0.5)

Task 5: Status Without a Laptop

  • Bring back the latching alarm logic from Activity 2.10.
  • Put ARMED or TRIGGERED on the top line and the temperature underneath.
  • Close your editor. The board keeps running, and now you can still read it.

That last step is the point of the whole session. Everything you have built so far has needed a laptop to be useful. This does not.

The OLED Display
from machine import Pin, ADC
import qwiic_large_oled
import time
temp_sensor = ADC(Pin(41))
light_sensor = ADC(Pin(42))
OFFSET = 0.0
DARK = 12000
oled = qwiic_large_oled.QwiicLargeOled()
if oled.is_connected() == False:
print("No display found. Check the Qwiic cable.")
oled.begin()
def read_average(sensor, samples):
total = 0
for i in range(samples):
total = total + sensor.read_u16()
time.sleep(0.01)
return total // samples
def to_celsius(reading):
volts = reading / 65535 * 3.3
return (volts - 0.5) * 100 + OFFSET
def show(oled, line1, line2):
oled.clear(oled.PAGE)
oled.print(line1)
oled.print(line2)
oled.display()
armed = True
while True:
celsius = to_celsius(read_average(temp_sensor, 10))
light = read_average(light_sensor, 10)
if armed and light < DARK:
armed = False
if armed:
status = "ARMED"
else:
status = "TRIGGERED"
show(oled, status, str(round(celsius, 1)) + "C")
time.sleep(0.5)
[PHOTO PLACEHOLDER — Task 5: OLED Showing ARMED and a Temperature, No Laptop Attached]

Challenge (Optional): Three Lines

  • Fit a third value on the screen — the potentiometer from 2.8, or a running highest-temperature.
  • You may need to look up how to position the cursor rather than relying on each print() to fall on the next line.
divider

Checkpoint

  • The screen lights up and shows text within a second of the script starting
  • The temperature on the glass matches what the terminal printed in Activity 2.9
  • Warming the sensor changes the number on screen within a few seconds
  • Covering the light sensor flips the top line to TRIGGERED, and it stays there
  • Closing the editor does not stop the display updating
divider

Reflection

Answer the following questions before submitting your work.

  1. Every other component in this unit needed its own pin and its own wiring. The OLED needed one cable. Explain what I²C does that makes that possible.
  2. Leaving out display() gives you a blank screen and no error message at all. Explain what a buffer is and why that mistake is silent rather than noisy.
  3. You wrote show() to wrap four library calls. Compare that to blink_all() in Activity 2.6, which wrapped two functions you wrote yourself. What is the same about why both were worth writing?
divider

Submit

Submit the required files to the appropriate dropbox.

Activity Complete