MicroPython: Nicht-blockierende Eingabe

In MicroPython steht zur Eingabe von Text, Zahlen und Zeichen auf der Kommandozeile bzw. Shell der input-Befehl zur Verfügung.
Der input-Befehl hat den Nachteil, dass er die weitere Programmausführung blockiert. Der input-Befehl wartet auf die Eingabe des Benutzers. Erst wenn der Benutzer seine Eingabe getätigt und auf „Return“ gedrückt hat, geht es im laufenden Programm weiter.

Die Frage ist, wie man eine Nicht-blockierende Eingabe ermöglicht. Das heißt, ein Programm läuft und es ist auf der Kommandozeile trotzdem möglich, eine Eingabe zu tätigen. Beispielsweise um Parameter oder Kommandos über die Kommandozeile einzugeben und vom Programm auswerten zu lassen.

  • Idee 1: Nicht-blockierende Eingabe mit „_thread“
  • Idee 2: Nicht-blockierende Eingabe mit „stdin“

Nicht-blockierende Eingabe mit „_thread“

Mancher Mikrocontroller, wie zum Beispiel der RP2040 vom Raspberry Pi Pico, hat einen zweiten Kern. Wenn man bisher mit diesem noch nicht so viel anzufangen wusste, dann ist das Warten auf eine Benutzereingabe eine tolle Aufgabe für den ersten Kern, während der zweite Kern die reguläre Arbeit macht. Man könnte das natürlich auch umgekehrt realisieren.

Im folgenden Programmcode lassen wir die Onboard-LED blinken. Um diese Aufgabe kümmert sich der zweite Kern. Der erste Kern wartet auf die Eingabe mit einem input-Befehl. Diese Eingabe ändert den Wert der Wartezeit zwischen dem Umschalten von An und Aus der LED. Das beeinflusst die Blinkgeschwindigkeit.

# Bibliotheken laden
import machine
import time
import _thread

# Initialisierung der Onboard-LED
led_onboard = machine.Pin(25, machine.Pin.OUT, value=0)

# Wartezeit für das Blinken
waiting = 1

# Funktion: Blinkende LED
def blink():
    global waiting
    while True:
        # LED einschalten
        led_onboard.on()
        # halbe Sekunde warten
        time.sleep(waiting)
        # LED ausschalten
        led_onboard.off()
        # 1 Sekunde warten
        time.sleep(waiting)

# Funktion aufrufen und vom 2. Kern ausführen lassen
_thread.start_new_thread(blink, ())

# Hauptprogramm für die Benutzereingabe
while True:
    value = input('Wartezeit für das Blinken eingeben (1 - 9): ')
    try:
        value = int(value)
        if value > 0 and value < 10:
            waiting = value
            print('Wartezeit geändert')
        else:
            print('Eingegebener Wert außerhalb des Wertebereichs')
    except ValueError as e:
        print('Bitte nur Zahlen zwischen 1 und 9 eingeben')

Hinweis: Die Nutzung des zweiten Kerns mit „_thread“ in MicroPython gilt als experimentell und wird im produktiven Einsatz nicht empfohlen.

Nicht-blockierende Eingabe mit „stdin“

„stdin“ ist eine Abkürzung für "standard input" und bezieht sich auf die Standard-Eingabe einer Anwendung. Wenn man zum Programmieren eine IDE verwendet, die über eine Kommandozeile/Shell verfügt, dann ist das die „stdin“. Normlerweise würde man die „stdin“ über den input-Befehl abfragen. Hier versuchen wir uns an einer eigenen Implementierung, um an die Daten der „stdin“ heranzukommen.

Im folgenden Programmcode lassen wir die Onboard-LED blinken. Gleichzeitig müssen wir auf die Dateneingabe von „stdin“ auf der Kommandozeile warten. Mit der Eingabe wird die Wartezeit für das Umschalten zwischen An und Aus geändert.

# Bibliotheken laden
import machine
import sys
import uselect as select
import time

# Initialisierung der Onboard-LED
led_onboard = machine.Pin(25, machine.Pin.OUT, value=0)

# Wartezeit für das Blinken
waiting = 1
pause = waiting

# Tastatur-Eingabe
spoll = select.poll()
spoll.register(sys.stdin, select.POLLIN)

# Funktion: Eingabe lesen
def eingabe():
    return(sys.stdin.read(1) if spoll.poll(0) else None)

# Endlos-Schleife
print('Wartezeit für das Blinken eingeben:')
while True:
    value = eingabe()
    if value != None and value != chr(10):
        # process input as needed
        try:
            value = int(value)
            if value > 0 and value < 10:
                waiting = 1 * value
                pause = waiting
                print('Wartezeit geändert')
            else:
               print('Eingegebener Wert außerhalb des Wertebereichs')
        except ValueError as e:
           print('Bitte nur Zahlen zwischen 1 und 9 eingeben')
        finally:
            print('Wartezeit für das Blinken eingeben:')
    if pause <= 0:
        led_onboard.toggle()
        pause = waiting
    pause -= 0.1
    time.sleep(0.1)

In der Thonny Python IDE: Zur Eingabe muss der Cursor in der Kommandozeile aktiv sein. Dazu muss in der Kommandozeile unten in eine leere Zeile geklickt werden. Wenn dort der Cursor blinkt, kann eine Taste auf der Tastatur betätigt werden. Die Eingabe wird angezeigt. Aber erst mit dem Drücken von „Enter“ bzw. „Return“ wird die Eingabe übernommen.

„_thread“ vs. „stdin“

Die Lösung mit „_thread“ ist von der Seite her charmant, weil man einfach den input-Befehl verwenden kann und gleichzeitig noch den vorhandenen zweiten Kern im RP2040-Mikrocontroller nutzen kann. Wenn der experimentelle Status von „_thread“ nicht stört, dann ist das vermutlich die einfachste Lösung.
Die Lösung mit „stdin“ ist deutlich komplexer. Im Prinzip baut man dabei den input-Befehl nach, was in gewisser Weise fragwürdig ist. Warum soll man etwas programmieren, was es schon gibt und gut funktioniert. Leider hat der input-Befehl besagte Einschränkungen, weshalb eine eigene Lösung die Anforderungen besser meistert kann.
Beide Lösungen haben leider den Nachteil, dass die Eingabe erst mit „Enter“ bzw. „Return“ übernommen wird.

Weitere verwandte Themen:

Frag Elektronik-Kompendium.de

Hardware-nahes Programmieren mit dem Raspberry Pi Pico und MicroPython

Elektronik-Set Pico Edition

Das Elektronik-Set Pico Edition ist ein Bauteile-Sortiment mit Anleitung zum Experimentieren und Programmieren mit MicroPython.

  • LED: Einschalten, ausschalten, blinken und Helligkeit steuern
  • Taster: Entprellen und Zustände anzeigen
  • LED mit Taster einschalten und ausschalten
  • Ampel- und Lauflicht-Steuerung
  • Elektronischer Würfel
  • Eigene Steuerungen programmieren

Elektronik-Set jetzt bestellen Online-Workshop buchen

Online-Workshop: Programmieren mit dem Raspberry Pi Pico

Programmieren mit dem Raspberry Pi Pico

Gemeinsam mit anderen und unter Anleitung experimentieren? Wir bieten unterschiedliche Online-Workshops zum Raspberry Pi Pico und MicroPython an. Einführung in die Programmierung, Sensoren programmieren und kalibrieren, sowie Internet of Things und Smart Home über WLAN und MQTT.

Online-Workshop buchen

Besuchen Sie unser fast monatlich stattfindendes Online-Meeting PicoTalk und lernen Sie uns kennen. Die Teilnahme ist kostenfrei.

Termine und Newsletter-Anmeldung

 

Elektronik-Sets für das Hardware-nahe Programmieren