Skip to content

Instantly share code, notes, and snippets.

@mdkendall
Last active October 9, 2023 05:19
Show Gist options
  • Save mdkendall/a43b203ff42a429706e819179b4aa80c to your computer and use it in GitHub Desktop.
Save mdkendall/a43b203ff42a429706e819179b4aa80c to your computer and use it in GitHub Desktop.
Python script to display Raspberry Pi status on SSD1306-based 128x64px OLED connected via I2C
#!/bin/bash
# Prerequisite:
# Enable I2C using raspi-config if necessary
# Install I2C support, Python image library, and other support libraries.
sudo apt install -y python3-smbus i2c-tools
sudo apt install -y python3-pil
sudo apt install -y python3-pip
sudo apt install -y python3-setuptools
sudo apt install -y python3-rpi.gpio
# Install Adafruit SSD1306 driver. This is the older version that
# does not depend on the CircuitPython abstraction layer.
git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git
cd Adafruit_Python_SSD1306
sudo python setup.py install
cd ..
# Install the process utilities library that is used by the script.
sudo apt install python3-psutil
# Install the font used by the script
wget https://github.com/google/fonts/raw/376ff5c1ab3952ec7d324a2222f1018a09b2a437/apache/roboto/static/Roboto-Regular.ttf -P Roboto
sudo cp -r Roboto /usr/share/fonts/truetype
# Install the script
sudo cp oled_status.py /usr/local/bin/oled_status
sudo chmod +x /usr/local/bin/oled_status
# Create a user to run the script
sudo useradd -r oled
sudo usermod -a -G i2c oled
# Install the service
sudo cp oled.service /lib/systemd/system
sudo systemctl start oled
sudo systemctl enable oled
[Unit]
Description=OLED Status Display
[Service]
User=oled
ExecStart=/usr/local/bin/oled_status
SyslogIdentifier=oled
Type=simple
Restart=on-failure
RestartSec=30
Nice=10
[Install]
WantedBy=default.target
#! /usr/bin/python3
# Loosely based on Adafruit_Python_SSD1306/examples/stats.py
#
# Modified to use psutil instead of spawning shells to run commands to get stats.
# This, plus sleeping to yield after getting stats and updating image, plus
# reducing the update rate to only every 3s, dramatically lowers the CPU usage.
# To further reduce impact on other real-time programs, run with 'nice'.
import time
import psutil
import Adafruit_SSD1306
from PIL import Image, ImageDraw, ImageFont
# 128x64 display with hardware I2C:
disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
# Initialize and clear the display.
disp.begin()
disp.clear()
disp.display()
# Create a blank 1-bit image and get an associated drawing object.
image = Image.new('1', (disp.width, disp.height))
draw = ImageDraw.Draw(image)
# Load a TTF font from a .ttf file and set the height in pixels.
font = ImageFont.truetype('/usr/share/fonts/truetype/Roboto/Roboto-Regular.ttf', 12)
while True:
# Draw a black filled box to clear the image.
draw.rectangle((0, 0, disp.width, disp.height), outline=0, fill=0)
# Get stats to display.
ip_addr = psutil.net_if_addrs()['wlan0'][0].address
cpu_percent = psutil.cpu_percent()
cpu_load = psutil.getloadavg()
mem_usage = psutil.virtual_memory()
disk_usage = psutil.disk_usage('/')
temperature = psutil.sensors_temperatures()['cpu_thermal'][0].current
time.sleep(0.1)
# Write text to the image.
draw.text((0, 0), "IP %s" % (ip_addr), font=font, fill=255)
draw.text((0, 12), "CPU %d%% Load %.2f" % (cpu_percent, cpu_load[0]), font=font, fill=255)
draw.text((0, 24), "Mem %d/%dM %d%%" % (mem_usage.used/(1<<20), mem_usage.total/(1<<20), mem_usage.percent), font=font, fill=255)
draw.text((0, 36), "Disk %d/%dG %d%%" % (disk_usage.used/(1<<30), disk_usage.total/(1<<30), disk_usage.percent), font=font, fill=255)
draw.text((0, 48), "Temp %dC" % (temperature), font=font, fill=255)
time.sleep(0.1)
# Display image.
disp.image(image)
disp.display()
time.sleep(3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment