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:
- MicroPython: REPL - Read-Eval-Print-Loop
- MicroPython: Eingabe und Ausgabe von Text
- MicroPython: Verzweigungen mit Bedingungen
- MicroPython: _thread
Teilen:
Hardware-nahes Programmieren mit dem Raspberry Pi Pico und MicroPython
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
Online-Workshop: 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.
Für Ihre Fragen zu unseren Online-Workshops mit dem Raspberry Pi Pico besuchen Sie unseren PicoTalk (Online-Meeting). (Headset empfohlen)