Im vorherigen Beitrag haben wir uns ein paar Grundlagen zum 0,96'' OLED-Display mit 128x64 Pixeln angeeignet und hier gehen wir ein Stück weiter: Wir lesen die CPU-Auslastung vom Raspberry Pi aus und stellen diese als Diagramm auf dem Display dar. Die Skalierung des Diagramms soll sich dabei abhängig von den dargestellten Werten automatisch anpassen. Zusätzlich wird der aktuelle Wert als Text angezeigt.
Inhalt
Benötigte Bibliotheken
Um an die benötigten Informationen zu gelangen, nutzen wir psutil
– eine Bibliothek, mit der man Systemwerte auslesen kann. Zur Installation benötigen wir PIP
. Wer das nicht hat, muss das vorher noch installieren:
$ sudo apt-get install python-pip
Dann machen wir direkt mit dem Paket weiter:
$ sudo pip install psutil
psutil
nur die CPU-Auslastung aus, die Bibliothek kann aber noch mehr liefern. Einen genauen Überblick darüber könnt ihr euch hier verschaffen. Der Code
Wer den vorherigen Beitrag aufmerksam gelesen hat, wird mit dem Code schnell zurecht kommen. Daher gehe ich nur auf das Auslesen der Werte und den Aufbau des Diagramms ein.
#!/usr/bin/python # coding=utf-8 # Einbindung der notwendigen Grundbibliotheken import os, sys, time # Einbindung 0,96 Zoll OLED Display 128x64 Pixel from lib_oled96 import ssd1306 from smbus import SMBus from PIL import ImageFont # Einbindung von Bibliotheken für die gewünschten Funktionen import psutil # ---------------------------------------------------------------------------- # Variablen anlegen # ---------------------------------------------------------------------------- cpuList = [] scale = 100 # ---------------------------------------------------------------------------- # Display einrichten # ---------------------------------------------------------------------------- i2cbus = SMBus(1) # 0 = Raspberry Pi 1, 1 = Raspberry Pi > 1 oled = ssd1306(i2cbus) # Ein paar Abkürzungen, um den Code zu entschlacken draw = oled.canvas # Display zum Start löschen oled.cls() oled.display() # Schriftarten festlegen FreeSans08 = ImageFont.truetype('FreeSans.ttf', 8) FreeSans11 = ImageFont.truetype('FreeSans.ttf', 11) # ---------------------------------------------------------------------------- # Hauptprogramm # ---------------------------------------------------------------------------- while True: try: # Inhalt des Displays bei jedem Durchlauf neu aufbauen draw.rectangle((0,0, oled.width, oled.height), outline=0, fill=0) # CPU-Auslastung auslesen cpu_val = psutil.cpu_percent(interval=1) # Momentanwert anzeigen draw.text((0, 0), "CPU: " + str(cpu_val) + " %", font=FreeSans11, fill=255) # Werte für Diagramm speichern und Länge auf 110 Einträge begrenzen cpuList.append(cpu_val) if len(cpuList) > 110: cpuList.pop(0) # Skalierung des Diagramms max_val = max(cpuList) if max_val <= 100.0: scale = 100 if max_val <= 90.0: scale = 90 if max_val <= 80.0: scale = 80 if max_val <= 70.0: scale = 70 if max_val <= 60.0: scale = 60 if max_val <= 50.0: scale = 50 if max_val <= 40.0: scale = 40 if max_val <= 30.0: scale = 30 if max_val <= 20.0: scale = 20 if max_val <= 10.0: scale = 10 # Achsen zeichnen draw.line((12, 60, oled.width, 60), fill=255) # X draw.line((15, 20, 15, 63), fill=255) # Y draw.line((12, 20, 15, 20), fill=255) # oberster Skalenwert # obersten Y-Wert beschriften draw.text((0, 16), str(scale), font=FreeSans08, fill=255) # X-Koordinate für ersten Wert festlegen X = 17 # Diagrammwerte zeichnen for n in range(len(cpuList)): Y = float(40 / float(scale) * cpuList[n]) draw.line((X, 58, X, 58-Y), fill=255) X = X + 1 # Daten am Display ausgeben oled.display() # Ausgabe der aktuellen Werte auf der Kommandozeile zum Debuggen #print str(cpu_val) + " | " + str(max_val) + " | " + str(scale) + " | " + str(40.0 / float(scale) * float(cpu_val)) except KeyboardInterrupt: oled.cls() oled.display() sys.exit(0)
Funktionsweise
Grob kann man das Ganze so beschreiben:
Das Display kann, durch seine Breite vorgegeben 110 Einzelwerte darstellen. Den restlichen Platz benötigen wir für die Y-Achse. Die Einzelwerte reihen wir mit 1px breiten Linien aneinander, bis das Display gefüllt ist. So ergibt sich unser Diagramm.
Momentanwerte speichern
Auf Zeile 18 erzeugen wir eine leere Liste und darunter legen wir den Skalenendwert der Y-Achse auf 100 fest. Die momentane CPU-Auslastung lesen wir mittels psutil
auf Zeile 49 aus und stellen diese auf Zeile 52 als Text dar.
Mit dem Code auf den Zeilen 55-57 hängen wir Durchlauf für Durchlauf den aktuellen Momentanwert der CPU-Auslastung an die anfangs noch leere Liste an. Diese baut sich somit immer weiter auf. Sie soll jedoch nicht ewig lang werden, da unser Display ja auch nicht ewig breit ist. In der hier verwendeten Darstellung passen 110 Werte in das Diagramm auf dem Display. Somit muss die Liste mit den CPU-Werten auch nicht länger sein. Wenn der 111. Eintrag angehängt wird, wird der erste aus der Liste entfernt (cpuList.pop(0)
), sodass die Liste danach wieder 110 Einträge besitzt.
Y-Achse skalieren
Bei geringer CPU-Last und einer Skalierung der Y-Achse, dass 0…100% angezeigt werden können, würde man die meiste Zeit überhaupt keine Werte im Diagramm sehen. Daher soll die Skalierung der Y-Achse automatisch angepasst und die Darstellung der Einzelwerte optimal auf den zur Verfügung stehenden Platz zugeschnitten werden. Dazu ermitteln wir den größten Wert der Liste (Zeile 60) und runden ihn auf 10er-Stellen auf (Zeilen 62-81). Der ermittelte Wert dient als Faktor für die Höhe der zu zeichnenden Linien.
Diagramm zeichnen
Auf den Zeilen 95 bis 98 iterieren wir über alle Werte in der Liste und zeichnen für jeden Einzelwert eine Linie, deren Länge abhängig vom Skalierungsfaktor ist. Die Berechnung lautet wie folgt:
<Diagrammhöhe> / <Skalierungsfaktor> * <CPU-Auslastung>
Die Diagrammhöhe ergibt sich daraus, wie man den Platz auf dem Display dafür freihält. In meinem Beispiel sind 40 Pixel für die Werte vorgesehen. Den Skalierungsfaktor haben wir im vorherigen Abschnitt betrachtet und die CPU-Auslastung haben wir mit psutil
erfasst.
Ein Beispiel: In unserer Liste befinden sich jede Menge bunte Werte zwischen 0 und 19. Der Skalierungsfaktor wird demzufolge 20 sein. Der Wert, der gezeichnet werden soll, beträgt 14. Das führt uns zu folgender Formel:
Linienlänge = 40px / 20 * 14% = 28px
Der Startpunkt der Werte ist auf 58px festgelegt. Von dieser Höhe werden die Linien aufwärts gezeichnet.
Auf Zeile 92 haben wir zuvor noch die X-Koordinate für den ersten Wert festgelegt. Bei jedem Durchlauf der for
-Schleife wird X um 1 erhöht, sodass jede weitere Linie um je einen Pixel nach rechts verschoben gezeichnet wird.
Debuggen
Wer die im Diagramm angezeigten Werte mit der Berechnung vergleichen möchte, kann Zeile 104 einkommentieren. Hier werden die aktuelle CPU-Auslastung, der höchste Wert in der Liste, der Skalierungsfaktor und die berechnete Linienlänge ausgegeben.
- Proxmox: „Failed to connect to Server“ mit Safari auf MacOS - 28. Januar 2023
- Loxone: Benachrichtigung per Telegram - 15. Januar 2022
- Telegram: Nachrichten per Bot von der Heimautomation aufs Handy - 2. Januar 2022
18 Comments