Noob
I am working on a small project to add an OLED display to my Pi's case to display system information and UPS battery info from the following guide: https://www.the-diy-life.com/mini-raspb ... ment-26030
I have the display working using the provided script from the tutorial without any edits. However, I noticed that the display will freeze after a while and stop updating any of the stats. I suspect this is happening when the Pi puts the display to sleep, but not 100% sure. I ran the stats.py script in Thonny and got the following output once it stopped.
Python 3.7.3 (/usr/bin/python3)
>>> %Run stats.py
Traceback (most recent call last):
File "/home/pi/stats.py", line 90, in <module>
IP = subprocess.check_output(cmd, shell = True )
File "/usr/lib/python3.7/subprocess.py", line 395, in check_output
**kwargs).stdout
File "/usr/lib/python3.7/subprocess.py", line 472, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.7/subprocess.py", line 775, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.7/subprocess.py", line 1412, in _execute_child
errpipe_read, errpipe_write = os.pipe()
OSError: [Errno 24] Too many open files
>>>
Stats.py script below:
Code: Select all
import time
import smbus2
import logging
from ina219 import INA219,DeviceRangeError
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import subprocess
DEVICE_BUS = 1
DEVICE_ADDR = 0x17
PROTECT_VOLT = 3700
SAMPLE_TIME = 2
# Raspberry Pi pin configuration:
RST = None # on the PiOLED this pin isnt used
# 128x64 display with hardware I2C:
disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)
# Initialize library.
disp.begin()
# Clear display.
disp.clear()
disp.display()
# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
width = disp.width
height = disp.height
image = Image.new('1', (width, height))
# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)
# Draw a black filled box to clear the image.
draw.rectangle((0,0,width,height), outline=0, fill=0)
# Draw some shapes.
# First define some constants to allow easy resizing of shapes.
padding = -2
top = padding
bottom = height-padding
# Move left to right keeping track of the current x position for drawing shapes.
x = 0
# Display counter
dispC = 0
# Load default font.
# font = ImageFont.load_default()
# Alternatively load a TTF font. Make sure the .ttf font file is in the same directory as the python script!
# Some other nice fonts to try: http://www.dafont.com/bitmap.php
font = ImageFont.truetype('PixelOperator.ttf', 16)
while True:
# Draw a black filled box to clear the image.
draw.rectangle((0,0,width,height), outline=0, fill=0)
# Shell scripts for system monitoring from here : https://unix.stackexchange.com/questions/119126/command-to-display-memory-usage-disk-usage-and-cpu-load
cmd = "hostname -I | cut -d\' \' -f1"
IP = subprocess.check_output(cmd, shell = True )
cmd = "top -bn1 | grep load | awk '{printf \"CPU: %.2f\", $(NF-2)}'"
CPU = subprocess.check_output(cmd, shell = True )
cmd = "free -m | awk 'NR==2{printf \"Mem: %s/%sMB %.2f%%\", $3,$2,$3*100/$2 }'"
MemUsage = subprocess.check_output(cmd, shell = True )
cmd = "df -h | awk '$NF==\"/\"{printf \"Disk: %d/%dGB %s\", $3,$2,$5}'"
Disk = subprocess.check_output(cmd, shell = True )
cmd = "vcgencmd measure_temp |cut -f 2 -d '='"
temp = subprocess.check_output(cmd, shell = True )
# Scripts for UPS monitoring
ina = INA219(0.00725,address=0x40)
ina.configure()
piVolts = round(ina.voltage(),2)
piCurrent = round (ina.current())
ina = INA219(0.005,address=0x45)
ina.configure()
battVolts = round(ina.voltage(),2)
try:
battCur = round(ina.current())
battPow = round(ina.power()/1000,1)
except DeviceRangeError:
battCur = 0
battPow = 0
bus = smbus2.SMBus(DEVICE_BUS)
aReceiveBuf = []
aReceiveBuf.append(0x00) # Placeholder
for i in range(1,255):
aReceiveBuf.append(bus.read_byte_data(DEVICE_ADDR, i))
if (aReceiveBuf[8] << 8 | aReceiveBuf[7]) > 4000:
chargeStat = 'Charging USB C'
elif (aReceiveBuf[10] << 8 | aReceiveBuf[9]) > 4000:
chargeStat = 'Charging Micro USB.'
else:
chargeStat = 'Not Charging'
battTemp = (aReceiveBuf[12] << 8 | aReceiveBuf[11])
battCap = (aReceiveBuf[20] << 8 | aReceiveBuf[19])
if (dispC <= 15):
# Pi Stats Display
draw.text((x, top+2), "IP: " + str(IP,'utf-8'), font=font, fill=255)
draw.text((x, top+18), str(CPU,'utf-8') + "%", font=font, fill=255)
draw.text((x+80, top+18), str(temp,'utf-8') , font=font, fill=255)
draw.text((x, top+34), str(MemUsage,'utf-8'), font=font, fill=255)
draw.text((x, top+50), str(Disk,'utf-8'), font=font, fill=255)
dispC+=1
else:
# UPS Stats Display
draw.text((x, top+2), "Pi: " + str(piVolts) + "V " + str(piCurrent) + "mA", font=font, fill=255)
draw.text((x, top+18), "Batt: " + str(battVolts) + "V " + str(battCap) + "%", font=font, fill=255)
if (battCur > 0):
draw.text((x, top+34), "Chrg: " + str(battCur) + "mA " + str(battPow) + "W", font=font, fill=255)
else:
draw.text((x, top+34), "Dchrg: " + str(0-battCur) + "mA " + str(battPow) + "W", font=font, fill=255)
draw.text((x+15, top+50), chargeStat, font=font, fill=255)
dispC+=1
if (dispC == 30):
dispC = 0
# Display image.
disp.image(image)
disp.display()
time.sleep(.1)