Die Grundlagen von CircuitPython für Prototyping und Entwicklung auf Mikrocontrollerbasis

Von Steve Leibson

Zur Verfügung gestellt von Nordamerikanische Fachredakteure von Digi-Key

Obwohl das Programmieren durch Python zugänglicher geworden ist, wurde die Programmiersprache für PCs konzipiert, die über ausreichend Verarbeitungs-, Speicher- und Ressourcen für Peripheriebausteine verfügen. Für Embedded-Systeme mit größeren Einschränkungen hinsichtlich Ressourcen und Schnittstellen hat sich mit MicroPython eine für Mikrocontroller optimierte Version zu einer beliebten Alternative entwickelt. Die Popularität dieser Version geht sogar so weit, dass die Open-Source-Community MicroPython für bestimmte Mikrocontroller und Entwicklungskarten angepasst hat, um die ernsthafte Mikrocontrollerentwicklung zu unterstützen.

Dieser Artikel stellt mit CircuitPython von Adafruit eine dieser Anpassungen vor. Nach einer kurzen Vorstellung von Python im Vergleich zu C++, der klassischen Programmiersprache für Embedded-Entwicklungsprojekte, behandelt der Artikel die Entwicklung von Python hin zu MicroPython und jetzt CircuitPython. Anschließend wird das Schreiben von Software mit CircuitPython beschrieben, bevor der Artikel verschiedene Entwicklungskarten von Adafruit und weiteren Anbietern vorstellt, die diese CircuitPython-Umgebung unterstützen.

Warum Python?

Die ursprüngliche Arduino-Entwicklungskarte und ihre zahlreichen Nachfolger waren äußerst beliebte Mikrocontroller-Entwicklungskarten bei Hobbybastlern und Studenten sowie für Embedded-Prototypen. Die Arduino-IDE und die Programmiersprache basieren jedoch auf C++, einer leistungsstarken, aber komplexen kompilierten Sprache mit einer seltsam anmutenden Syntax und strengen Interpunktionsregeln, die viele Programmieranfänger abschrecken.

Python ist eine neuere Programmiersprache. Es handelt sich dabei um eine interpretierte, interaktive, objektorientierte Sprache, die eine bemerkenswerte Programmierleistung mit einer klar strukturierten Syntax kombiniert. Sie ist bekannt für ihre Schreibbarkeit und Lesbarkeit sowie für ihre einfachere Syntax. Alles das trägt dazu bei, dass weniger Programmierfehler gemacht werden und die Wiederverwendbarkeit von Code vereinfacht wird, wodurch wiederum die Softwareentwicklung beschleunigt wird.

Die interpretative Natur der Sprache gibt dem Programmierer ein unmittelbares Feedback, das zum Experimentieren einlädt und ein rasches Lernen fördert. Aus diesen Gründen ist Python inzwischen die erste Programmiersprache, die viele Studenten und Hobbybastler lernen.

Ein Nachteil der Sprache besteht jedoch darin, dass Python für PCs und größere Maschinen mit ausreichend RAM, enormem Massenspeicher sowie einer umfassenden Benutzeroberfläche mit Tastatur, großem Display und Maus entwickelt wurde. Sie war nicht für die Embedded-Programmierung vorgesehen. Mit MicroPython ist jedoch eine schlanke und effiziente Implementierung der Programmiersprache Python 3 entstanden, die speziell zur Ausführung mit den beschränkten Ressourcen eines Mikrocontrollers entwickelt und optimiert wurde.

Das Erkennen der Möglichkeiten von MicroPython als eine Sprache zur Embedded-Programmierung hat dazu geführt, dass die Open-Source-Community sie für bestimmte Mikrocontroller und Entwicklungskarten angepasst hat, um die ernsthafte Mikrocontrollerentwicklung zu unterstützen. So hat beispielsweise Adafruit mit CircuitPython eine eigene Version von MicroPython entwickelt. Die auf die Mikrocontroller und die Hardwareressourcen der Entwicklungskarten von Adafruit zugeschnittene Sprache soll zum Experimentieren einladen und das Erlernen der Programmierung mit CircuitPython auf kostengünstigen Mikrocontrollerkarten erleichtern. CircuitPython ist auf verschiedenen Entwicklungskarten von Adafruit bereits vorinstalliert und kann auf weiteren Karten installiert werden.

Unterschiede zwischen C++ und Python

Angesichts der Beliebtheit und Verbreitung der Arduino-IDE und der Vielzahl an verfügbaren Arduino-Entwicklungskarten macht die Frage, ob für die Embedded-Entwicklung wirklich eine eigene Python-Version benötigt wird, durchaus Sinn. Ein Vergleich der Programmiersprachen liefert die Antwort.

C++ ist eine Erweiterung der älteren Programmiersprache C mit objektorientierten Erweiterungen. Doch selbst mit diesen Erweiterungen liest sich C++ etwas kryptisch, da auch weiterhin die Syntax von C verwendet wird, die ursprünglich von Kernigan und Ritchie in den späten 1960er- und frühen 1970er-Jahren in den Bell-Laboratorien entwickelt worden ist. Die ursprüngliche Absicht hinter der Entwicklung von C bestand darin, geschriebenen Code problemlos in Maschinenanweisungen für einen Zielprozessor umwandeln zu können. Diese Ausrichtung auf die Anforderungen der Maschine anstatt auf die der Programmierer spiegelt sich in der Syntax der Programmiersprache wider. Da kommerzielle Mikroprozessoren erst 1971 auf den Markt kamen, wurde C ursprünglich für Minicomputer entwickelt. C-Compiler für Mikroprozessoren entwickelten sich in den 1980er-Jahren allmählich zu hilfreichen Werkzeugen. C war schon immer eine kompilierte Sprache und selbiges gilt auch für C++.

Der dänische Computerwissenschaftler Bjarne Stroustrup begann 1979 mit der Entwicklung von C++. Sein erstes Lehrbuch zur Programmiersprache erschien 1985. Es dauerte jedoch bis 1998, bevor sich C++ zu einer standardmäßigen Programmiersprache entwickelte. Ebenso wie C war Stroustrups C++ ursprünglich für größere Computer vorgesehen Die 2003 entwickelte Arduino-IDE (Integrated Development Environment, integrierte Entwicklungsumgebung) machte C++ auch für Mikrocontroller hilfreich.

Bei Python handelt es sich ebenfalls um eine objektorientierte Sprache. Sie wurde von dem dänischen Programmierer Guido van Rossumin entwickelt und erstmals 1991 veröffentlicht. Die syntaktische Struktur von Python betont die Lesbarkeit des Codes (für Menschen), worin einer der entscheidenden Unterschiede zwischen Python und C++ liegt. Die Schreibbarkeit, die eng mit der Lesbarkeit zusammenhängt, ist ebenfalls ein Punkt zugunsten von Python. Sie ermöglicht Programmierern im Allgemeinen das schnellere Schreiben von Anwendungen, wodurch die Experimentierfreudigkeit angeregt wird und ein schnelleres Prototyping und kürzere Entwicklungszyklen ermöglicht werden.

Ein zweiter großer Unterschied besteht darin, dass Python eine interpretierte Sprache ist, so wie die Programmiersprache Basic, die erstmalig in den 1960er-Jahren für Minicomputer zum Einsatz kam und ihre große Blütezeit in den 1970er-Jahren erlebte, und zwar mit Einführung der Mikrocomputer. Wie bei Basic auch lädt die interpretative Natur von Python zum Experimentieren ein, was ein Lernen durch den Verzicht auf den Entwicklungszyklus für kompilierte Programmiersprachen unterstützt, der aus Bearbeiten, Kompilieren, Herunterladen und Ausführen bestand. Im Gegensatz zu Basic handelt es sich bei Python jedoch um eine moderne, objektorientierte Sprache auf einer höheren Ebene, die die Fortschritte der Computerwissenschaft eines halben Jahrhunderts berücksichtigt, das seit der erstmaligen Entwicklung von Basic vergangen ist.

Beispielsweise müssen die in Python verwendeten Variablen vor der Verwendung deklariert oder typisiert werden. Programmierer müssen sich keine Gedanken darüber machen, ob es sich bei der Variable um eine Ganzzahl oder eine Gleitkommazahl handeln soll. Der Python-Interpreter erkennt dies automatisch und nimmt während der Ausführung die entsprechende Auswahl vor.

Zwei weitere Unterschiede zwischen C++ und Python liegen in der Verarbeitung von Strings und der Interpunktion. Viele Programmierer halten die Verarbeitung von Strings in C++ für stumpf und verwirrend. Die Verarbeitung von Strings in Python ist sehr viel einfacher und erinnert stark an die einfache und beliebte Verarbeitung von Strings in Basic, was lange als eine der großen Stärken von Basic galt.

Die Interpunktion von C und C++ – insbesondere die geschweiften Klammern ({}) – ist ein weiterer Punkt, der Neueinsteiger und selbst erfahrene Programmierer häufig vor Probleme stellt. Ständig scheint ein Programm eine ungerade Anzahl an geschweiften Klammern zu enthalten, was bedeutet, dass sich der Programmierer auf die mühevolle Suche nach der Stelle machen muss, an der die fehlende geschweifte Klammer platziert werden muss. Python verwendet keine derart knifflige Interpunktion. Stattdessen verwendet die Sprache Einrückungen, die auch für die Lesbarkeit des Python-Codes sorgen.

Die Ursprünge von MicroPython

Ebenso wie C und C++ wurde auch Python ursprünglich zur Ausführung auf größeren Computern entwickelt. Infolgedessen erforderte die Sprache zu viele Ressourcen, um zur Programmierung von Mikrocontrollern verwendet werden zu können. Aus diesem Grund entwickelte der australische Programmierer und Physiker Damien George eine Python-Version mit der Bezeichnung MicroPython, die auch mit den beschränkteren Ressourcen eines Mikrocontrollers ausgeführt werden konnte. Arduino-Entwicklungskarten waren frühe Anwendungsziele für MicroPython.

Die interaktive Natur von MicroPython beruht auf ihrer Befehlsschnittstelle. Diese wird formell als das REPL-Fenster (Read-Eval-Print-Loop) bezeichnet und üblicherweise über eine serielle Verbindung betrieben, über die ein Host-PC mit einer Mikrocontroller-Entwicklungskarte verbunden ist. Die REPL-Schnittstelle ähnelt sehr stark den Befehlszeilenschnittstellen von Basic aus den 1970er- und 1980er-Jahren. Sie akzeptiert Benutzereingaben (Einzelausdrücke oder -aussagen), wertet sie aus und gibt anschließend entweder über das REPL-Fenster Ergebnisse an den Benutzer zurück oder führt den in die Aussage eingebetteten Befehl aus.

Mit der REPL-Schnittstelle kann eine Variable abgefragt, eine I/O-Leitung umgeschaltet oder eine Zeichenfolge an einen angeschlossenen Peripheriebaustein gesendet werden. Die Zeile wird interpretiert und umgehend ausgeführt, sobald die Eingabetaste gedrückt wird. Hierin liegt die Natur einer interpretierten Programmiersprache.

Die Funktion von MicroPython erleichtert die explorative Programmierung und Fehlersuche und stellt einen der Aspekte von MicroPython dar, der die Programmiersprache sowohl für Einsteiger als auch für erfahrene Programmierer benutzerfreundlich macht. Die REPL-Schnittstelle unterstützt kürzere Entwicklungszyklen im Vergleich zum klassischen, aus Bearbeiten, Kompilieren, Herunterladen und Ausführen bestehenden Zyklus der Arduino-IDE. Selbst erfahrene Programmierer profitieren davon, interaktiv mit neuartigen Peripheriebausteinen experimentieren zu können, indem sie die REPL-Schnittstelle von MicroPython verwenden.

CircuitPython-Unterstützung für Entwicklungskarten

Jeder Mikrocontroller verfügt über einen einzigartigen Satz von Peripheriebausteinen, wobei diese Liste durch jede Entwicklungskarte weiter ergänzt wird. Für diese Peripheriebausteine sind unterstützende Bibliotheken erforderlich. Das gilt sowohl für die Arduino-IDE als auch für MicroPython. Zusätzlich gibt es zahlreiche Add-on-Peripheriekomponenten, z. B. den adressierbaren NeoPixel RGB-LED-Streifen 1655 von Adafruit, die ebenfalls die Unterstützung durch eine Bibliothek erfordern.

Für eine bessere Unterstützung hat Adafruit mit CircuitPython eine eigene Version von MicroPython entwickelt, um den speziellen Anforderungen verschiedener kostengünstiger Mikrocontroller-Entwicklungskarten des Unternehmens gerecht zu werden. Des Weiteren hat das Unternehmen viele Bibliotheken für Peripheriebausteine aus seiner riesigen Arduino-Sammlung in Bibliotheken für CircuitPython umgewandelt, wodurch bereits eine große und stetig wachsende Anzahl an Bibliotheken für CircuitPython zur Verfügung steht.

Adafruit hat eine Reihe von Mikrocontroller-Entwicklungskarten speziell zur Unterstützung von CircuitPython entwickelt. Hierzu zählen folgende Karten:

  • 3333 Circuit Playground Express mit zehn adressierbaren, steuerbaren RGB-LEDs (Abbildung 1)

Bild: 3333 Circuit Playground Express von Adafruit

Abbildung 1: Die 3333 Circuit Playground Express von Adafruit bietet zehn adressierbare, steuerbare RGB-LEDs. (Bildquelle: Adafruit)

  • 3500 Trinket M0 mit Abmessungen von lediglich 27 mm x 15,3 mm x 2,75 mm (Abbildung 2)

Bild: 3500 Trinket M0 von Adafruit

Abbildung 2: 3500 Trinket M0 von Adafruit mit Abmessungen von lediglich 27 mm x 15,3 mm x 2 mm. (Bildquelle: Adafruit)

  • 3501 Gemma M0 mit einem Durchmesser von etwa 25 mm und Stromversorgung über ihren USB-Anschluss oder einen separaten Batterieanschluss (Abbildung 3)

Bild: 3501 Gemma M0 von Adafruit

Abbildung 3: Die 3501 Gemma M0 von Adafruit hat einen Durchmesser von etwa 25 mm und kann über ihren USB-Anschluss oder einen separaten Batterieanschluss mit Strom versorgt werden. (Bildquelle: Adafruit)

  • 3403 Feather M0 Express mit einem kleinen Steckbrettbereich für kundenspezifische Schaltkreise (Abbildung 4)

Bild: 3403 Feather M0 Express von Adafruit

Abbildung 4: Die Entwicklungskarte 3403 Feather M0 Express von Adafruit verfügt über einen kleinen Steckbrettbereich für kundenspezifische Schaltkreise. (Bildquelle: Adafruit)

Diese vier Mikrocontroller-Entwicklungskarten von Adafruit basieren alle auf den SAMD21-Mikrocontrollern von Microchip Technology (ehemals Atmel) mit nativer USB-Unterstützung. CircuitPython unterstützt jedoch nicht nur die Entwicklungskarten von Adafruit und die SAMD21-Mikrocontroller. Inzwischen gibt es auch Versionen von CircuitPython für andere Entwicklungskarten mit anderen Mikrocontrollern, so etwa die Entwicklungskarten 3406 Feather NRF52 von Adafruit und die nRF52-DK von Nordic Semiconductor, die beide auf dem nRF52832-Mikrocontroller von Nordic Semiconductor basieren. Des Weiteren wird auch die Entwicklungskarte nRF52840-DK von Nordic Semiconductor (Abbildung 5), die auf dem nRF52840-Mikrocontroller des Unternehmens basiert, von CircuitPython unterstützt. Beide Mikrocontroller, auf denen diese drei Karten basieren, bieten Bluetooth mit geringem Stromverbrauch (BLE) sowie die entsprechende Softwareunterstützung.

Bild: Entwicklungskarte nRF52840-DK von Nordic Semiconductor

Abbildung 5: Die Entwicklungskarte nRF52840-DK von Nordic Semiconductor bietet integrierten BLE-Support. (Bildquelle: Nordic Semiconductor)

Entwickeln mit CircuitPython

Adafruit hat einen einzigartigen Ansatz verfolgt, um CircuitPython auf für die direkte Unterstützung der Sprache konzipierten Entwicklungskarten zu etablieren. Verbindet man eine dieser Karten per USB mit einem Host-PC, wird die Karte als Laufwerk des PCs angezeigt. Im Stammverzeichnis dieses Laufwerks befinden sich die für CircuitPython wichtigen Dateien, inklusive des Interpreters, des Benutzerprogramms und eines Ordners mit den Bibliotheksdateien. Dank dieser Anordnung kann der Host-PC problemlos über sein bestehendes Dateisystem und seine Treiber auf die Entwicklungskarte zugreifen.

Die CircuitPython-Benutzeroberfläche auf dem Host-PC erfordert einen kostenlosen, als Download verfügbaren Open-Source-Editor sowie eine REPL-Schnittstelle. Adafruit empfiehlt die Open-Source-Anwendung Mu (siehe Abbildung 6). Der Mu-Bildschirm ist in ein Code-Fenster für die Bearbeitung und das REPL-Fenster für Steuerung und Überwachung aufgeteilt, in dem der Programmierer den CircuitPython-Interpreter der Entwicklungskarte steuert.

Bild: Open-Source-Programmierschnittstelle Mu von Adafruit

Abbildung 6: Adafruit empfiehlt die Verwendung der Open-Source-Programmierschnittstelle Mu. Der Mu-Bildschirm ist in ein Code-Fenster für die Bearbeitung und das REPL-Fenster für Steuerung und Überwachung aufgeteilt, in dem der Programmierer den CircuitPython-Interpreter der Entwicklungskarte steuert. (Bildquelle: codewith.mu/en/tutorials/1.0/adafruit)

Wenn Sie in das Code-Fenster ein Programm eingeben und in Mu auf die Schaltfläche „Save“ klicken, wird der Code auf den CircuitPython-Entwicklungskarten von Adafruit im großen On-Chip-Flash-Speicher des SAMD21-Mikrocontrollers gespeichert. Jeglicher CircuitPython-Code wird im Flash-Speicher des Mikrocontrollers auf der Entwicklungskarte gespeichert. Erinnern Sie sich, dass der PC in der CircuitPython-Karte ein Laufwerk sieht. Von daher ist das aus Sicht eines Betriebssystems nichts Ungewöhnliches.

Fazit

Die Programmiersprache Python bietet Programmierern zahlreiche Vorteile wie interaktive Programmierung, Experimentiermöglichkeiten und Debugging. Sie verfügt über eine vereinfachte, der menschlichen Sprache ähnlicheren Syntax, bei der die Deklaration oder Typisierung von Variablen sowie eine komplexe Interpunktion entfallen. MicroPython stellt eine Abwandlung von Python 3 dar, mit der die Programmierung von Mikrocontrollern in Python ermöglicht wird.

Wie gezeigt hat Adafruit aus MicroPython die Programmiersprache CircuitPython für die direkte Hardwareunterstützung abgeleitet, um das Experimentieren weiter zu vereinfachen und das Erlernen der Sprache sowie die Softwareentwicklung zu beschleunigen. CircuitPython unterstützt bereits verschiedene kostengünstige Mikrocontroller-Entwicklungskarten auf der Basis des SAMD21-Mikrocontrollers von Microchip sowie weitere Entwicklungskarten auf der Basis der BLE-fähigen nRF-Mikrocontroller von Nordic Semiconductor.

Haftungsausschluss: Die Meinungen, Überzeugungen und Standpunkte der verschiedenen Autoren und/oder Forumsteilnehmer dieser Website spiegeln nicht notwendigerweise die Meinungen, Überzeugungen und Standpunkte der Digi-Key Electronics oder offiziellen Politik der Digi-Key Electronics wider.

Über den Autor

Steve Leibson

Steve Leibson war Systemingenieur für HP und Cadnetix, der Chefredakteur für EDN und Microprocessor Report, ein Tech-Blogger für Xilinx und Cadence (u.a.) und er diente als Technologieexperte für zwei Folgen von „The Next Wave with Leonard Nimoy“. Er hilft Entwicklern seit 33 Jahren, bessere, schnellere und zuverlässigere Systeme zu entwickeln.

Über den Verlag

Nordamerikanische Fachredakteure von Digi-Key