Wer heute Microcontroller programmiert, verwendet dafür meistens C/C++. Mit dieser Sprache ist zwar alles umsetzbar, jedoch ist die Programmierung aufwändig und fehleranfällig. Bevor man etwas Programmieren kann, muss zudem eine Toolchain installiert und konfiguriert werden. Je nach Hardware ist selbst die Konfiguration der Entwicklungsumgebung bereits eine Hürde. Je nach Einstellungen kann man damit seinen Microcontroller sogar permanent zerstören (verflashen).
Seit einer Weile gibt es zwar Alternativen, beispielsweise Micropython oder Circuitpython. Beide sind speziell für Microcontroller konfektionierte Interpreter, die auf der beliebten Python-Programmiersprache basieren. Python hat allerdings den grossen Nachteil, dass sie als dynamisch typisierte Sprache viel Speicher verwendet und ein schlechteres Laufzeitverhalten aufweist. Rechenleistung und Speicher ist auf normalen PC’s in grossen Menge verfügbar, nicht aber auf Microcontrollern. Daher kann man sich heute eigentlich nur entscheiden, ob man effizient, jedoch aufwändig mit C/C++ arbeiten möchte oder mit Micropython schnell und kompakt, dafür langsam und mit grossem Speicherlimitationen.
NanoPy füllt hier diese Lücke. Die Sprache ist statisch typisiert mit statischer Speicherverwaltung. Dadurch kann sie sehr effizient mit den beschränkten Ressourcen eines Microcontrollers umgehen. Sie ist aber auch einfach zu nutzen, da sie bekannte Sprachkonzepte der beliebten Python-Sprache übernimmt. Dies gelingt dank modernder Compilertechnik, die bis zu einem gewissen Grad auch dynamische Programmierpraktiken nachahmen kann. Bei der Ausführung erzeugt NanoPy einen kompakten Bytecode, der über einen effizienten Interpreter auf der Zielmaschine ausgeführt wird. Dadurch dass kein dynamischer Speicher verwendet wird, ist NanoPy sehr robust und läuft auch im Langzeitbetrieb stabil.
Beispiel:
background(0,0,0)
for i in 100:
x = random(0,240)
y = random(0,240)
r = random(0,20)
drawCircle(x,y,r)
update()
Zu NanoPy gibt es viele Tools, die man bei Microcontrollern normalweise vermisst, wobei man nichts lokal installieren und bewirtschaften muss. Alles läuft bequem im Browser. In der integrierten Entwicklungsumgebung finden wir Live-Debugging-Tools, Autocomplete-Funktionen, eine komplette interaktive Dokumentation, sowie viele fertig programmierte Beispiele, die man sofort für eigene Projekte einsetzen kann.
NanoPy kombiniert bestehende Sprachkonzepte mit neuen technischen Verfahren.
Dadurch lässt sich häufig sogar einfacher Python-Code mit wenig Änderungen auf Microcontrollern ausführen.
NanoPy kann mit vielen Sprachkonstrukten von Python umgehen. U.a. verwendet die Sprache auch die Einrückung von Blöcken. Der in Python zwingend notwendigen Doppelpunkt, sowie die Klammern um Prozeduraufrufen ist in NanoPy jedoch nicht zwingend. Gerade Einsteiger:innen bekunden häufig Mühe mit diesen Konstrukten, daher kann man diese in NanoPy auch einfach weglassen.
In NanoPy lassen sich Microcontroller ereignisgesteuert programmieren.
Das NanoPy-System für Microcontroller definiert eine Anzahl Ereignisprozeduren, die vom System automatisch aufgerufen werden, wenn eine bestimmte Situation eintritt.
Aktuell sind folgende Ereignisse verfügbar:
Ereignis | Auslöser |
---|---|
onClick | wird ausgelöst, wenn ein Button auf dem Gerät gedrückt wird. |
onTimer | Wenn ein Timer konfiguriert ist, wird beim Eintreffen des Ereignisses onTimer aufgerufen. Der Timer kann entweder einmalig (setTimer) oder als Intervall wiederkehrend (setInterval) definiert sein. |
onDraw | Wird ca. alle 20ms ausgelöst, wenn der Controller nicht mit höherprioritären Tasks beschäftigt ist. Damit lassen sich flüssige Bildschirmanimationen auf dem TFT-Screen der Oxocards darstellen. |
Wenn der Button nach unten gedrückt wird, wird das Interval definiert und gestartet. Dadurch wird alle 100ms ein onTimer-Ereigns ausgelöst. Wenn der Button noch oben gedrückt wird, stoppt das Intervall.
Python-Style
def onTimer():
print("timer")
def onClick():
b = getButtons()
if b.down:
setInterval(100)
print("start interval")
if b.up:
stopInterval()
print("stop interval")
Compact-Style
def onTimer
print "timer"
def onClick
b = getButtons()
if b.down
setInterval 100
print "start interval"
if b.up
stopInterval
print "stop interval"
Durch Klick auf den Button wechselt die globale Variable on zwischen true und false. Das Ereignis onDraw wird 30-50x pro Sekunde aufgerufen. In dieser Funktionen prüfen wir den Zustand der Variablen und zeichnen einen Kreis, wenn on true ist.
Python-Style
on=false
def onDraw():
clear()
if on:
drawCircle(120,120,80)
update()
def onClick():
on = not on
delay(500)
Compact-Style
on=false
def onDraw
clear
if on
drawCircle 120,120,80
update
def onClick
on = not on
delay 500
Micropython | C/C++ / Arduino | NanoPy |
---|---|---|
Kompletter Python-Sprachumfang | Kompletter C/C++ Sprachumfang | Optimierter Sprachumfang für Microcontroller |
Dynamisch typisiert | Statisch typisiert | Statisch typisiert |
Dynamische Speicherverwaltung | Statische und dynamische Speicherverwaltung | Statische Speicherverwaltung |
Langsamer, da dynamisch typisiert / dynamische Speicherverhaltung | schnell | schnell |
Höherer Speicherbedarf | geringer Speicherbedarf | geringer Speicherbedarf |
Kein Debugging | Debugging mit Adapter | Debugging direkt via Browser |
Übertragung von Benutzerscripts | Nur komplette Firmware kann übertragen werden | Übertragung von Benutzerscripts |
Installation der Firmware / Aktualisierung via Flasher | Installation von Software. Kompilieren und flashen | Programmieren via Browser / App. / Firmware over the air |
Interpreter | Compiler | Bytecode-Compiler / Interpreter |