Welcome to my running commentary, hacks, projects, and time-wasters using open-source software and inexpensive hardware. I really like tinkering with GNU/Linux and hardware that supports free software.
Tuesday, August 9, 2016
An SSD1306 OLED System Monitor for the Raspberry Pi
Here's a simple system monitor for the Raspberry Pi using an SSD1306 OLED and a BME280 sensor (to get temperature, barometric pressure and humidity). You'll need to construct an iC2 'Y' cable and plug into the GPIO pins on your Pi. Make sure to enable iC2 for Raspbian, then download and install rm-hull's Github SSD1306 library, along with Matt Hawkin's bme280.py script. Put everything into the same directory.
After testing to make sure that your sensor and OLED are working, use this script to get a host of information about your Pi, ambient conditions and even local weather.
Here's the script:
#!/usr/bin/env python
# myssd.py version 0.8 - a simple system monitor for the Raspberry Pi
# adapted from rmhull's wonderful ssd1306 Python lib by bball@tux.org
# crafted for the dual-color 128x96 OLED w/yellow top area
# 060316 - added date, CPU temp, wlan0 IP addr, memory, sd card used
# 060416 - added splash screen, general code cleanup, KB output for memory
# 061316 - added local current WX conditions
# 080616 - added wifi, serial number, uptime with text wrap
# 080816 - added BME280 output of temp, pressure, and humidity
import os
import psutil
from lib_oled96 import ssd1306
from time import sleep
from datetime import datetime
from PIL import ImageFont, ImageDraw, Image
#font = ImageFont.load_default()
from smbus import SMBus # These are the only two variant lines !!
i2cbus = SMBus(1) #
oled = ssd1306(i2cbus)
draw = oled.canvas
# set font to 13 for yellow area
font = ImageFont.truetype('FreeSans.ttf', 13)
# show splash screen
draw.text((1, 1), 'RASPBIAN SYSMON', font=font, fill=1)
logo = Image.open('rpi.png')
draw.bitmap((42, 16), logo, fill=1)
oled.display()
sleep(3)
oled.cls()
while True:
# "draw" onto this canvas, then call display() to send the canvas contents to the hardware.
draw = oled.canvas
# set font to 13 for yellow area
font = ImageFont.truetype('FreeSans.ttf', 13)
# get, display date and time
draw.text((1, 1), str(datetime.now().strftime('%a %b %d %H:%M:%S')), font=font, fill=1)
# reset font for four smaller lines
font = ImageFont.truetype('FreeSans.ttf', 10)
# get, return CPU's current temperature
def cpu_temp():
tempF = (((int(open('/sys/class/thermal/thermal_zone0/temp').read()) / 1000)*9/5)+32)
return "CPU TEMP: %sF" % str(tempF)
# display CPU temp
draw.text((1, 15), cpu_temp(), font=font, fill=1)
# get, return wlan0's current IP address
def wlan_ip():
f = os.popen('ifconfig wlan0 | grep "inet\ addr" | cut -c 21-33')
ip = str(f.read())
# strip out trailing chars for cleaner output
return "WIFI IP: %s" % ip.rstrip('\r\n')
# display the IP address
draw.text((1, 28), wlan_ip(), font=font, fill=1)
# get amount of free memory
def mem_usage():
usage = psutil.virtual_memory()
return "MEM USED: %s KB" % (int(str(usage.used)) / 1024)
# display amount of free memory
draw.text((1, 41), mem_usage(), font=font, fill=1)
# get disk usage
def disk_usage(dir):
usage = psutil.disk_usage(dir)
return "SD CARD USED: %.0f%%" % (usage.percent)
# display disk usage
draw.text((1, 53), disk_usage('/'), font=font, fill=1)
oled.display()
sleep(6)
oled.cls() # Oled still on, but screen contents now blacked out
# LARGE display - get wifi wlan0 signal strength
def get_wifi():
cmd = "iwconfig wlan0 | grep Signal | /usr/bin/awk '{print $4}' | /usr/bin/cut -d'=' -f2"
strDbm = os.popen(cmd).read()
dbm = int(strDbm)
quality = 2 * (dbm + 100)
if strDbm:
return("{0} dbm = {1}%".format(dbm, quality))
else:
return("No Wifi")
font = ImageFont.truetype('/home/pi/Downloads/ssd1306-master/FreeSans.ttf', 17)
draw.text((1, 1), 'WIFI SIGNAL', font=font, fill=1)
font = ImageFont.truetype('/home/pi/Downloads/ssd1306-master/FreeSans.ttf', 15)
draw.text((1, 30), get_wifi(), font=font, fill=1)
oled.display()
sleep(2)
oled.cls()
# LARGE display - uptime
def get_uptime():
uptime = os.popen("uptime")
ut = str(uptime.read())
# strip out trailing chars for cleaner output
return "%s" % ut.rstrip('\r\n')
font = ImageFont.truetype('/home/pi/Downloads/ssd1306-master/FreeSans.ttf', 17)
draw.text((1, 1), ' UPTIME', font=font, fill=1)
# now smaller font needed and wrap text to show info
font = ImageFont.truetype('/home/pi/Downloads/ssd1306-master/FreeSans.ttf', 11)
import textwrap
lines = textwrap.wrap(get_uptime(), width=25)
# what 'line' to start info
y_text = 20
w = 1 # we'll always start at left side of OLED
for line in lines:
width, height = font.getsize(line)
draw.text((w, y_text), line, font=font, fill=1)
y_text += height
oled.display()
sleep(2)
oled.cls()
# LARGE display - get, display serial number
def get_serial():
cmd = "cat /proc/cpuinfo | grep Serial | /usr/bin/awk '{print $3}'"
strDbm = os.popen(cmd).read()
snum = str(strDbm)
return "%s" % snum.rstrip('\r\n')
font = ImageFont.truetype('/home/pi/Downloads/ssd1306-master/FreeSans.ttf', 17)
draw.text((1, 1), 'Serial Number', font=font, fill=1)
font = ImageFont.truetype('/home/pi/Downloads/ssd1306-master/FreeSans.ttf', 14)
draw.text((1, 30), get_serial(), font=font, fill=1)
oled.display()
sleep(1)
oled.cls()
# read bme280 data
def get_temp():
from bme280 import readBME280All
temperature,pressure,humidity = readBME280All()
return "%.2f degrees F" % (((temperature)*9/5)+32)
def get_pressure():
from bme280 import readBME280All
temperature,pressure,humidity = readBME280All()
return "%.2f inches mercury" % ((pressure)/33.8638866667)
def get_humidity():
from bme280 import readBME280All
temperature,pressure,humidity = readBME280All()
return "%.2f%% humidity" % humidity
font = ImageFont.truetype('/home/pi/Downloads/ssd1306-master/FreeSans.ttf', 13)
draw.text((1, 1), 'Ambient Conditions', font=font, fill=1)
font = ImageFont.truetype('/home/pi/Downloads/ssd1306-master/FreeSans.ttf', 11)
draw.text((1, 20), get_temp(), font=font, fill=1)
draw.text((1, 35), get_pressure(), font=font, fill=1)
draw.text((1, 50), get_humidity(), font=font, fill=1)
oled.display()
sleep(10)
oled.cls()
# get, return current WX
def do_wx():
f = os.popen('/usr/local/bin/currentwx')
wx = str(f.read())
# strip out trailing chars for cleaner output
return "%s" % wx.rstrip('\r\n')
font = ImageFont.truetype('FreeSans.ttf', 13)
draw.text((1, 1), 'CURRENT WEATHER:', font=font, fill=1)
# display the WX
font = ImageFont.truetype('FreeSans.ttf', 12)
draw.text((1, 15), 'PINELLAS PARK', font=font, fill=1)
draw.text((1, 41), do_wx(), font=font, fill=1)
oled.display()
sleep(10)
oled.cls() # Oled still on, but screen contents now blacked out
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment