Nach der Corona-Pandemie ist in vielen Unternehmen Shared Office das kostengünstige Gebot der Stunde. Mitarbeiter verbringen nur noch einen Teil ihrer Arbeitszeit im Büro. Doch ob im Office noch ein Platz frei ist, lässt sich nicht ohne weiteres ermitteln.
Die Pandemie hat die Arbeitswelt in vielen Belangen massiv umgekrempelt. So entwickelte sich das hybride Arbeiten für viele Arbeitnehmer zur täglichen Routine. Um Kosten zu senken, verringerten zahlreiche Firmen die Anzahl der verfügbaren Arbeitsplätze vor Ort. Häufig kommt es vor, dass Mitarbeiter weniger als 10 Prozent ihrer Arbeitszeit im Büro verbringen. Unter diesen Bedingungen ist klar: Feste Arbeitsplätze ergeben keinen Sinn mehr.
Kommen wir jetzt zum Problem, dass wir mit dem hier vorgestellten Projekt lösen. Da die Kollegen nicht wissen, welche Plätze in einem Gebäude noch frei sind, bleibt ihnen nichts anderes übrig, als durch die Fläche zu wandern und nach einem freien Platz Ausschau zu halten. Das kostet einiges an Zeit. Zusätzlich lenkt das ständige Gewandere andere Kollegen von ihrer eigentlichen Aufgabe ab. Oft lässt sich außerdem nicht erkennen, ob ein Platz von einem kurzfristig abwesenden Kollegen schon belegt ist.
Eine Möglichkeit, all diesen Herausforderungen zu begegnen, besteht in einem Gerät, das über ein Display signalisiert, ob ein Platz noch zur Verfügung steht. Das Gerät sendet über das WLAN den Status eines Arbeitsplatzes an eine zentrale Datenbank. Die Daten lassen sich dann von beliebigen Anwendungen auslesen. Ähnlich wie in einem Parkhaus erlaubt diese Technik, eine Ampel vor jeder Etage anzusteuern, die im Falle einer Komplettbelegung auf Rot springt.
Mit ein wenig mehr Aufwand ließe sich zudem die aktuelle Belegung der Fläche über einen Bildschirm oder eine App anzeigen. Nicht zuletzt dienen die gesammelten Information auch dazu, die Gebäudenutzung zu optimieren. Zeigt sich zum Beispiel bei der Auswertung der Daten, dass jeden Freitag lediglich die Hälfte der Fläche ausgelastet ist, ließen sich gezielt Stockwerke sperren, um Heiz- und Stromkosten zu senken.
Hardware
Unser Gerät soll helfen, Kosten zu reduzieren, weswegen wir bei der Auswahl der einzelnen Komponenten darauf achten, dass diese möglichst wenig Strom verbrauchen. Zur Anzeige, ob ein Platz belegt oder frei ist, setzen wir daher ein E-Paper-Displays ein. Sie weisen die Besonderheit auf, dass sie die zuletzt angezeigten Informationen selbst bei einem Spannungsausfall immer noch anzeigen. Das heißt, sie benötigen nur Energie, sobald sich die Anzeige ändert. Das sollte unserem Fall relativ selten passieren. In diesem Projekt nutzen wir ein kleines E-Paper-Display [1] mit einer Auflösung von 200×200 Pixeln, das bei Amazon mit etwa 20 Euro zu Buche schlägt. Im Kasten “E-Paper” gehen wir auf die Funktionsweise und Eigenheiten dieser Displays etwas genauer ein.
Zum Ansteuern des Displays dient ein ESP32 Mikrocontroller. Er verfügt über verschiedene Mechanismen, um den Energieverbrauch fast auf Null zu drosseln. Darüber hinaus lässt er sich über unterschiedliche Wege wieder in den normalen Betriebsmodus versetzen. Wir verwenden ein ESP32 Dev-Board [2]. Hierbei gilt es, zu beachten, dass zwar der ESP32 sehr sparsam arbeitet, allerdings lassen sich die restlichen Komponenten auf dem Dev-Board nicht in einen Energiesparmodus versetzen. Sie sind jedoch nötig, um den ESP32 leicht zu programmieren. Wenn Sie die hier vorgestellte Schaltung in einem produktiven Umfeld verwenden möchten, sollten Sie den ESP32 ohne Dev-Board nutzen, und ihn über eine externe Hardware programmieren. Aktuell kostet ein einzelnes Dev-Board bei Amazon etwa 12 Euro. Abbildung 1 zeigt den Testaufbau auf einem Breadboard.
E-Paper-Displays
Ein E-Paper-Display richtet Mikropartikel mithilfe von elektrischen Feldern aus, die das einfallende Licht reflektieren oder absorbieren. So entsteht ein dauerhaftes Bild, das auch nach dem Abschalten der Betriebsspannung erhalten bleibt. Das bedeutet: Ein E-Paper-Display benötigt ausschließlich zum Verändern des Bildes Energie. Das prädestiniert diese Displays für alle Anwendungen, bei denen es auf niedrigen Energiebedarf und gute Lesbarkeit ankommt. Die angezeigten Inhalte sollten sich nach Möglichkeit nicht all zu oft ändern. Das elektronische Preisschild im Supermarkt gehört zu den verbreitetsten Anwendungsbespielen.
E-Papers bieten mittlerweile viele verschiedene Hersteller in unterschiedlichen Ausführungen an. Es gibt biegsame Modelle oder solche, die bis zu fünf Farben mit Abstufungen wiedergeben. Während der Anzeige eines Inhalts flimmert das Display nicht. Es kommt aber vor, dass während des Bildaufbaus ein starkes Flackern erscheint. Das in diesem Artikel eingesetzte Display benötigt für einen solchen Full Refresh etwa 14 Sekunden, in denen es blinkt und nach und nach das Bild aufbaut oder löscht. Alternativ zum Full Refresh besteht die Möglichkeit eines schnelleren partiellen Aktualisierens. Hierbei besteht allerdings immer die Gefahr, das Geisterbilder entstehen.
Schaltplan
Auf den ersten Blick sieht der Schaltplan (Abbildung 2) recht übersichtlich aus. Einige der Details sollten wir trotzdem genauer besprechen. Zunächst der einfache Teil: Das Display ist über die SPI-Schnittstelle an den ESP32 angeschlossen. Die zusätzlich nötigen Steuerleitungen sind 1 zu 1 durchverdrahtet. Der Kondensator C1 stellt sicher, dass das automatische Update der Firmware tatsächlich funktioniert. Die genaue Funktion von C2 und C3 bedarf einer näheren Erläuterung.

Abbildung 2: Der mit Fritzing erstellte Schaltplan des Versuchsaufbaus wirkt zunächst relativ übersichtlich.
In diesem Projekt befindet sich der ESP32 die meiste Zeit im Tiefschlaf. Um ihn aufzuwecken, müssen wir einen Hardware-Interrupt auslösen. Das klappt allerdings nur, wenn die entsprechenden Eingänge über die Funktion RTC (Real Time Clock) verfügen. Nehmen wir an, der ESP32 befindet sich im Ruhezustand. Sobald wir einen der Taster drücken, löst das einen Interrupt aus und der ESP32 fährt hoch. Jetzt tritt ein Problem auf. Damit unser Programm herausfinden kann, welcher der zwei Taster gedrückt wurde, müssten wir diesen so lange festhalten, bis der ESP32 vollständig wach ist und der Python-Interpreter läuft.
Da dieser Vorgang eine gewisse Zeit beansprucht und nicht anwenderfreundlich ausfällt, müssen wir ein wenig weiter denken. An dieser Stelle kommen die zwei Kondensatoren ins Spiel. Sie halten die Spannungspegel lange genug aufrecht, um auszuwerten, welcher Taster gedrückt wurde. Sollten Sie sich ein wenig mit Kondensatoren auskennen, fällt Ihnen auf, dass diese Schaltung nur genau einmal funktionieren kann. Danach sind die Kondensatoren geladen und werden die Eingänge auf 3,3 Volt halten. Wir müssen also dafür sorgen, dass sich die Kondensatoren wieder entladen können. Hierzu verwenden wir die internen Pull-down-Widerstände des ESP32. Diese aktiviert unser Programm und entlädt die Kondensatoren wieder. So steht die Schaltung für die nächste Runde bereit. Den Schaltplan haben dieses mal mit der Fritzing Software [3] erstellt.
Software
Zum Programmieren des ESP32 setzen wir ein wenig untypisch die Programmiersprache Micropython ein. Sie arbeitet wie Python, ist aber für den Betrieb auf Mikrocontrollern optimiert, in diesem Fall stark abgespeckt. Micropython führt den Code naturgemäß erheblich langsamer aus als etwa C-Code. Um zu zeigen, dass sich mit Micropython wirklich hardwarenahe Funktionen verwenden lassen, entschied sich der Autor trotzdem dafür. Für diesen Anwendungsfall spielt die Geschwindigkeit darüber hinaus lediglich eine untergeordnete Rolle. Eine Anleitung, wie Sie Micropython mit der dazugehörigen Entwicklungsumgebung installieren, finden Sie im Artikel “Kleine Schlange” [4]. Wir nutzen hier einen Nightly Build v1.19.1 von Micropython. Grundsätzlich nicht die beste Idee – Wir benötigen jedoch die Funktion ellipse, die erst in die kommende, stabile Release Einzug halten wird.
Display-Treiber
Der Hersteller des Displays stellt auf seiner Homepage [5] einen Python-Treiber für den RasPi zur Vergügung, der allerdings nicht auf Anhieb mit dem ESP32 funktioniert. Um ihn zum Laufen zu bekommen, müssen wir deswegen ein wenig Hand anlegen. Der Treiber besteht aus zwei Dateien: Aus epd1in54b_V2.py wurde lediglich das Logging entfernt. Die zweite Datei epdconfig.py enthält die hardwarespezifischen Kommandos. Hierbei mussten wir sehr viel an den ESP32 angepassen. Sie finden beide Dateien im Download-Bereich dieses Artikels. Damit der Treiber im Speicher des Micropython-Gerätes nicht allzu viel Platz verschlingt, galt es alle Kommentare zu entfernen. Interessanterweise fehlt im Herstellertreiber eine Funktion für einen partiellen Refresh.
In diesem Zusammenhang sei noch erwähnt: Das Display verwendet für jede der zwei Farben einen eigenen Speicherbereich (Buffer). Daher müssen wir für rot und schwarz zwei unterschiedliche Speicherstrukturen anlegen. Diese werden später zwar über einen Aufruf an das Display übermittelt, sind aber tatsächlich getrennt. Dieses recht eigentümliche Vorgehen liegt in der Physik begründet, auf der das Display basiert.
Programm
Das Programm für unseren Versuchsaufbau zeigt Listing 1. Die beiden Funktionen printFree() und printOccupied() erzeugen jeweils die Bildschirmausgaben. Alternativ ließen sich Grafikdateien verwenden, diese besäßen aber den Nachteil, dass sie im Speicher des ESP32 mehr Platz belegen als die wenigen Zeilen Programmcode. Nachdem wir schon so viele Bibliotheken importiert haben, gilt es, den Speicherverbrauch im Auge zu behalten. Der Anfang des Programms definiert die zwei Eingänge für die Taster. Hier sehen wir zudem, dass die Pull-down-Widerstände für die Eingänge aktiviert werden. Damit uns der Status der Taster nicht verloren geht, speichern wir ihn in den Variablen occupied und free. Die beiden Variablen wertet das Programm nach dem Erstellen der WLAN-Verbindung aus.
Mit der Zeile epd = epd1in54b_V2.EPD() erzeugen wir ein Kommunikationsobjekt, mit dem wir Daten an das Display übermitteln. Um die Bilder zunächst im Speicher aufzubauen, generieren wir zwei Frambuffer, die das schwarze und das rote Bild speichern. Anfangs wirkt es etwas verwirrend, dass die zwei Farben nicht in einem Buffer gehalten werden.
Hierbei müssen Sie darauf achten, dass das Programm die Buffer in einer bestimmten Reihenfolge schreibt. Das bedeutet, falls bereits rot an einer Koordinate gesetzt ist, lässt sich dort kein schwarz mehr verwenden. Eine weitere spezielle Angewohnheit des Displays liegt in den Farbcodes. Wenn wir im fbBlack arbeiten, bedeutet der Farbcode 0, dass das Pixel schwarz erscheint, der Code 1 färbt das Pixel weiß. Im fbRed verhält es sich genau umgekehrt: Der Farbcode 0 ist ein weißes Pixel, der Farbcode 1 ein rotes.
Kommen wir jetzt zur Auswertung der Interrupts. Je nachdem, welchen der zwei Taster Sie drücken, laden Sie im dementsprechenden if-Zweig. Dieser erzeugt die Anzeige für das Display und setzt einen HTTP-Request an einen Webserver ab. In unserem Beispiel handelt es sich dabei um zwei einfache GET-Requests, die unterschiedliche Dateien auf dem Server aufrufen. Sie können sich hier genauso gut erheblich komplexere URLs zusammenbauen, die zusätzliche Informationen wie die Arbeitsplatznummer mit an den Server übertragen.
Das Programm müssen Sie im nächsten Schritt mit dem Namen main.py abspeichern, die der ESP32 damit automatisch beim Start des ESP32 ausführt. An dieser Stelle ein kleiner Warnhinweis: Wenn Sie mit der Deepsleep-Funktion arbeiten, sollten Sie immer das Kommando time.sleep() einbauen, bevor Sie den Controller in den Deepsleep-Modus versetzen. Während der Schlafenszeit lässt sich der Programmablauf mit Thonny unterbrechen. Das erlaubt es, das Programm immer wieder zu erweitern. Sobald sich der ESP32 im Deepsleep befindet, steht diese Funktion nicht mehr zur Verfügung. Es ist also tatsächlich möglich, den ESP32 in einen Modus zu versetzen, in dem er sich nicht mehr mit Thonny programmieren lässt. Dann hilft nur noch, die Mikropython-Firmeware neu aufzuspielen, was jedoch alle Programme im Controller löscht. Daher der Tipp: Immer mal wieder ein Backup auf dem PC speichern.
Listing 1
main.py
import sys
import os
import epd1in54b_V2
import time
import framebuf
import micropython
import array
import network
import socket
import machine
import esp32
ssid = "<YOUR_SSID>"
key = "<YOUR_PASSWORD>"
wakeUpOccupied = machine.Pin(4, machine.Pin.IN,machine.Pin.PULL_DOWN)
wakeUpFree = machine.Pin(15, machine.Pin.IN,machine.Pin.PULL_DOWN)
occupied=wakeUpOccupied.value()
free=wakeUpFree.value()
station = network.WLAN(network.STA_IF)
station.active(True)
print ("Connecting .",end="")
while not station.isconnected():
print (".",end="")
station.connect(ssid, key)
time.sleep(1)
print(" Connected!")
print("My IP Address:", station.ifconfig()[0])
epd = epd1in54b_V2.EPD()
epd.init()
#epd.Clear()
w=epd.width
h=epd.height
bufferBlack = bytearray(w * h // 8)
bufferRed = bytearray(w * h // 8)
fbBlack = framebuf.FrameBuffer(bufferBlack, w, h, framebuf.MONO_HLSB)
fbBlack.fill(1)
fbRed = framebuf.FrameBuffer(bufferRed, w, h, framebuf.MONO_HLSB)
fbRed.fill(0)
def printFree():
arr=array.array('h',[60,100, 45,115, 100,150, 160,40, 145,25, 95,120, 60,100])
fbBlack.ellipse(99,99,99,99,0,True) #schwarz
fbBlack.ellipse(99,99,91,91,1,True) #weiss
fbBlack.poly(0,10,arr,0,True)
def printOccupied():
arr=array.array('h',[0,20, 40,60, 0,100, 20,120, 60,80, 100,120, 120,100, 80,60, 120,20, 100,0, 60,40, 20,0])
fbBlack.ellipse(99,99,99,99,0,True) #Black
fbBlack.ellipse(99,99,91,91,1,True) #white
fbRed.ellipse(99,99,91,91,1,True)#red
fbRed.poly(38,38,arr,0,True)#white
wakeUpOccupied = machine.Pin(4, machine.Pin.IN,machine.Pin.PULL_DOWN)
wakeUpFree = machine.Pin(15, machine.Pin.IN,machine.Pin.PULL_DOWN)
esp32.wake_on_ext1(pins = (wakeUpOccupied,wakeUpFree), level = esp32.WAKEUP_ANY_HIGH)
s = socket.socket()
ai = socket.getaddrinfo("<YOUR_SERVER>", 80)
addr = ai[0][-1]
s.connect(addr)
if occupied:
print("Occupied")
printOccupied()
s.send(b"GET /occupied HTTP/1.0\r\n\r\n")
#print(s.recv(4096))
s.close()
if free:
print("Free")
printFree()
s.send(b"GET /free HTTP/1.0\r\n\r\n")
#print(s.recv(4096))
s.close()
print('Wating')
epd.display(bufferBlack,bufferRed)
time.sleep(5)
print('Deep Sleep')
machine.deepsleep()
Fazit
Dieses Projekt zeigt, dass sich auch Controller-spezifische Funktionen in Micropython-Programmen verwenden lassen. Programm und Hardware sind hierbei eher als Anregung zu sehen, um eine eigene Lösung für das Problem der Arbeitsplatzbelegung zu entwickeln. Interessant ist außerdem, das Verhalten von E-Paper-Displays ein wenig genauer zu untersuchen. Gerade die doch recht langen Refresh-Zeiten können anfangs für etwas Verwirrung sorgen. Der Autor wünscht Ihnen viel Spaß bei eigenen Experimenten mir E-Paper Displays und Micropython. (tle)
Infos
- E-Paper Display: https://www.amazon.de/gp/product/B0751NSSPV/
- ESP32 Dev-Board: https://www.amazon.de/gp/product/B07Z849GM6/
- Fritzing Homepage: https://fritzing.org/
- Micropython auf ESP32: Martin Mohr, “Kleine Schlange”, RPG 06/2022, S. 26, https://www.raspi-geek.de/47908
- Display-Treiber vom Hersteller:https://www.waveshare.com/wiki/1.54inch_e-paper_Module_Manual#Users_Guides_of_Raspberry_Pi





