Raspberry Pi Pico Kurs – #4 – Erste Schritte in der Programmierung

Lesezeit 15 min.

Im vorherigen Material haben wir gemeinsam die Visual Studio Code-Umgebung vorbereitet und das erste Beispielprogramm ausgeführt, um zu prüfen, ob alles korrekt funktioniert. In diesem Artikel werden wir die Vorbereitung unseres eigenen Projekts üben, und ich werde Sie auch über die grundlegenden Abhängigkeiten und Regeln, die in der Sprache C auftreten, informieren.

Kaufen Sie ein Set, um das Programmieren mit dem Raspberry Pi Pico W zu erlernen, und nutzen Sie die Vorteile des Kurses, der im Botland Blog verfügbar ist!

Im Set enthalten: Raspberry Pi Pico W-Modul, Kontaktplatte, Leitungen, LEDs, Widerstände, Tasten, Fotowiderstände, digitale Licht-, Temperatur-, Feuchtigkeits- und Drucksensoren, OLED-Display und ein USB-microUSB-Kabel.

Vor dem Start sollte das Team zusammengestellt werden

Ein Satz von Komponenten für den Raspberry Pi Pico Kurs.

Wer das Programmieren anhand von realen Projekten erlernen möchte, braucht natürlich die richtige Ausrüstung, aber keine Sorge – Sie müssen jetzt nicht von einem Artikel zum nächsten springen und eine Liste der benötigten elektronischen Komponenten erstellen. Im Botland-Shop ist ein fertiger Bausatz erhältlich, der alle notwendigen Komponenten enthält, um die in der Tutorial-Reihe beschriebenen Projekte mit dem Raspberry Pi Pico durchzuführen.

In dem fertigen Set von Elementen finden Sie:

  • Raspberry Pi Pico W,
  • MicroUSB-Kabel,
  • Kontaktplatte,
  • Ein Set von Anschlusskabeln in drei Ausführungen,
  • Ein Set von LEDs in drei Farben,
  • Ein Set der in der Elektronik am häufigsten verwendeten Widerstände,
  • Tact Switch-Tasten,
  • Fotowiderstände,
  • Digitaler Lichtsensor,
  • Digitaler Feuchtigkeits-, Temperatur- und Drucksensor,
  • OLED-Display.

Ganz neue LED-Blinkfunktion, Projekterstellung

Blinkschaltung, erweitert um weitere LEDs.

Der zuvor ausgeführte Code stammt aus einem Beispiel der Raspberry Pi Foundation namens blink. Dieses Programm schaltete die an den Raspberry Pi Pico W angeschlossene LED synchron ein und aus. Blink-Projekte sind in allen Programmier-Tutorials, die auf kleinen Hardware-Plattformen basieren, sehr verbreitet. Deshalb zeige ich Ihnen auch, wie Sie diese Art von Programm selbst schreiben können, allerdings in einer etwas aufwändigeren Version, da wir hier eine etwas größere Anzahl von Leuchtdioden verwenden werden. Zunächst sollten wir jedoch die notwendige Ausrüstung vorbereiten. Bisher war nur eine grüne LED mit dem RPI Pico W verbunden, die an die Leitung GP0 angeschlossen ist. Die nächsten beiden Dioden sollten an die nächstfolgenden Pins angeschlossen werden, nämlich GP1 und GP2, die sich direkt daneben befinden. Und vergessen Sie nicht die Widerständemit einem Wert von 330 Ω. Wie Sie auf dem Foto oben sehen können, habe ich die Anordnung der ersten Diode leicht verändert, so dass die Kathoden aller Leuchtelemente durch den blau markierten Bus (-) verbunden sind.

Sobald die Schaltung für künftige Experimente fertig ist, können wir zum VSC zurückkehren und versuchen, unseren eigenes Projekt zur Steuerung von drei LEDs zu erstellen. Bevor wir jedoch dazu kommen, müssen einige organisatorische Fragen geklärt werden.

Standardmäßig ist unter Visual Studio Code der Ordner pico-examples angehängt, der von der Raspberry Pi Foundation bereitgestellte Beispiele enthält. Wenn Sie Ihre eigenen Projekte vorbereiten wollen, lohnt es sich, einen separaten Speicherplatz vorzubereiten oder den oben erwähnten Beispielordner zu verwenden. Es spricht nichts dagegen, dass wir unsere künftigen Projekte genau dort platzieren. Abgesehen davon ist pico-examples ein Ort, an dem es sich einfach lohnt, einen Blick darauf zu werfen. Hier gibt es viele Beispielprogramme, und wenn Sie Ihren eigenen Code erstellen, können Sie die dort veröffentlichten Informationen nutzen.

Sie können die Struktur des Ordners pico-examples in der nebenstehenden Abbildung, aber auch auf Ihrem eigenen Computerbildschirm sehen. Die darin enthaltenen Dateien und Ordner sind recht zahlreich und haben jeweils eine andere Funktion. Betrachten wir zunächst die Ausnahmen, die keine Projekte sind. Ordner wie .github, .vscode und cmake stehen im Zusammenhang mit der Organisation des gesamten Bereichs. Ersteres ist darauf zurückzuführen, dass das Ganze aus der Ferne von GitHub heruntergeladen wurde, .vscode steht im Zusammenhang mit der Visual Studio Code-Umgebung, die dort relevante Informationen speichert, während cmake Dateien im Zusammenhang mit dem Kompilierungsprozess enthält.

In pico-examples gibt es auch eine Reihe von separaten Dateien, von denen die meisten für uns nicht von Interesse sind, da sie Informationen über die Ordnerkonfiguration oder die Lizenzierung enthalten. Im Moment ist die einzige Datei, der wir etwas mehr Aufmerksamkeit schenken werden, CMakeLists.txt. Sie enthält eine Liste von Projekten in pico-examples, die wir nach und nach erweitern werden, indem wir unsere eigenen Konstruktionen hinzufügen. Da wir gerade von Projekten sprechen: Es gibt eine ganze Reihe davon, die in verschiedenen Ordnern untergebracht sind, von denen einige weitere Ordner verbergen. So umfasst das Innere des adc nicht weniger als sieben Projekte, die sich auf diese Art von Funktionalität beziehen. Der letzte Ordner, auf den wir achten müssen, ist build, den wir bereits in einem früheren Artikel verwendet haben, indem wir die .uf2-Datei kopiert haben. Hier befinden sich alle resultierenden Kompilierungsdateien in bestimmten Ordnern, die mit dem Namen der Projektdefinition übereinstimmen.

Struktur des Ordners pico-examples.
pico-examples, nachdem Sie den Ordner extended_blink erstellt haben.

Es ist nun an der Zeit, unser erstes Projekt in VSC zu erstellen. Es handelt sich um eine erweiterte Version des klassischen Blinks der mit drei LEDs arbeitet. Zunächst müssen wir uns natürlich einen Namen für das Projekt ausdenken, der auch der Name des Ordners sein wird, in dem unsere Dateien gespeichert werden. Sie müssen wissen, dass auch die Nomenklatur auf bestimmten Grundsätzen beruht. Die Projektnamen sollten einfach sein, vorzugsweise englische Begriffe verwenden und keine deutschen Zeichen oder Sonderzeichen verwenden. Das Design des erweiterten LED-Blinkens kann einfach als “expanded blink” bezeichnet werden, aber vor allem der Schreibstil selbst hat auch eine gewisse Bedeutung und spiegelt sich gut in dem folgenden Text wider, den ich einmal in einem Forum gesehen habe.

IfYouLikeReadingStuffLikeThisThenUseCamelCase.

if_you_like_reading_stuff_like_this_then_use_snake_case.

So können wir unser Projekt als ExpandedBlink oder expanded_blink speichern. Welche Version Sie wählen, bleibt Ihnen überlassen, ich habe mich für expanded_blink entschieden, da in pico-examples Projekte nach dieser Konvention gespeichert werden.

In der obigen Abbildung können Sie auch den Ordner TestCode sehen, der, wie der Name schon sagt, eine Art Test war, bevor ich die Artikel schrieb, und wie Sie sehen können, habe ich ihn reflexartig gemäß CamelCase benannt.

Wenn Sie den Mauszeiger über den Explorer-Bereich bewegen, sehen Sie neben dem Pico-Beispiel Piktogramme, mit denen Sie neue Dateien und Ordner erstellen können. Damit sollte der Ordner expanded_blink erzeugt werden und zwei Dateien darin hinzugefügt werden: expanded_blink.c und CMakeLists.txt. Im ersten Fall wird der Code in C geschrieben, während die Textdatei Informationen über den Kompilierungsprozess enthält. Wenn in Ihrem Fall beide Dateien nach der Erstellung rot hervorgehoben sind, besteht kein Grund zur Sorge. An diesem Punkt haben wir die Struktur des Ordners pico-examples mit roher Gewalt manipuliert, und um den Änderungen Rechtskraft zu verleihen, muss die Datei CMakeLists.txt, die sich auf die gesamten pico-examples bezieht, leicht geändert werden. Sie finden sie am unteren Rand der Datei-Explorer-Ansicht.

Der Inhalt von CMakeLists.txt für pico-Beispiele.

Damit unser neuer Ordner und damit das expended_blink Projekt akzeptiert wird, müssen wir ihn in der Datei CMakeLists.txt hinzufügen. Am Ende finden Sie eine Liste in der die Namen aller beispielhaften Projekte in Klammern angegeben sind. An Ihrem Ende fügen wir hinzu:

				
					add_ subdirectory(expanded_blink)
				
			

Nach der Änderung können wir die Datei speichern. Nach einer Weile wird der Ordner pico-examples neu geladen und die kurz zuvor hinzugefügten Dateien leuchten grün auf. Dies bedeutet, dass wir erfolgreich ein neues Projekt zu pico-examples hinzugefügt haben. Natürlich ist er im Moment noch leer, aber das wird sich bald ändern.

Vorbereitung des Programmcodes

Das Programm, das unsere leuchtenden Elemente steuern soll, beginnt mit einem leeren Skript. Wie ich bereits erwähnt habe, besteht jedes Programm, das von einem Mikrocontroller, einem Prozessor oder einer anderen digitalen Maschine ausgeführt wird, aus sequentiell geschriebenen Anweisungen. Der Programmierer erstellt einen Code, der Schritt für Schritt ausgeführt wird. Werden wir in diesem Fall den Code einfach Anweisung für Anweisung schreiben? Nicht ganz. Dies wäre der Fall, wenn wir das Programm in Maschinencode schreiben wollten, aber das wäre äußerst kompliziert. In dieser Hinsicht ist die Sprache C einfacher und intuitiver, d. h. sie ist eher für Menschen als für Maschinen geeignet.

				
					//comment
//program area before main function

int main(){
    /*lengthy comment,
    here we will place
    single commands*/
}

				
			

Wir können den Programmbereich zunächst in zwei Teile unterteilen, nämlich in den Bereich oberhalb der Funktion main und den Bereich innerhalb der Funktion. In der Sprache C werden alle Anweisungen, die wir ausführen wollen, in der Funktion main untergebracht. Eine Funktion ist nichts anderes als eine Art von Befehl, der bei der Kompilierung in eine Reihe von Maschinenbefehlen umgewandelt wird, die die Form von Nullen und Einsen haben und im Speicher abgelegt werden. Funktionen können in Form eines einzelnen Befehls oder einer Reihe von Befehlen ausgeführt werden. Es ist auch gut zu wissen, dass wir die Funktionen selbstständig schreiben können; es ist recht einfach, sich ein Skript vorzustellen, das unabhängig von äußeren Faktoren immer wieder die gleiche Aufgabe ausführt. Anstatt einen extrem aufwändigen Code zu schreiben, können bestimmte feste Elemente des Programms in einer Funktion gekapselt werden, der von Zeit zu Zeit aufgerufen wird, um anzuzeigen: “Führe jetzt diesen Teil des Codes aus und kehre zur Hauptaufgabe zurück”. Die Funktion main ist genau so etwas, sie ist die Hauptfunktion des Programms, innerhalb derer wir andere Befehle platzieren werden.

Vor dem Schlüsselwort main steht das geheimnisvolle int. Es ist einer der grundlegenden Datentypen in der Sprache C, und seine Platzierung ist auf die Tatsache zurückzuführen, dass Funktionen sowohl Daten empfangen als auch zurückgeben können. Wenn wir zum Beispiel eine Funktion schreiben, die die Addition von zwei Zahlen durchführt, muss sie einige Argumente aufnehmen, eine mathematische Operation durchführen und dann das Ergebnis zurückgeben. int ist genau der Datentyp, den die Hauptfunktion zurückgibt. Wir wollen hier nicht näher darauf eingehen, welche Daten das sind, werden aber in Zukunft auf dieses Thema zurückkommen.

Es gibt auch eine Klammer neben der Funktion main, in der die Daten stehen, die die Funktion aufnehmen kann. Dies könnten die bereits erwähnten Argumente für die Additionsoperation sein. In diesem Fall akzeptiert main jedoch keine Daten, so dass die Klammer leer ist.

Zusätzlich zu den üblichen Klammern können Sie auch geschweifte Klammern sehen. Darin werden weitere Befehle platziert, die vom Prozessor ausgeführt werden sollen. Im obigen Beispiel wird dort ein Kommentar eingefügt. In der Sprache C wird der Operator ‘//’ verwendet, um den Kommentar hinzuzufügen, alles was danach eingegeben wird, wird vom Compiler ignoriert. Wenn Sie einen längeren Kommentar, der sich über mehrere Zeilen erstreckt, hinzufügen möchten, können Sie dies mit der Konstruktion „/* lengthy comment */” tun. Kommentare im Code dienen als Information für den Programmierer, der den Code liest, und diese sind selbst bei den einfachsten Programmen sinnvoll. Eine gute Praxis ist es, den Code auf Englisch zu kommentieren – man weiß nie, wer sich unsere Programme zufällig anschaut. Zu beachten ist auch, wie der Code formatiert ist. Wie Sie sehen können, ist der lange Kommentar leicht versetzt; genauer gesagt, wird am Anfang jeder Zeile ein Tabulatorzeichen eingefügt. Ein solches Vorgehen soll die Lesbarkeit des Codes erleichtern; für den Compiler hat die zusätzliche Unterteilung keine Bedeutung. In der Regel wird ein zusätzlicher Tabulator verwendet, wenn Anweisungen innerhalb von Funktionen, bedingten Anweisungen, Schleifen und anderen spezifischen Konstrukten im Code stehen. Es ist recht intuitiv und wird sich mit der Zeit bestimmt einprägen. Außerdem fügt das Programm beim Schreiben von Codes in VSC automatisch ein Tabulatorzeichen in eine neue Zeile ein, entsprechend einem zuvor geschriebenen Befehl.

Wie ich bereits erwähnt habe, gibt es oberhalb der Funktion main auch einen Programmbereich, in dem wir bestimmte Konstrukte wie Konstanten, Definitionen, Deklarationen oder Direktiven unterbringen werden. Wir werden sie im Laufe der Zeit anhand von praktischen Beispielen kennenlernen.

Nachdem Sie wissen, wie der Aufbau eines Programms in der Sprache C in aussieht, können wir uns daran machen, es zu schreiben. Damit dies möglich ist, müssen wir jedoch definieren, was unser Programm konkret tun soll. Dies wird eine erweiterte Version des Skripts für das Blinken der LED sein. Wir können auch ein Programm vorbereiten, das in einem bestimmten Zeitraum mehrere LEDs auslöst, während die vorherige erlischt. Etwa so: grüne LED einschalten, eine halbe Sekunde warten, gelbe LED einschalten, grüne LED ausschalten, eine halbe Sekunde warten, rote LED einschalten, gelbe LED ausschalten und so weiter.

				
					#include "pico/stdlib.h"

int main() {
    gpio_init(0); //initialization of GP0, GP1 and GP2 pins
    gpio_init(1);
    gpio_init(2);

    gpio_set_dir(0, GPIO_OUT); //setting GP0, GP1 and GP2 as outputs
    gpio_set_dir(1, GPIO_OUT);
    gpio_set_dir(2, GPIO_OUT);

    gpio_put(0, 1); //set state 1 on pin 0
    sleep_ms(500); //wait 500ms
    gpio_put(0, 0); //set state 0 on pin 0
    gpio_put(1, 1); //set state 1 on pin 1
    sleep_ms(500);
    gpio_put(1, 0);
    gpio_put(2, 1);
    sleep_ms(500);
    gpio_put(2, 0);
    sleep_ms(500);
}

				
			

Das erste Programm, das wir ausführen werden, ist das Programm, dessen Code Sie oben sehen können. Im Moment sieht es vielleicht noch etwas geheimnisvoll aus, aber in Kürze, wenn ich Ihnen seine Struktur erkläre, wird alles klar werden. Das Ganze besteht eigentlich aus vier Arten von Befehlen, die mehrmals mit unterschiedlichen Parametern wiederholt werden. Beginnen wir unsere Analyse mit dem Kern des Codes, d. h. mit den Anweisungen innerhalb der Hauptfunktion.

Die ersten drei Befehle sind gpio_init, und wenn man sie betrachtet, ist ihre Bedeutung leicht zu verstehen – init steht für initialization, während gpio für general purpose input/output steht. gpio_init ist also nichts anderes als ein Initialisierungsbefehl für Ein-/Ausgabeanschlüsse (I/O), mit dem der Mikrocontroller bestimmte externe Leitungen für den Betrieb vorbereitet. Die Zahl in den Klammern bestimmt, welche Leitungen dies sind. 0, 1, 2 sind die Anschlüsse GP0, GP1 und GP2, an die wir zuvor die LEDs angeschlossen haben. Es wäre auch nützlich, anzugeben, in welchem Modus wir diese Ports verwenden werden. Derzeit weiß der RP2040 nur, dass wir drei Pins verwenden wollen, aber ihr Zweck bleibt ein Geheimnis. Um dies zu ändern, verwendet man gpio_set_dir, diese Art von Befehl ist auch recht einfach zu entwickeln. Sie kennen bereits die Bedeutung von gpio, set ist einfach set, während dir die Abkürzung für direction ist. Die im Projekt verwendeten Pins werden die Leuchtdioden steuern, daher müssen sie als Ausgänge konfiguriert werden, d. h. die Schaltung wird diese Leitungen steuern, indem der entsprechende logische Zustand an ihnen eingestellt wird. Um GP0, GP1 und GP2 als Ausgänge zu setzen, geben Sie die Pin-Nummern 0, 1, 2 und das Schlüsselwort GPIO_OUT in den Parametern der Funktion gpio_set_dir an. Beachten Sie, dass alle bisher besprochenen Befehle mit einem Semikolon enden. Ein solches Verfahren ist beabsichtigt, da es dem Compiler mitteilt, dass ein bestimmter Befehl an dieser Stelle endet.

Sobald die Leitungen konfiguriert sind, können wir damit beginnen, sie zu steuern. Dazu verwenden wir gpio_put, das es ermöglicht, den Ausgang auf Null oder Eins zu setzen. Dieser wird innerhalb der Klammern angegeben, wie der zweite Parameter, der durch die Zahl 0 oder 1 beschrieben wird. Die erste Ziffer in Klammern ist die Pin-Nummer, so dass gpio_put(0, 1); als Setzen des Zustands Eins am Pin-Null beschrieben werden kann.

Der letzte im Programm verwendete Befehl ist sleep_ms, die Bedeutung dieser Funktion ist ebenfalls recht vorhersehbar. Sie bewirkt einfach, dass der Mikrocontroller für eine bestimmte Zeitspanne pausiert, in diesem Fall Millisekunden, deren Wert in Klammern angegeben ist. Die Zahl 500 steht für 500 ms, also das Warten einer halben Sekunde.

Programme in der Sprache C werden Schritt für Schritt, Anweisung für Anweisung ausgeführt. Beachten Sie, dass wir zu Beginn die an GP0 angeschlossene Diode einschalten, dann 500 ms warten und in den nächsten Schritten die Diode, die eine halbe Sekunde lang eingeschaltet war, ausschalten und gleichzeitig ein anderes Lichtelement einschalten. Dann warten wir ein zweites Mal 500 ms, und der Zyklus des Ein- und Ausschaltens der LEDs wiederholt sich, nur dass wir jetzt die Pins GP1 und GP2 steuern. Auf diese Weise können wir die Programme analysieren und den Code in aufeinanderfolgende Schritte zerlegen, die vom Mikrocontroller ausgeführt werden.

Am Anfang des Programms finden Sie auch die mysteriöse Zeile #include “pico/stdlib.h”. Wie ich bereits erwähnt habe, werden wir oberhalb der Hauptfunktion des Programms bestimmte Konstrukte, wie z. B. Anhänge, platzieren, im Code können Sie genau so etwas sehen. Dies ist mehr eine Information für den Compiler als ein Teil des vom Chip implementierten Programms. Dank der Bibliothek, die im Code enthalten ist, können wir spezifische Funktionen und Parameter verwenden, die von der Raspberry Pi Foundation vorbereitet wurden. Wenn wir beispielsweise die Einbindung der stdlib-Bibliothek aufheben, meldet VSC einen Fehler und teilt uns mit, dass ihr etwas wie GPIO_OUT unbekannt ist. Dank einer externen Bibliothek waren wir in der Lage, den Ausgangsanschluss auf diese Weise zu deklarieren. Auch die Schreibweise dieser Direktive ist erklärungsbedürftig: Am Anfang steht das Schlüsselwort #include, gefolgt vom Pfad zur so genannten Header-Datei (Erweiterung .h) die Prototypen der Funktion enthält, die im Code verwendet werden können, vorausgesetzt natürlich, dass der entsprechende Anhang am Anfang der Datei steht. Externe Bibliotheken gibt es eine ganze Reihe, und in den folgenden Beispielen werden wir sie praktisch immer verwenden, zusätzlich zur Vorbereitung unserer eigenen Bibliothek in der Zukunft.

Damit ist unser erster Code fertig, aber ich möchte schon jetzt darauf hinweisen, dass es sich nicht um die endgültige Form handelt und wir im weiteren Verlauf des Artikels noch einige Änderungen daran vornehmen werden. Sie können den Code natürlich kopieren, aber ich empfehle, ihn selbst neu zu schreiben. Auf diese Weise kann das erworbene Wissen viel besser aufgenommen werden.

Vervollständigung der CMakeLists Datei

				
					add_executable(expanded_blink
        expanded_blink.c
        )

# pull in common dependencies
target_link_libraries(expanded_blink pico_stdlib)

# create map/bin/hex file etc.
pico_add_extra_outputs(expanded_blink)

				
			

Das einzige Element, das uns daran hindert, das erweiterte blink-Projekt auszuführen, ist die Datei CMakeLists.txt und ihr Inhalt, der noch nicht vorhanden ist. Die Erstellung von so genannten “make” Dateien, die den Prozess der Kompilierung und Erstellung von Software automatisieren sollen, kann ein äußerst komplexer Prozess sein. Daher werde ich nicht zu tief in dieses Thema eindringen, denn im Internet gibt es eine ganze Reihe von Inhalten, die das allgemeine Konzept von “make”-Dateien vorstellen.

Im Fall von RPI Pico ist CMakeLists.txt in drei Teile unterteilt. Im ersten Teil, dank des add_executable Befehls, fügen wir die ausführbare Datei expended_blink.c zum expended_blink Projekt hinzu, wenn es mehr Dateien gibt, und wenn solche Situationen in der Zukunft auftreten, sollten sie hier aufgenommen werden. Als Nächstes muss angegeben werden, welche Bibliotheken im Projekt verwendet wurden. Dies wird durch target_link_libraries ermöglicht, wobei wir den Projektnamen und die enthaltenen Bibliotheken in Klammern setzen. Die letzte Regel in CMakeLists ist pico_add_extra_outputs, die sicherstellt, dass alle Binärdateien während des Kompilierungsprozesses erzeugt werden.

Erster Start von expanded_blink

Es ist nun an der Zeit, das Projekt expanded_blink zum ersten Mal auszuführen. Wenn alle Dateien gespeichert sind, können wir zur Registerkarte CMake gehen, die wir bereits im vorherigen Material verwendet haben. Wählen Sie dort wie zuvor das entsprechende Projekt in der Option Build aus und führen Sie dann die Kompilierung aus.

Sobald diese erfolgreich ist, können Sie, wie beim ersten Blink-Projekt, die Datei expended_blink.uf2 auf den RPI-RP2 hochladen. Vergessen Sie nicht, beim Anschließen des Boards die Taste auf dem Board zu drücken, damit der Raspberry Pi Pico W in den Programmiermodus bootet.

Sobald die Daten gespeichert sind, sollte ein Effekt wie im obigen Video zu sehen sein – jede LED leuchtet abwechselnd für eine halbe Sekunde auf, danach erlischen sie alle. Aber ist das der Effekt, den wir erwartet haben? Nun, nicht ganz. Die gesamte Sequenz sollte immer wieder ausgeführt werden, unterliegt der vorbereitete Code in diesem Fall einem Fehler? Nein, alles wurde wie geplant ausgeführt und der Code funktioniert einwandfrei. Schauen Sie sich das Programm an, das wir geschrieben haben. Wir initialisieren die drei Pins, wählen ihre Funktionalität aus und steuern dann mit ein paar Befehlen, die einen bestimmten logischen Zustand einstellen und den RP2040 pausieren, die LEDs. Was passiert jedoch, wenn der Chip den letzten Befehl sleep_ms(500); ausführt? Die richtige Antwort ist: nichts, das Programm wurde ausgeführt, der Chip hat keine Ahnung, dass es sich aus unserer Sicht lohnen würde, den gesamten Vorgang des Ein- und Ausschaltens der LEDs zu wiederholen.

Endlose Lichteffekte

				
					#include "pico/stdlib.h"

int main() {
    gpio_init(0); //initialization of GP0, GP1 and GP2 pins
    gpio_init(1);
    gpio_init(2);

    gpio_set_dir(0, GPIO_OUT); //setting GP0, GP1 and GP2 as outputs
    gpio_set_dir(1, GPIO_OUT);
    gpio_set_dir(2, GPIO_OUT);

    while (true) { //infinite while loop
        gpio_put(0, 1);
        sleep_ms(500);
        gpio_put(0, 0);
        gpio_put(1, 1);
        sleep_ms(500);
        gpio_put(1, 0);
        gpio_put(2, 1);
        sleep_ms(500);
        gpio_put(2, 0);
        sleep_ms(500);
    }
}

				
			

Wenn wir wollen, dass der RP2040 die LEDs ständig synchron ein- und ausschaltet, müssen wir den Teil des Codes, der diese Aufgabe ausführt, irgendwie in eine Schleife bringen. Die ersten beiden Befehlssätze sind für die Konfiguration der Anschlüsse zuständig und es ist nicht sinnvoll, sie wiederholt auszuführen, da die einmal als Ausgänge konfigurierten Ausgänge auch als solche erhalten bleiben. Damit der Code, der die LEDs steuert, unbegrenzt ausgeführt werden kann, und zwar so lange, bis der Strom abgeschaltet wird, müssen wir ihn in eine Schleife einbauen. In der Sprache C sind Schleifen spezielle Konstrukte, die es ermöglichen, den darin enthaltenen Code wiederholt auszuführen. Darüber hinaus können Schleifen mit bestimmten Bedingungen verknüpft werden, so dass wir ihre Ausführung steuern können. Eine Schleife kann nur wenige Male ausgeführt werden, sie kann überhaupt nicht ausgeführt werden oder sie kann unendlich oft ausgeführt werden.

In unserem Code werden wir eine while-Schleife verwenden, die so lange läuft, bis die in Klammern gesetzte Bedingung erfüllt ist. Mit anderen Worten: Der Code innerhalb der Schleife wird ausgeführt, solange die Bedingung in den Klammern erfüllt ist. Wenn der Code innerhalb der Schleife ausgeführt wird, kehrt der Schaltkreis zum Anfang der Schleife zurück und führt sie erneut aus.

So etwas wie eine Endlosschleife kommt in der Programmierung immer wieder vor. Normalerweise wollen wir, dass das Programm die ganze Zeit läuft, egal ob wir nur die Leuchtdioden steuern oder z. B. Daten vom Temperatursensor lesen und den Wert auf einem Display anzeigen. Der Code muss ohne Unterbrechung ausgeführt werden, da sonst die Temperatur nur einmal abgelesen wird und nur ein Wert auf dem Bildschirm zu sehen ist.

Was sollte in diesem Fall in die Bedingung der while-Schleife aufgenommen werden, damit sie unbegrenzt ausgeführt wird? Die Antwort ist einfach: Wahrheit, oder einfach true. In der Sprache C können wir etwas wie true als eine immer erfüllte Bedingung behandeln. Auf diese Weise kann eine ständig laufende Schleife erstellt werden. Natürlich können wir auch kompliziertere Bedingungen in Klammern setzen, aber damit werden wir uns in späteren Materialien beschäftigen.

Nachdem wir die neue Datei extended_blink.uf2 kompiliert und auf den Raspberry Pi Pico W hochgeladen haben, können wir sehen, dass die LEDs dieses Mal wiederholt ein- und ausgeschaltet werden, d.h. unsere Endlosschleife funktioniert korrekt. Damit ist die Gestaltung des erweiterten Programms zur LED-Steuerung abgeschlossen, aber ich möchte Sie ermutigen, zu experimentieren. Sie können versuchen, die Anschlüsse zu ändern, an die die Leuchtelemente angeschlossen sind, die Timing-Werte zu ändern oder die gpio_put Funktionen komplett zu ändern, so dass die LEDs jetzt synchron ausgeschaltet werden statt einzuschalten. Mit diesen wenigen Anweisungen, die ich in diesem Artikel beschrieben habe, können Sie recht interessante Lichteffekte vorbereiten. Abschließend möchte ich sagen, dass Sie sich nicht scheuen sollten, Ihre eigenen Projekte zu erstellen, denn dadurch lernen Sie tatsächlich das Programmieren.

Das Problem von sleep_ms und anderen blockierenden Funktionen

Der Kern eines der RP2040-Chip-Prototypen. (https://forbot.pl/blog/jak-powstawal-mikrokontroler-raspberry-pi-rp2040-id47544)

Zum Schluss möchte ich Ihnen noch etwas anderes sagen. Im heutigen Projekt haben wir die Funktion sleep_ms verwendet, die, wie andere so genannte blockierende Funktionen, aus bestimmten Gründen problematisch ist. Auf den ersten Blick mag diese Funktion sehr praktisch und nützlich erscheinen, denn sie ermöglicht es, das Programm für eine bestimmte Zeit zu unterbrechen, aber genau darin liegt leider ihr größtes Problem. Was passiert mit dem RP2040-Chip, wenn er auf den Befehl sleep_ms trifft? Der Chip wartet, bis die angegebene Zeit verstrichen ist, führt dann aber keine Aufgaben aus und kann, was noch schlimmer ist, nicht auf externe Faktoren reagieren. Auf den ersten Blick mag dies unbedeutend erscheinen, aber sobald wir uns mit so etwas wie Unterbrechungen vertraut gemacht haben, wird deutlich, dass es höchst unratsam ist, ein Programm zu pausieren. Wenn ein Mikrocontroller einfach nur wartet, wird seine Leistung verschwendet.

Ich möchte, dass Sie sich daran erinnern, dass jede blockierende Funktion, auch wenn sie verlockend ist, in der Programmierung unerwünscht ist. Es gibt bessere Möglichkeiten, das Programm scheinbar “anzuhalten”, die wir natürlich in Zukunft erforschen werden. Die Funktion sleep_ms gehört nicht zu den verbotenen Befehlen, aber wenn Sie sich entscheiden, sie in Ihren Code einzubauen, müssen Sie dies sorgfältig durchdenken und sich ihrer Grenzen bewusst sein.

Ein paar Worte zum Schluss...

Das erste Projekt, das von Grund auf neu erstellt wurde, liegt hinter uns. Wir haben drei LEDs zum Laufen gebracht und ich hoffe, dass Sie nach dem Erlernen des Codes einige Änderungen daran vorgenommen haben, mit anderen Worten, Sie haben experimentiert, denn das Spielen mit dem Code ist das Wesentliche am Programmieren. Meine Aufgabe besteht lediglich darin, ein paar einfache Funktionen zu beschreiben, wie sie funktionieren, was sie bewirken und wie man sie in praktischen Beispielen einsetzt, aber die Magie der Wissenschaft liegt im Prototyping. Außerdem habe ich Ihnen etwas über Make-Konfigurationsdateien erzählt, und wir haben auch etwas über die erste Art von Schleifen gelernt, die es in der Programmierung gibt. Schließlich erfuhren wir etwas über die Problematik der so genannten Blockierfunktionen. In den folgenden Materialien werden Sie viele Neuigkeiten erfahren, wir werden mehr über Schleifentypen und bedingte Funktionen lernen, alles anhand von praktischen Projekten.

Quellen:

  • https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf
  • https://datasheets.raspberrypi.com/picow/pico-w-datasheet.pdf
  • https://www.raspberrypi.com/products/rp2040/
  • https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html

Wie hilfreich war dieser Beitrag?

Klicke auf die Sterne um zu bewerten!

Durchschnittliche Bewertung 5 / 5. Stimmenzahl: 18

Bisher keine Bewertungen! Sei der Erste, der diesen Beitrag bewertet.

Teilen:

Picture of Rafał Bartoszak

Rafał Bartoszak

Ein mit Botland kooperierender Elektroniker, der sein Wissen im Internet teilt. Enthusiast für digitale Systeme, programmierbare Schaltungen und Mikroelektronik. Leidenschaftlich für Geschichte, mit besonderem Schwerpunkt auf dem 20. Jahrhundert.

Siehe mehr:

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Aus Sicherheitsgründen ist die Verwendung des reCAPTCHA-Dienstes von Google erforderlich, der den Google-Datenschutzbestimmungen und Nutzungsbedingungen unterliegt..