Raspberry Pi Pico: Autostart mit Abbruch, Fehlerbehandlung und Neustart

Um ein Programm auf dem Raspberry Pi Pico automatisch starten zu lassen, muss das Programm auf dem Pico mit dem Dateinamen „main.py“ gespeichert werden. Bei einem Neustart wird die Datei automatisch ausgeführt.

Es ist eine gängige Methode einen Programmcode einfach in der Datei "main.py“ zu speichern. Die Erfahrung lehrt jedoch, dass das keine gute Idee ist. Auch die offizielle MicroPython-Dokumentation empfiehlt eine andere Methode.

Es ist empfehlenswert, den Programmcode in einer Datei mit einem anderen Namen zu speichern und mit einem „import dateiname“ (ohne .py-Dateiendung) in der Datei "main.py“ ausführen zu lassen. Das hat den Vorteil, dass man das Hauptprogramm um Funktionen erweitern kann, die man nur mit Mühe integrieren kann. Beispielsweise der Autostart mit Abbruch-Funktion oder eine Fehlerbehandlung mit Reset bzw. Neustart.
Das sind Funktionen, die man beim Programmieren des Hauptprogramms nicht braucht und bei Bedarf mit Mühe nachträglich einprogrammieren müsste.

  • Autostart mit Abbruch-Funktion: Die Idee ist, im Programmcode ziemlich am Anfang eine Möglichkeit einzubauen, um mit dem Drücken eines Tasters den Abbruch des Programmcodes und einen Ausstieg zur REPL zu ermöglichen, um zum Beispiel Änderungen am Programmcode mit der Thonny Python IDE vorzunehmen.
  • Fehlerbehandlung: Meistens sorgt man beim Programmieren für optimale Bedingungen. Die Stromversorgung ist stabil (durch den Host-Computer), alle Kabelverbindungen zu den externen Geräten sind korrekt und die Verbindung zum WLAN ist hergestellt. Und selbst der Stand-alone-Betrieb funktioniert problemlos und fehlerfrei. Doch irgendwann gibt es einen unerwarteten Fehler, weshalb der Raspberry Pi Pico die weitere Ausführung des Programmcodes beendet. Um diesen Abbruch zu verhindern, muss eine Fehlerbehandlung implementiert werden.
  • Logging: Schön wäre es, man könnte später noch mal nachsehen, was einen Fehler verursacht hat. Dann kann man auch im Nachgang kritische Fehler korrigieren. Dazu muss die Fehlermeldung in eine Datei geschrieben werden, damit man sich das später noch mal ansehen kann.
  • Neustart: Und wenn wir schon eine Fehlerbehandlung implementiert haben, dann wollen wir bei Bedarf auch einen Neustart vornehmen, damit ein manueller Neustart vermieden wird.

Wer so etwas versucht zu implementieren wird auf verschiedene Probleme stoßen. Beispielsweise kann ein automatischer Reset dazu führen, dass man auf einen Pico mit Thonny keinen Zugriff mehr bekommt und auf Werkseinstellungen zurückgestellt werden muss und dabei der Programmcode verloren geht.

Insbesondere ein unbedacht ausgeführter Reset kann dazu führen, dass man den Raspberry Pi Pico so blockiert, dass er sich nicht mehr programmieren lässt, weil er in einer Reset-Schleife steckt.

Wichtig ist deshalb, dass im Fehlerfall trotz Autostart und Reset/Neustart eine manuelle Unterbrechung noch möglich ist.

Programmcode für die Datei „main.py“

Der folgende Programmcode vereint die beschriebenen Funktionen. Um diese Funktionen zu nutzen speichert man das eigentliche Hauptprogramm in einer Datei mit einen beliebigen Dateinamen, der auf „.py“ endet. Den folgenden Programmcode speichert man in der Datei "main.py“ und ersetzt „test“ in der Zeile „import test“ durch den Dateinamen ohne die Dateiendung „.py“ des Hauptprogramms.

Wichtig: Beim Einbinden von Programmcode mit „import“ ist darauf zu achten, dass der Dateiname keine Leerzeichen, Punkte und Bindestriche enthält, weil es sonst nicht funktioniert.
Es sollte ein möglichst kurzer, vollständig kleingeschriebener Name sein. Nur mit Unterstrichen kann man die Lesbarkeit verbessern.

# Bibliotheken laden
import machine
import time

# GPIO 0 (Pin 1) für manuellen Abbruch (PULL_UP=1/True)
RUN = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)

# Initialisierung des GPIOs abwarten!
time.sleep(1)

if not RUN():
    print("Programmcode durch GPIO 0 gegen GND beendet")
else:
    # Fehlerbehandlung
    try:
        # Hauptprogramm: /test.py
        import test
    except KeyboardInterrupt:
        # Unterbrechung durch Host-Computer (z. B. CTRL+C oder Thonny-STOP)
        print("Programmcode mit CTRL+C oder STOP beendet")
    except Exception as error:
        # Ausgabe der Fehlermeldung
        print("Fehler:", error)
        # Ausgabe der Fehlermeldung in eine Datei
        with open('error.txt', 'w') as file: file.write(str(error))
    # Reset/Neustart
    time.sleep(1)
    print("Neustart")
    time.sleep(3) # !!!
    machine.reset()

Um diesen Programmcode in der Autostart-Datei "main.py“ ausprobieren zu können, folgt ein beispielhafter Programmcode für die Datei „test.py“, der als Hauptprogramm verwendet werden kann, das nach etwa 9 Sekunden einen Fehler und damit einen Abbruch des Programms provoziert.

Dieses Test-Programm lässt die Onboard-LED blinken.

# Bibliotheken laden
import machine
import time

# Onboard-LED
led_onboard = machine.Pin('LED', machine.Pin.OUT, value=1)

# Variable für die Laufzeitmessung
lifetime = time.ticks_ms()

# Hauptprogramm
while True:
    time.sleep(1)
    led_onboard.toggle()
    # Codezeile, die zu einem Fehler führt  (nach 9 Sekunden)
    if time.ticks_ms()-lifetime > 9000: x = 1 / 0

Programmcode im Detail erklärt

Im folgenden wird der Programmcode für die Datei „main.py“ im Detail erklärt.

# Bibliotheken laden
import machine
import time

# GPIO 0 (Pin 1) für manuellen Abbruch (PULL_UP=1/True)
RUN = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)

# Initialisierung des GPIOs abwarten!
time.sleep(1)
  1. Zuerst werden die Module „machine“ und „time“ geladen. Die werden in den darauffolgenden Zeilen gebraucht.
  2. Anschließend wird der GPIO 0 (Pin 1 auf dem Pico-Board) als Eingang mit einem internen Pullup-Widerstand initialisiert. Dadurch führt dieser Eingang im Grundzustand logisch „1“.
  3. Dann macht der Programmcode ein Sekunde eine Pause. Die ist deshalb notwendig, weil das tatsächlich Initialisieren des GPIOs länger dauert und der Pico die nächsten Programmcodezeile ausführt, bevor die Initialisierung abgeschlossen ist. Das ist aber wichtig für den nächsten Schritt im Programmcode.
if not RUN():
    print("Programmcode durch GPIO 0 gegen GND beendet")

Die erste Funktion im Programmcode ist die Möglichkeit, den Autostart in der Datei "main.py“ abzubrechen, wenn der GPIO 0 (Pin 1) mit GND (z. B. Pin 3) verbunden ist. Diese Verbindung kann man mit einem gedrückten Taster oder einer Drahtbrücke realisieren. Das ist deshalb sinnvoll, weil man nur so die Ausführung der Datei main.py wirkungsvoll unterbrechen kann.

else:
    # Fehlerbehandlung
    try:
        # Hauptprogramm: /test.py
        import test
    except KeyboardInterrupt:
        # Unterbrechung durch Host-Computer (z. B. CTRL+C oder Thonny-STOP)
        print("Programmcode mit CTRL+C oder STOP beendet")
    except Exception as error:
        # Ausgabe der Fehlermeldung
        print("Fehler:", error)
        # Ausgabe der Fehlermeldung in eine Datei
        with open('error.txt', 'w') as file: file.write(str(error))
    # Reset/Neustart
    time.sleep(1)
    print("Neustart")
    time.sleep(3) # !!!
    machine.reset()

Wenn die Programmausführung nicht abgebrochen werden soll, dann folgt der Aufruf des Hauptprogramms durch „import“, dass sich in einer anderen Datei befindet. Das hat den Vorteil, dass alle Funktionen rund um den Stand-alone-Betrieb unabhängig vom Hauptprogramm implementiert werden können. Beispielsweise die Fehlerbehandlung und der Neustart.

  1. Die Fehlerbehandlung wird mit dem „try“-Block eingeleitet, in dem sich der Programmcode befindet, der auf Fehler überwacht werden soll. Das ist in diesem Fall die Ausführung der Datei „test.py“, bei dem es sich um unser Hauptprogramm handelt.
  2. Mit „except“ wird ein Fehler bzw. eine Ausnahme behandelt. Im ersten „except“ wird die manuelle Unterbrechung durch den Nutzer in der Thonny Python IDE abgefangen. Eigentlich ist das kein richtiger Fehler. Trotzdem führt es zur Beendigung des Programmcodes mit einem Fehler. Dieser Fehler führt NICHT dazu, dass der Programmcode neu gestartet wird. Der Programmcode wird tatsächlich beendet.
  3. Das zweite „except“ behandelt jeden anderen Fehler, der auftritt. Der Fehlertext wird auf der Kommandozeile ausgegeben und zusätzlich in eine Datei geschrieben. Die Datei wird dabei überschrieben und enthält nur den Text des letzten Fehlers.
  4. Am Ende, aber noch im „else:“-Block, wird der Neustart ausgeführt. Besonders wichtig ist hierbei, dass vor dem eigentlichen „machine.reset()“ eine Wartezeit vorhanden ist. Dadurch ist sichergestellt, dass man den Programmcode noch manuell abbrechen kann, bevor der Neustart erfolgt.

Fehlermeldung in der Thonny Python IDE

In der Thonny Python IDE erscheint folgender Fehler:

PROBLEM IN THONNY'S BACK-END: Exception while handling 'Run' (ConnectionError: read failed: [Errno 6] Device not configured).
See Thonny's backend.log for more info.
You may need to press "Stop/Restart" or hard-reset your MicroPython device and try again.

Die Fehlermeldung erscheint nachdem der Raspberry Pi Pico offensichtlich einen Reset ausgelöst hat und ein Neustart erfolgen soll. Doch dieser Neustart erfolgt niemals.

Was passiert da? Wenn man mit „machine.reset()“ einen Reset auslöst, dann startet der Pico sofort neu, ohne Thonny vorher Bescheid zu geben. Da Thonny die Verbindung verliert, wirft es einen Verbindungsfehler aus. Das ist normal und kein schwerwiegender Fehler. Man kann das ignorieren. Das Problem dabei ist nur, dass ein Reset, aber kein wirklicher Neustart erfolgt.

Erweiterungen der Datei main.py

Es geht darum, Funktionen die normalerweise im Hauptprogramm enthalten sind, in die Datei "main.py“ auszulagern. Die Gründe dafür können unterschiedlich sein. Beispielsweise um die Übersicht im Hauptprogramm zu wahren.

Beispiele:

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