Aus Raspberry Pi Geek 09/2023

I2C-Displays mit dem ESP32 ansteuern (Seite 2)

Listing 2

config.py

OLED_WIDTH = 128
OLED_HEIGHT = 32
I2C_1_SDA = 33
I2C_1_SCL = 32
I2C_2_SDA = 26
I2C_2_SCL = 25
FILENAME = 'data.txt'
INPUT = 14
PASS = 'Train'
SSID = 'Train'

Alle für die Anzeige auf den Displays zuständigen Funktionen fasst die Datei display.py (Listing 3) zusammen. Der Code aktiviert die zwei I2C-Schnittstellen, liest die Texte aus der Datei data.txt und stellt sie auf den beiden Displays dar. Die Variable direction steuert dabei, welche Zeile aus der Datei auf den Displays erscheint.

Aktuell arbeitet das Programm nur mir zwei Texten, die sich über den Eingang cfg.INPUT wechseln lassen. Der Eingang ist dazu gedacht, von einer Steuerplatine der Lok verwendet zu werden (Open-Collector-Ausgang). Der Taster, den wir hier zum Test angeschlossen haben, kann prellen, sodass die Anzeige beim Umschalten eventuell flackert.

Listing 3

display.py

import config as cfg
from machine import SoftI2C,Pin
from writer import Writer
import freesans31
import ssd1306
class Display:
  def show(direction):
    i2c1 = SoftI2C(scl=Pin(cfg.I2C_1_SCL), sda=Pin(cfg.I2C_1_SDA))
    i2c2 = SoftI2C(scl=Pin(cfg.I2C_2_SCL), sda=Pin(cfg.I2C_2_SDA))
    oled1 = ssd1306.SSD1306_I2C(cfg.OLED_WIDTH, cfg.OLED_HEIGHT, i2c1)
    oled2 = ssd1306.SSD1306_I2C(cfg.OLED_WIDTH, cfg.OLED_HEIGHT, i2c2)
    file = open(cfg.FILENAME)
    lines=file.read()
    file.close()
    line=lines.split("\n")
    wri1 = Writer(oled1, freesans31)
    wri2 = Writer(oled2, freesans31)
    Writer.set_textpos(oled1, 0, 0)
    Writer.set_textpos(oled2, 0, 0)
    wri1.printstring(line[direction])
    wri2.printstring(line[direction])
    oled1.show()
    oled2.show()

Kommen wir jetzt zur Datei, die alle Abläufe für den Zielanzeiger steuert. Angelehnt an die englische Bezeichnung Train Direction Indicator lautet der Dateiname tdi.py (Listing 4). Im Kern startet das Programm einen Access Point und einen einfach aufgebauten Webserver ohne Bibliotheken. Letzterer erlaubt es, die Einträge in der Datei data.txt zu ändern. Zum Testen starten Sie die Datei tdi.py über die Python-IDE Thonny. Wenn Sie möchten, dass das Programm beim Einschalten automatisch mitlädt, speichern Sie es unter dem Namen main.py.

Um Zugriff auf den Webserver zu erlangen, verbinden Sie sich zunächst mit dem Access Point des ESP32. Die Zugangsdaten legen Sie in der Datei config.py unter SSID und PASS fest. Nachdem die Verbindung zum ESP32 steht, öffnen Sie einen Webbrowser und geben die IP-Adresse des Webservers ein, etwa http://192.168.4.1. Jetzt sollten Sie die Webseite zum Ändern der Einträge sehen (Abbildung 3).

Abbildung 3: Der rudiment&auml;re Webserver erlaubt es, Eintr&auml;ge in der <code>data.txt</code> zu &auml;ndern. Dieses File enth&auml;lt die im Display angezeigten Begriffe.

Abbildung 3: Der rudimentäre Webserver erlaubt es, Einträge in der data.txt zu ändern. Dieses File enthält die im Display angezeigten Begriffe.

Listing 4

tdiv2.py

from machine import Pin
import config as cfg
import display
from time import sleep
import network
import socket
accesspoint = network.WLAN(network.AP_IF)
accesspoint.active(True)
accesspoint.config(password=cfg.PASS,essid=cfg.SSID)
while accesspoint.active() == False:
  sleep(1)
print('Connection successful')
accesspoint.ifconfig(('192.168.4.1' , '255.255.255.0' , '192.168.4.1' , '192.168.4.1'))
print(accesspoint.ifconfig())
def handle_interrupt(pin):
  d = display.Display
  d.show(switch.value())
switch = Pin(cfg.INPUT, Pin.IN, Pin.PULL_UP)
switch.irq(trigger=3, handler=handle_interrupt)
html = """<!DOCTYPE html>
<html>
  <head> <title>Train Config</title> </head>
  <body>
   <form action="/" method=get>
    Destination 1: <input name ='0' type='text'><br>
    Destination 2: <input name ='1' type='text'><br>
    <input type='submit' value='Submit'>
   </form>
  </body>
</html>
"""
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('listening on', addr)
handle_interrupt(cfg.INPUT)
while(True):
  conn, addr = s.accept()
  print('client connected from', addr)
  request = conn.recv(1024)
  request = str(request)
  p=""
  i=request.find ('?') + 1
  print(i)
  if (i !=0 ):
    while(request[i]!=' '):
      if (request[i]=='\\'): break
      p+=request[i]
      i+=1
      param = p.split('&')
      dest1 = param[0].split('=')[1]
      dest2 = param[1].split('=')[1]
      if (dest1!=''):
        f = open("data.txt", "w")
        f.write(dest1+"\n")
        f.write(dest2+"\n")
        f.close()
  d = display.Display
  d.show(1)
  conn.send('HTTP/1.1 200 OK\n')
  conn.send('Content-Type: text/html\n')
  conn.send('Connection: close\n\n')
  conn.send(html)
  conn.close()

Tipps

Wenn Sie beginnen, das Programm an Ihre Bedürfnisse anzupassen, kann es hin und wieder zu kleinen Problemen kommen. Manchmal verabschiedet sich das Programm etwa mit der Ausrede EADDRINUSE. Der Grund dafür liegt darin, dass trotz sauberen Beenden des Programms noch Teile davon in den Untiefen des ESP32 laufen und die WLAN-Schnittstelle blockieren. Hier hilft tatsächlich nur ein Hardware-Reset, den Sie über den Taster auf dem Dev-Board ausführen. Interessanterweise ist der Reset-Taster auf vielen Dev-Boards mit EN (Enable) beschriftet.

Sehr selten tritt das recht nervige Problem auf, dass das Programm nicht die aktuell gespeicherten Dateien verwendet. Sollte das bei Ihnen der Fall sein, hilft auch hier im Zweifelsfall ein Hardware-Reset. Sollte das nicht der Fall sein, beenden Sie die IDE, trennen den ESP32 kurz vom Strom, und stecken ihn danach wieder an. Jetzt starten Sie die IDE erneut, damit alles wieder so läuft wie gewohnt.

Fazit

Dieses Projekt zeigt sehr gut, dass man nicht zwangsläufig C oder Assembler als Programmiersprache für Mikrocontroller verwenden muss. Es gibt viele Anwendungen, bei denen man mit MicroPython schon sehr weit kommt. Kommt es allerdings auf Geschwindigkeit oder präzises Timing an, schneidet MicroPython eher schlecht ab. Oftmals erweisen sich die MicroPython-Bibliotheken sogar als flexibler als die in anderen Programmiersprachen. Beispielhaft seien hier die Softwareimplementierungen der I2C- und SPI-Schnittstellen genannt. Unsere Zugzielanzeige bietet Bastlern viel Raum für zusätzliche Erweiterungen. Der ESP32 hat selbst beim Betrieb mit MicroPython noch ausreichend CPU-Reserven, um einiges an Erweiterungen bedienen zu können. (tle)

Der Autor

Martin Mohr hat die komplette Entwicklung der modernen Computertechnik live miterlebt. Nach dem Studium entwickelte er überwiegend Java-Applikationen. Mit dem Raspberry Pi erwachte seine alte Liebe zur Elektronik wieder.

Infos

  1. 0,91-Zoll-I2C-Display: https://www.amazon.de/gp/product/B07BDFXFRK/
  2. ESP32 NodeMCU Development Board: https://www.amazon.de/AZDelivery-unverl%C3%B6tet-Development-Nachfolgermodell-inklusive/dp/B08BTWJGFX/
  3. MicroPython auf dem ESP32: Martin Mohr, “Kleine Schlange”, RPG 06/2022, S. 26, https://www.raspi-geek.de/47908
  4. Dateien zum Artikel: https://www.linux-user.de/dl/49271
  5. Display-Bibliothek: https://github.com/stlehmann/micropython-ssd1306
  6. Bibliothek zur Textdarstellung: https://github.com/peterhinch/micropython-font-to-py/blob/master/writer/writer.py
  7. Erzeugen von Fonts für writer.py: https://github.com/peterhinch/micropython-font-to-py
DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 5 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
RASPBERRY PI GEEK KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Raspberry Pi Geek bei Google Play Readly Logo
Nach oben