MicroPython ist eine „schlanke“ Version von Python, die speziell für die effiziente Ausführung auf speicherbeschränkten Mikrocontrollern entwickelt wurde.
MicroPython ist sowohl eine lose typisierte als auch eine dynamisch typisierte Sprache. Variablen werden nicht explizit deklariert. Vielmehr wird eine Variable implizit deklariert, wenn sie zum ersten mal in einer Anweisung verwendet wird. Der Variablentyp wird zur Laufzeit bestimmt.
Die Regeln für die Benennung von Variablen sind einfach:
Das erste Zeichen muss ein Buchstabe oder ein Unterstrich ("_") sein.
Die folgenden Zeichen dürfen nur Buchstaben, Unterstriche und Ziffern (0 - 9) sein.
Bei MicroPython-Bezeichnern und Schlüsselwörtern wird zwischen Groß- und Kleinschreibung unterschieden.
Diese reservierten Wörter von MicroPython können nicht als Variablennamen verwendet werden:
and, del, global, not, with, as, elif, if, or, yield, assert, else, import, pass, False, break, except, in, raise, None, class, finally, is, return, True, continue, for, lambda, try, def, from, nonlocal, while
Ein MicroPython-Programm bricht ab, sobald es auf einen Fehler stößt, es sei denn, das Programm kann einen Mechanismus zur Wiederherstellung nutzen. In MicroPython kann es sich bei einem Fehler um einen Syntaxfehler oder eine Exception (Ausnahme) handeln.
Syntax-Fehler
Ein Syntaxfehler tritt auf, wenn MicroPython eine Anweisung erkennt, die in irgendeiner Weise nicht dem Sprachstandard entspricht.
# Dieses Programm wird mit einem Syntaxfehler beendet
phrase1 = 'Hallo!,'
phrase2 = 'Mein Name ist Emma.'
Satz = phrase1 + ' ' + phrase2
prnt(satz)`
Ausgabe:
Traceback (letzter Aufruf):
Datei „main.py“, Zeile 6, in <module>
NameError: Name 'prnt' ist nicht definiert
Findest du den Fehler?
Dir ist vielleicht aufgefallen, dass prnt in Wirklichkeit print sein sollte. Wenn man diesen Fehler im Code korrigiert und das Programm erneut ausführt, erhält man die erwartete Ausgabe.
Ausgabe:
Hallo! Mein Name ist Emma.
Exception-Error/Ausnahmefehler
Ein Exception-Error tritt immer dann auf, wenn syntaktisch korrekter MicroPython-Code zu einem Fehler führt. MicroPython verfügt über verschiedene eingebaute Exceptions (dargestellt als eine Hierarchie von Klassen) sowie über die Möglichkeit, selbst definierte Exceptions zu erstellen.
Ein Programm kann die Exception-Error abfangen und auf sie reagieren. Wenn das Programm die Ausnahme ignoriert, tritt das Standardverhalten von MicroPython bei der Behandlung von Exceptions in Kraft: Das Programm hält an und es wird eine Meldung ausgegeben.
Ausgabe:
# Ein Programm zur Berechnung der Fläche von
# Kreisen anhand des Radius berechnet.
# Es wird eine Liste von Kreisradien wird
# abgearbeitet, wobei die berechnete Fläche
# für jeden Kreis berechnet und ausgedruckt werden soll.
# Dieses Programm bricht mit
# einem Variablentypfehler ab.
from math import pi
# Definieren Sie eine Liste von Kreisradien
radii = [5, 3.15, 26, 'r', 69]
Ausgabe:
Radius = 5 : Area = 78.53982
Radius = 3.15 : Area = 31.17246
Radius = 26 : Area = 2123.717
Traceback (most recent call last):
File "main.py", line 13, in <module>
TypeError: can't convert 'int' object
to str implicitly
Die Ausnahme TypeError ist aufgetreten, weil die Zeichenkette 'r' (offensichtlich kein numerischer Wert) in der Liste der Kreisradien gefunden wurde.
Behandlung von Ausnahmen
MicroPython behandelt Ausnahmefehler auf ähnliche Weise wie viele andere Computersprachen mit dem Konstrukt try..except..else..finally. Die Syntax lautet in groben Zügen:
try:
Code-Block
except [exception_1, ...exception_n] [as err_obj]:
Code-Block
else:
Code-Block
finally:
Code-Block
try-Block
Jeder Code, bei dem Ausnahmen abgefangen und behandelt werden müssen, ohne dass MicroPython das Programm vorzeitig abbricht, sollte in einem try-Block erscheinen.
except-Block
Wenn in einem try-Block eine Ausnahme auftritt, übergibt MicroPython die Codeausführung an den except-Block. Dieser Code ist für die Behebung des Fehlers, die Protokollierung des Fehlers, die Benachrichtigung des Benutzers usw. verantwortlich.
Die accept-klausel hat verschiedene Fälle. Beispiele sind:
# Fall 1:Dies wird alle und jeden erfassen
except:
# Fall 2: Gibt eine einzige Ausnahmeart an
except ZeroDivisionError:
# Fall 3: Spezifiziert mehrere Ausnahmetypen
except (ZeroDivisionError, TypeError):
# Fall 4: Ausnahmedetails im Ausnahmeobjekt
except (ZeroDivisionError, TypeError) as err_obj:
Es ist sehr hilfreich, except mit einen Ausnahmetyp anzugeben und nicht so, wie im ersten Beispiel oben gezeigt.
Jeder try-Block kann auch mehr als einen except-Block enthalten. Zum Beispiel:
try:
code block
except ZeroDivisionError:
code block
except TypeError:
code block
Das Beispiel von Fall 4, aus den unterschiedlichen Darstellungen der der accept-Klausel wird üblicherweise verwendet. In dieser Form wird bei Auftreten einer Ausnahme das Fehlerdetail im Fehlerobjekt gefunden.
Betrachte dazu das folgende Beispiel:
# Demonstriert die Verwendung von error object
# in 'except'-Klausel.
# Summiert alle gültigen Zahlen in einer Liste.
# Jedes Element in einem nicht-numerischen Element
# in der Liste wird mit einer
# einer behandelten Ausnahme abgefangen.
# Definiere die Liste der zu summierenden Zahlen
list1 = [1, 2, 'p', 3, 4, 5]
sum = 0
for element in list1:
try:
sum += element
except (TypeError) as err_obj:
# Erhalte jeden nicht-numerischen Wert
# und behandle ihn. Die Programmausführung
# wird dann fortgesetzt.
print("Fehler bei Artikel '", element, "'")
print(err_obj)
print('Die Verarbeitung wird fortgesetzt...')
print('Summe der Zahlen:', sum)
Ausgabe
Fehler bei Element ' p '
nicht unterstützte Typen für __iadd__: 'int', 'str'
Die Verarbeitung wird fortgesetzt...
Summe der Zahlen: 15
Wenn das nicht-numerische p erreicht ist, wird eine Ausnahme ausgelöst. Der except-Block behandelt den Fehler, dann läuft das Programm weiter. Das Fehlerobjekt err_obj enthält die Beschreibung des Fehlers und wird in diesem Fall einfach zur Information der Benutzer ausgedruckt.
else-Block
Der else-Block wird nur ausgeführt, wenn der try-Block abgeschlossen wurde, ohne dass eine Ausnahme ausgelöst wurde. Er ist optional, d.h. es ist keine sprachliche Anforderung, dass ein try..except-Konstrukt eine else-Klausel haben muss.
finally-Block
Der finally-Codeblock wird immer ausgeführt, unabhängig davon, ob im try-Block eine Ausnahme ausgelöst wurde. Er ist ebenfalls optional.
Das vorherige Beispiel wurde umgeschrieben, um die TypeError-Ausnahme zu erfassen und programmatisch zu behandeln.
Das nächste wird nun unter Programmkontrolle beendet. Dies ist eine Verbesserung gegenüber Beispiel 2A, das durch MicroPythons Standardmechanismus zur Behandlung von Ausnahmen gestoppt wurde.
Es gibt jedoch immer noch ein Problem. Nachdem das Programm die TypeError-Ausnahme behandelt hat, setzt es die Verarbeitung der Kreisradien nicht fort. Sobald der try-Block für den Eintritt in den except-Block verlassen wurde, kann die Programmausführung nicht mehr in den try-Block zurückkehren.
# Demonstriert die Verwendung von 'try..except'
# um jeden Fehler zu behandeln.
# Ein Programm zur Berechnung der Fläche eines Kreises
# anhand des Radius.
# Es wird eine Liste von Kreisradien verarbeitet
# und die Fläche für jeden Kreis berechnet
# dann ausgedruckt.
from math import pi
# Kreisradien
radii = [5, 3.15, 26, 'p', 69]
complete = False
try:
for radius in radii:
Fläche = pi * Radius ** 2
print('R =', radius, ': A =', area)
vollständig = Wahr
except (ZeroDivisionError, TypeError) as error:
print(„Fehler bei Element:‚“, radius, „‘“)
print(error)
else:
print('Alle Elemente erfolgreich verarbeitet')
finally:
if complete:
print('Verarbeitung abgeschlossen')
else:
print('Verarbeitung abgebrochen')
Ausgabe:
R = 5 : A = 78.53982
R = 3.15 : A = 31.17246
R = 26 : A = 2123.717
Error with element:' p '
can't convert 'int' object to str implicitly
Processing halted
Das folgende Beispiel behebt dieses Problem, indem die for-Schleife aus dem try-Block entfernt wird:
# Demonstriert die Verwendung von 'try..except'
# um jeden Fehler zu behandeln. Ein Fehler wird
# nicht zum Abbruch des Programms führen.
# Ein Programm zur Berechnung der Fläche eines Kreises
# mit dem Radius.
# Es wird eine Liste von Kreisradien verarbeitet
# und die Fläche für jeden Kreis berechnet
# dann ausgedruckt.
from math import pi
# Kreisradien
radii = [5, 3.15, 26, 'p', 69]
Fehler = 0
for radius in radii:
try:
Fläche = pi * Radius ** 2
print('R =', radius, ': A =', area)
except TypeError as error:
print(„Fehler bei Element:‚“, radius, „‘“)
print(error)
fehler += 1
print('Verarbeitung abgeschlossen:', errors, 'error(s)')
Ausgabe:
R = 5 : A = 78,53982
R = 3,15 : A = 31,17246
R = 26 : A = 2123.717
Fehler bei Element:' p '
kann 'int'-Objekt nicht implizit nach str konvertieren
R = 69 : A = 14957.12
Verarbeitung abgeschlossen: 1 Fehler(s)
BEFEHLE
Im Calliope mini Python Editor python.calliope.cc können alle nutzbaren Befehle auch direkt im Bereich API gefunden werden.
Wichtige Teile der API finden sich ebenfalls hier:
MODUL
from calliope mini import *
Mit dem "calliopemini" Modul hast du Zugriff auf die gesamte Hardware, die im Calliope mini eingebaut ist.
PANIC
panic(n)
Ruft einen Panikmodus auf, der die gesamte Ausführung stoppt, einen Fehlercode auf der Calliope mini-Matrix anzeigt und einen Neustart erfordert:
Parameter:
n - Eine beliebige ganze Zahl zwischen 0 und 255 zur Angabe eines Fehlercodes.
ZURÜCKSETZEN
reset()
Startet den Calliope mini neu.
LAUFZEIT
running_time()
Die Zeit seit dem Einschalten oder Neustart in Millisekunden.
KONVERTIEREN
scale(value, from_, to)
Konvertiert einen Wert aus einem Bereich in einen anderen Bereich.
Zum Beispiel, um 30 Grad von Celsius in Fahrenheit umzurechnen:
temp_fahrenheit = scale(30, from_=(0.0, 100.0), to=(32.0, 212.0))
Dies kann nützlich sein, um Werte zwischen Eingängen und Ausgängen zu konvertieren, z. B. einen Beschleunigungsmesserwert in eine Lautsprecherlautstärke.
Wenn eine der Zahlen im Parameter to eine Fließkommazahl ist (z. B. eine Dezimalzahl wie 10.0), gibt die Funktion eine Fließkommazahl zurück. Handelt es sich bei beiden um ganze Zahlen (z. B. 10), gibt sie eine ganze Zahl zurück:
returns_int = scale(accelerometer.get_x(), from_=(-2000, 2000), to=(0, 255))
Negative Skalierung wird ebenfalls unterstützt, zum Beispiel liefert
scale(25, from_=(0, 100), to=(0, -200)) -50
als Ergebnis -50 zurück.
Parameter:
value - Eine zu konvertierende Zahl.
from - Ein Tupel, um den Bereich zu definieren, aus dem konvertiert werden soll.
bis - Ein Tupel, um den Bereich zu definieren, in den konvertiert werden soll.
Rückgabe:
Der in den Bereich bis umgewandelte Wert.
LAUTSPRECHER
set_volume(volume)
Konfiguriere die Ausgangslautstärke des Calliope mini Lautsprechers und der Pins:
Parameter:
volume - Eine ganze Zahl zwischen 0 und 255 zur Einstellung der Lautstärke.
PAUSE
sleep(n)
Warte für n Millisekunden.
Eine Sekunde entspricht 1000 Millisekunden, so dass sleep(1000) die Ausführung eine Sekunde lang unterbricht.
Parameter:
n - Eine Ganzzahl oder Fließkommazahl, die die Anzahl der zu wartenden Millisekunden angibt.
PLANER
run_every(callback, days=None, h=None, min=None, s=None, ms=None)
Plan für die Ausführung einer Funktion in dem durch die Zeitargumente angegebenen Intervall.
run_every kann dabei auf zwei Arten verwendet werden:
Als Decorator - wird über die zu planende Funktion gelegt. Zum Beispiel:
@run_every(days=1, h=1, min=20, s=30, ms=50)
def my_function():
# Do something here
Als Funktion - Übergabe des Rückrufs als Positionsargument. Zum Beispiel:
def my_function():
# Do something here
run_every(my_function, s=30)
Jedes Argument entspricht einer anderen Zeiteinheit und sie sind additiv. Mit run_every(min=1, s=30) wird der Zeitplan also auf einen Aufruf für jede anderthalb Minuten gesetzt.
Wenn innerhalb dieser Funktion eine Ausnahme ausgelöst wird, wird die Funktion abgebrochen.
Um dies zu vermeiden, können Ausnahmen mit try/except abfangen werden.
Parameter:
callback - Funktion, die in dem angegebenen Intervall aufgerufen wird.
days - Legt die Tagesmarke für die Terminierung fest.
h - Legt die Stundenmarkierung für die Terminierung fest.
min - Legt die Minutenmarkierung für die Terminierung fest.
s - Legt die Sekundenmarke für die Terminierung fest.
ms - Legt die Millisekundenmarkierung für die Terminierung fest."
TEMPERATUR
temperature()
Rückgabe:
Eine Ganzzahl der vom Calliope mini gemessenen Temperatur in Grad Celcius.