OLED Display
Time estimate: ~45 minutes Prerequisites: Enable I2C, MCP9808 Driver
Now that you have a kernel driver reading temperature from the MCP9808, let's display that data on an OLED screen. The MCP9808 driver exposes temperature through /dev/mcp9808 — you will build a Python application that reads this value and shows it on a small I2C OLED display using user-space tools.
An OLED (Organic Light-Emitting Diode) display uses organic compounds that emit light when an electric current passes through them — each pixel produces its own light, so there is no backlight. The small displays used in this lab use the SSD1306 controller chip, which accepts commands and pixel data over I2C (the same bus you used for the MCP9808 temperature sensor). The SSD1306 handles all display refresh internally — you just send it data.
Connect the OLED display with cables to the temperature sensor to the same I2C bus. Check if it connected properly:
Should appear at address 0x3C. Note that 0x18 shows UU instead of the address — this means a kernel driver has already claimed that address (the MCP9808 temperature sensor driver):
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Download the OLED tool
Enter to the directory:
Build it:
Copy to /usr/bin
Test it:
Flag reference: -c clears the display before drawing, -I 128x32 sets the display resolution (128 pixels wide, 32 pixels tall), -n 1 selects I2C bus 1, and -m specifies the message text to display.
Now create an application that display the indoor temperature and weather information on the OLED display.
Create a demo app
Warning
Get a free API key from weatherapi.com and replace YOUR_API_KEY_HERE. Never commit API keys to version control.
import time
import requests
import subprocess
# Set your Weather API key here
API_KEY = 'YOUR_API_KEY_HERE' # Get a free key at weatherapi.com
LAT = 47.4979
LON = 19.0402
WEATHER_URL = f'https://api.weatherapi.com/v1/current.json?q={LAT}%2C{LON}&key={API_KEY}'
# Global variable to store latest weather info
latest_weather = "Getting weather..."
latest_indoor = "Getting temperature"
def get_weather():
global latest_weather
try:
headers = {'accept': 'application/json'}
response = requests.get(WEATHER_URL, headers=headers)
response.raise_for_status()
weather_data = response.json()
temp_c = weather_data['current']['temp_c']
condition = weather_data['current']['condition']['text']
latest_weather = f"{temp_c}~C {condition}"
except Exception as e:
latest_weather = e # "Weather error"
print(f"Failed to get weather: {e}")
def get_indoor_temp():
global latest_indoor
try:
with open('/dev/mcp9808', 'r') as file:
temp = file.read().strip()
latest_indoor = f"{temp}~C indoor"
except Exception as e:
latest_indoor = "Get temp error"
print(f"Failed to get indoor temp: {e}")
def update_display(current_time):
# Prepare the lines to display
time_part = current_time
weather_part = latest_weather
indoor_part = latest_indoor
# Split time and weather into lines if needed
lines = []
lines.append(weather_part[:20]) # Topmost line (truncated if too long)
#lines.append("") # Another blank line
lines.append(indoor_part[:20]) # Blank line
lines.append(time_part[:20]) # Bottom line (time)
# Join lines in correct order for OLED (bottom-up)
display_text = "\\n".join(reversed(lines))
#display_text = "hello"
try:
subprocess.run(["/usr/bin/ssd1306_bin", "-I", "128x32", "-c", "-n", "1", "-m", display_text], check=True)
except Exception as e:
print(f"Display update failed: {e}")
def main_loop():
counter = 0
while True:
current_time = time.strftime('%Y-%m-%d %H:%M')
# current_time = time.strftime('%Y-%m-%d %H:%M:%S')
print(f"Current Time: {current_time}")
if counter % 60 == 0:
get_weather()
get_indoor_temp()
update_display(current_time)
time.sleep(60)
counter += 1
if __name__ == "__main__":
try:
print("Starting background app. Press Ctrl+C to stop.")
main_loop()
except KeyboardInterrupt:
print("\nExiting cleanly.")
Create a systemd service file
A systemd service file tells the init system how to run your application as a managed background service. It has three sections:
- [Unit] — metadata and ordering:
Descriptionnames the service;After=network.targetmeans "start this after networking is ready" - [Service] — how to run:
ExecStartis the command,Restart=alwaysmeans systemd will restart the process if it crashes - [Install] — when to start:
WantedBy=multi-user.targetmeans "start at normal boot" (not just in rescue mode)
[Unit]
Description=OLED Weather Service
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/linux/app.py
WorkingDirectory=/home/linux/
StandardOutput=inherit
StandardError=inherit
Restart=always
User=linux
Group=linux
[Install]
WantedBy=multi-user.target
Course Overview | Next: OLED Framebuffer Driver →
Info
Don't have an OLED display? If you have the BUSE LED matrix hardware, you can continue with BUSE Framebuffer Driver instead — it teaches the same fbdev concepts.