Grundlagen C++ ============== Jede Anweisung in C++ wird mit einem Semikolon abgeschlossen. Die Funktionen ``setup()`` und ``loop()`` sind die Hauptfunktionen in einem Arduino-Programm. Die ``setup()`` Funktion wird einmal zu Beginn des Programms ausgeführt, während die ``loop()`` Funktion kontinuierlich wiederholt wird. Variablen --------- In Variablen können Werte gespeichert werden. Diese Werte können sich während der Laufzeit des Programms ändern. Variablen haben einen Namen, einen Datentyp und einen Wert. Der Datentyp gibt an, welche Art von Wert in der Variablen gespeichert werden kann. Es gibt verschiedene Datentypen, die in C++ verwendet werden können. Beispiel: Addition von zwei Zahlen .. code-block:: cpp int a = 5; // Deklaration einer Variablen vom Typ Integer int b = 3; // Deklaration einer weiteren Variablen vom Typ Integer int c = a + b; // Addition der beiden Variablen a = a + b + c; // Variable a hat jetzt den Wert 16 b = a - 2; // Variable b hat jetzt den Wert 14 In diesem Beispiel werden zwei Variablen ``a`` und ``b`` vom Typ Integer deklariert und mit den Werten 5 und 3 initialisiert. Die Variable ``c`` wird als Summe von ``a`` und ``b`` berechnet und enthält den Wert 8. Weitere Verwendungsmöglichkeiten sind später in Beispielen für die Funktionen ``digitalRead()`` und ``analogRead()`` zu sehen. Gültigkeitsbereich von Variablen ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Der Gültigkeitsbereich einer Variablen gibt an, in welchem Teil des Programms die Variable verwendet werden kann. Variablen können entweder global oder lokal sein. Globale Variablen sind im gesamten Programm verfügbar, während lokale Variablen nur in einem bestimmten Bereich des Codes verfügbar sind. Lokale Variablen werden innerhalb einer Funktion deklariert und sind nur innerhalb dieser Funktion gültig. Globale Variablen werden außerhalb von Funktionen deklariert und sind im gesamten Programm verfügbar. Beispiel: .. code-block:: cpp int globalVariable = 10; // Globale Variable void setup() { int localVariable = 5; // Lokale Variable } In diesem Beispiel ist ``globalVariable`` eine globale Variable, die im gesamten Programm verfügbar ist. ``localVariable`` ist eine lokale Variable, die nur in der Funktion ``setup()`` verfügbar ist. Datentypen ^^^^^^^^^^ Die wichtigsten Datentypen in C++ für die Arduino Programmierung zur Speicherung von Ganzzahlen sind: ============================= ============================== **Typ** **Wertebereich** ============================= ============================== char -128 bis 127 bzw. 0 bis 255 unsigned char 0 bis 255 int -32.768 bis 32.767 unsigned int 0 bis 65.535 long -2.147.483.648 bis 2.147.483.647 unsigned long 0 bis 4.294.967.295 ============================= ============================== Die Datentypen char, int und long können sowohl vorzeichenbehaftet (signed) als auch vorzeichenlos (unsigned) verwendet werden. Vorzeichenlose Datentypen können nur positive Werte speichern, haben aber einen größeren Wertebereich als vorzeichenbehaftete Datentypen. Für eine übersichtlichere Darstellung können folgende Datentypen verwendet werden: ============================= ============================== **Typ** **Wertebereich** ============================= ============================== int8_t -128 bis 127 uint8_t 0 bis 255 int16_t -32.768 bis 32.767 uint16_t 0 bis 65.535 int32_t -2.147.483.648 bis 2.147.483.647 uint32_t 0 bis 4.294.967.295 ============================= ============================== Diese Datentypen sind plattformunabhängig und garantieren eine bestimmte Größe, unabhängig von der Plattform, auf der der Code ausgeführt wird. Zur Speicherung von Kommazahlen können folgende Datentypen verwendet werden: ============================= ============================== **Typ** **Genauigkeit** ============================= ============================== float 6-7 signifikante Stellen double 15-16 signifikante Stellen ============================= ============================== Der Datentyp `bool` wird zur Speicherung von Wahrheitswerten verwendet und kann nur die Werte `true` oder `false` annehmen. In C++ ist generell alles Wahr, was nicht ``0`` ist. Das bedeutet, dass ``0`` als ``false`` interpretiert wird und alles andere als ``true``. Beispiel: .. code-block:: cpp bool flag = true; // Deklaration einer boolschen Variablen int result = 10; // result ist true, da 10 nicht 0 ist int status = 0; // status ist false, da 0 false ist Arrays ------ Ein Array ist eine Sammlung von Variablen des gleichen Datentyps, die unter einem gemeinsamen Namen gespeichert sind. Jedes Element im Array hat einen Index, der angibt, an welcher Position es sich im Array befindet. Der Index beginnt bei 0 und endet bei der Größe des Arrays minus 1. Beispiel: .. code-block:: cpp int numbers[5]; // Deklaration eines Arrays mit 5 Elementen numbers[0] = 10; // Setzt das erste Element auf 10 numbers[1] = 20; // Setzt das zweite Element auf 20 numbers[2] = 30; // Setzt das dritte Element auf 30 numbers[3] = 40; // Setzt das vierte Element auf 40 numbers[4] = 50; // Setzt das fünfte Element auf 50 int temp = numbers[2]; // Liest das dritte Element in die Variable temp -> temp = 30 Funktionen ---------- Funktionen sind benannte Codeblöcke, die eine bestimmte Aufgabe erfüllen. Sie können Parameter entgegennehmen und einen Wert zurückgeben. Funktionen ermöglichen es, den Code in übersichtliche und wiederverwendbare Teile zu gliedern. Beispiel: .. code-block:: cpp // Definition einer Funktion, die zwei Zahlen addiert int add(int a, int b) { return a + b; } void setup() { int result = add(3, 4); // Aufruf der Funktion add } In diesem Beispiel wird die Funktion ``add()`` definiert, die zwei Zahlen addiert und das Ergebnis zurückgibt. In der Funktion ``setup()`` wird die Funktion ``add()`` mit den Parametern 3 und 4 aufgerufen und das Ergebnis in der Variablen ``result`` gespeichert. Operatoren ---------- Operatoren sind Symbole, die verwendet werden, um Operationen auf Variablen und Werten durchzuführen. Es gibt verschiedene Arten von Operatoren in C++, darunter arithmetische, logische, Vergleichs- und Zuweisungsoperatoren. Arithmetische Operatoren: ^^^^^^^^^^^^^^^^^^^^^^^^^ Arithmetische Operatoren werden verwendet, um mathematische Operationen wie Addition, Subtraktion, Multiplikation und Division durchzuführen. ============================= ============================== **Operator** **Bedeutung** ============================= ============================== `+` Addition `-` Subtraktion `*` Multiplikation `/` Division `=` Zuweisung ============================= ============================== Beispiel: .. code-block:: cpp int a = 5; int b = 3; int sum = a + b; // Addition int difference = a - b; // Subtraktion int product = a * b; // Multiplikation int quotient = a / b; // Division logische Operatoren ^^^^^^^^^^^^^^^^^^^ Logische Operatoren werden verwendet, um logische Operationen wie UND, ODER und NICHT durchzuführen. ============================= ============================== **Operator** **Bedeutung** ============================= ============================== < Kleiner als <= Kleiner oder gleich > Größer als >= Größer oder gleich == Gleichheit ! logisches NICHT != Ungleichheit && logisches UND || logisches ODER ============================= ============================== If - else Anweisung ^^^^^^^^^^^^^^^^^^^ Die If-Else-Anweisung wird verwendet, um Entscheidungen zu treffen und Codeblöcke basierend auf einer Bedingung auszuführen. If - else Anweisung ^^^^^^^^^^^^^^^^^^^ Die If-Else-Anweisung wird verwendet, um Entscheidungen zu treffen und Codeblöcke basierend auf einer Bedingung auszuführen. Beispiel für logische Operatoren und If-Anweisungen ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: cpp int a = 5; int b = 10; bool c = true; bool d = false; if (a < b) // Überprüft, ob a kleiner als b ist { // Dieser Block wird ausgeführt, weil a kleiner als b ist } if (a <= b) // Überprüft, ob a kleiner oder gleich b ist { // Dieser Block wird ausgeführt, weil a kleiner oder gleich b ist } if (a > b) // Überprüft, ob a größer als b ist { // Dieser Block wird nicht ausgeführt, weil a nicht größer als b ist } if (a >= b) // Überprüft, ob a größer oder gleich b ist { // Dieser Block wird nicht ausgeführt, weil a nicht größer oder gleich b ist } if (a == b) // Überprüft, ob a gleich b ist { // Dieser Block wird nicht ausgeführt, weil a nicht gleich b ist } if (a != b) // Überprüft, ob a ungleich b ist { // Dieser Block wird ausgeführt, weil a ungleich b ist } if (c && d) // Überprüft, ob sowohl c als auch d wahr sind (logisches UND) { // Dieser Block wird nicht ausgeführt, weil c und d nicht beide wahr sind } if (c || d) // Überprüft, ob entweder c oder d wahr ist (logisches ODER) { // Dieser Block wird ausgeführt, weil c wahr ist } if (!(c && d) || a < b) // Überprüft, ob c und d nicht beide wahr sind oder ob a kleiner als b ist (logisches NICHT kombiniert mit UND und ODER) { /* Dieser Block wird ausgeführt, weil c und d nicht beide wahr sind oder a kleiner als b ist c && d ist falsch, also wird !(c && d) wahr */ } if (a < 20) // Überprüft, ob a kleiner als 20 ist { // Dieser Block wird ausgeführt, weil a kleiner als 20 ist } if (b >= 10) // Überprüft, ob b größer oder gleich 10 ist { // Dieser Block wird ausgeführt, weil b größer oder gleich 10 ist } if (c) // Überprüft, ob c wahr ist { // Dieser Block wird ausgeführt, weil c true ist } if (!d) // Überprüft, ob d nicht wahr ist { // Dieser Block wird ausgeführt, weil d false ist } if(a) // Überprüft, ob a ungleich 0 ist { // Dieser Block wird ausgeführt, weil a ungleich 0 ist } Beispiel für If, If-Else und Else-Anweisungen ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: cpp int x = 15; if (x < 10) // Überprüft, ob x kleiner als 10 ist { // Dieser Block wird nicht ausgeführt, weil x nicht kleiner als 10 ist } else if (x < 20) // Überprüft, ob x kleiner als 20 ist. Wird nur ausgeführt, wenn die vorherige Bedingung falsch ist { // Dieser Block wird ausgeführt, weil x kleiner als 20 ist } else // Wenn keine der vorherigen Bedingungen wahr ist { // Dieser Block wird nicht ausgeführt, weil eine der vorherigen Bedingungen wahr ist } Switch-Case-Anweisung ^^^^^^^^^^^^^^^^^^^^^ Die Switch-Case-Anweisung wird verwendet, um eine Variable auf verschiedene Werte zu überprüfen und basierend auf diesen Werten verschiedene Codeblöcke auszuführen. Beispiel für Switch-Case-Anweisung ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: cpp int day = 3; switch (day) { case 1: // Dieser Block wird ausgeführt, wenn day gleich 1 ist break; case 2: // Dieser Block wird ausgeführt, wenn day gleich 2 ist break; case 3: // Dieser Block wird ausgeführt, wenn day gleich 3 ist break; default: // Dieser Block wird ausgeführt, wenn kein case zutrifft break; } Die ``break`` Anweisung wird verwendet, um die Switch-Case-Anweisung zu beenden. Wenn ``break`` nicht verwendet wird, werden alle nachfolgenden Cases ebenfalls ausgeführt. Schleifen --------- Schleifen werden verwendet, um Codeblöcke mehrmals auszuführen. Es gibt verschiedene Arten von Schleifen in C++, darunter ``for``, ``while`` und ``do-while`` Schleifen. For-Schleife ^^^^^^^^^^^^ Die For-Schleife wird verwendet, um einen Codeblock eine bestimmte Anzahl von Malen auszuführen. Beispiel für For-Schleife ^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: cpp for (int i = 0; i < 5; i++) { // Dieser Block wird 5 Mal ausgeführt } In diesem Beispiel wird der Codeblock 5 Mal ausgeführt, da die Schleife von 0 bis 4 läuft (i < 5). Der Wert von ``i`` wird bei jedem Durchlauf um 1 erhöht (i++). Anstatt `5` kann auch eine Variable oder ein Ausdruck stehen. Es kann beispielsweie über ein Array iteriert werden. .. code-block:: cpp int numbers[] = {1, 2, 3, 4, 5}; for (int i = 0; i < sizeof(numbers); i++) // sizeof(numbers) gibt die Anzahl der Elemente im Array zurück { Serial.print(numbers[i]); Serial.print("\n"); } In diesem Beispiel wird über das Array ``numbers`` iteriert und jeder Wert wird auf dem seriellen Monitor angezeigt. Um über Arrays zu iterieren kann auch eine ``for-each`` Schleife verwendet werden. .. code-block:: cpp int numbers[] = {1, 2, 3, 4, 5}; for (int number : numbers) { Serial.print(number); Serial.print("\n"); } While-Schleife ^^^^^^^^^^^^^^ Die While-Schleife wird verwendet, um einen Codeblock so lange auszuführen, wie eine Bedingung wahr ist. Beispiel für While-Schleife .. code-block:: cpp int i = 0; while (digitalRead(12) == LOW) { // Dieser Block wird ausgeführt, solange digitalRead(12) LOW zurückgibt } In diesem Beispiel wird der Codeblock so lange ausgeführt, wie der Wert von ``digitalRead(12)`` LOW zurückgibt. Die Bedingung wird vor jedem Durchlauf überprüft. Wenn die Bedingung von Anfang an falsch ist, wird der Codeblock nie ausgeführt. Dadurch kann so lange gewartet werden, bis der Button gedrückt wird. Do-While-Schleife ^^^^^^^^^^^^^^^^^ Die Do-While-Schleife wird verwendet, um einen Codeblock mindestens einmal auszuführen und dann so lange auszuführen, wie eine Bedingung wahr ist. Beispiel für Do-While-Schleife .. code-block:: cpp int i = 0; do { // Dieser Block wird mindestens einmal ausgeführt } while (i < 5); Printausgaben ------------- Printausgaben werden verwendet, um Informationen auf dem seriellen Monitor anzuzeigen. Dies ist nützlich, um den Programmablauf zu überwachen und Fehler zu finden. Beispiel für Printausgaben .. code-block:: cpp int sensorValue = analogRead(A0); Serial.begin(9600); Serial.print("Sensorwert: "); Serial.println(sensorValue); Serial.print("\n"); // Fügt einen Zeilenumbruch hinzu -> Leere Zeile In diesem Beispiel wird der Wert eines Sensors, der an Pin A0 angeschlossen ist, gelesen und auf dem seriellen Monitor angezeigt. Die Funktion ``Serial.begin(9600)`` initialisiert die serielle Kommunikation mit einer Baudrate von 9600. Mit ``Serial.print()`` wird der Text ``Sensorwert:`` und mit ``Serial.println()`` der Wert des Sensors auf dem seriellen Monitor angezeigt. Der Unterschied zwischen ``print()`` und ``println()`` besteht darin, dass ``println()`` einen Zeilenumbruch am Ende hinzufügt. Manuell kann auch ein Zeilenumbruch mit ``\n`` hinzugefügt werden. Grundlagen Arduino ================== Ein leeres Arduino-Programm besteht aus zwei Funktionen: ``setup()`` und ``loop()``. Die ``setup()`` Funktion wird einmal zu Beginn des Programms ausgeführt, während die ``loop()`` Funktion kontinuierlich wiederholt wird. In der ``setup()`` Funktion werden die Initialisierungen und Konfigurationen durchgeführt, während in der ``loop()`` Funktion der Hauptprogrammablauf stattfindet. Konfiguration von Pins ---------------------- Die Pins eines Mikrocontrollers können als Ein- und Ausgänge konfiguriert werden. .. code-block:: cpp pinMode(13, OUTPUT); // Pin 13 als Ausgang pinMode(12, INPUT); // Pin 12 als Eingang Die Funktion ``pinMode()`` wird genutzt, um die Pins des Mikrocontrollers zu konfigurieren. Der erste Parameter gibt den Pin an, der konfiguriert werden soll. Der zweite Parameter gibt an, ob der Pin als Ein- oder Ausgang konfiguriert werden soll. Weitere Informationen: https://www.arduino.cc/reference/de/language/functions/digital-io/pinmode/ Konfiguration als Ausgang ^^^^^^^^^^^^^^^^^^^^^^^^^ Es kann entweder ein ``HIGH`` oder ``LOW`` Signal an den Pin gelegt werden. Ein ``HIGH`` Signal entspricht einer Spannung von 3,3V und ein ``LOW`` Signal entspricht einer Spannung von 0V. Damit können beispielsweise die LEDs angesteuert und zum leuchten gebracht werden. Dafür wird die Funktion ``digitalWrite()`` genutzt. Beispiel: .. code-block:: cpp digitalWrite(13, HIGH); // Setzt Pin 13 auf HIGH -> LED leuchtet delay(1000); // Wartet 1 Sekunde digitalWrite(13, LOW); // Setzt Pin 13 auf LOW -> LED leuchtet nicht delay(1000); // Wartet 1 Sekunde Weitere Informationen: https://www.arduino.cc/reference/de/language/functions/digital-io/digitalwrite/ Zusätzlich kann die Funktion analogWrite() genutzt werden um PWM Signale zu erzeugen. PWM Signale ermöglicht die Helligkeit von LEDs zu steuern oder Motoren zu regeln. Der Funktion kann ein Wert zwischen 0 und 255 übergeben werden .. code-block:: cpp analogWrite(13, 0); // LED leuchtet nicht delay(1000); // Wartet 1 Sekunde analogWrite(13, 127); // LED leuchtet mit halber Helligkeit delay(1000); // Wartet 1 Sekunde analogWrite(13, 255); // LED leuchtet mit voller Helligkeit delay(1000); // Wartet 1 Sekunde Weitere Informationen: https://www.arduino.cc/reference/de/language/functions/analog-io/analogwrite/ Konfiguration als Eingang ^^^^^^^^^^^^^^^^^^^^^^^^^ Die Pins eines Mikrocontrollers können auch als Eingänge konfiguriert werden, um Signale von externen Quellen zu lesen. Dafür wird die Funktion ``digitalRead()`` verwendet. Diese Funktion überprüft, ob eine Spannung an einem Pin anliegt der als Eingang konfiguriert ist und gibt entweder HIGH oder LOW zurück. Beispiel: .. code-block:: cpp int buttonState = digitalRead(12); // Liest den Zustand von Pin 12 In diesem Beispiel wird der Zustand eines Tasters, der an Pin 12 angeschlossen ist, gelesen und in der Variablen ``buttonState`` gespeichert. Wenn der Taster gedrückt ist, wird der Wert HIGH zurückgegeben, andernfalls LOW. Weitere Informationen: https://www.arduino.cc/reference/de/language/functions/digital-io/digitalread/ Die Pins eines Mikrocontrollers können auch als Analogeingänge konfiguriert werden, um analoge Signale von externen Quellen zu lesen. Dafür wird die Funktion ``analogRead()`` verwendet. Diese Funktion liest den aktuellen Spannungswert an einem Pin, der als Analogeingang konfiguriert ist, und gibt einen Wert zwischen 0 und 8192 zurück. Beispiel: .. code-block:: cpp int sensorValue = analogRead(A0); // Liest den analogen Wert von Pin A0 In diesem Beispiel wird der Wert eines Sensors, der an Pin A0 angeschlossen ist, gelesen und in der Variablen ``sensorValue`` gespeichert. Weitere Informationen: https://www.arduino.cc/reference/de/language/functions/analog-io/analogread/ .. _zeit-abschnitt: Zeit ^^^^ Mithilfe der Funktion ``delay()`` kann eine Pause im Programmablauf erzeugt werden. Die Funktion erwartet einen Wert in Millisekunden, der die Dauer der Pause angibt. Für eine genauere Verzögerung kann die Funktion ``delayMicroseconds()`` verwendet werden. Diese Funktion erwartet einen Wert in Mikrosekunden. Beispiel: .. code-block:: cpp delay(1000); // Pause für 1 Sekunde delayMicroseconds(1000); // Pause für 1 Millisekunde Weitere Informationen: https://www.arduino.cc/reference/de/language/functions/time/delay/ und https://www.arduino.cc/reference/de/language/functions/time/delaymicroseconds/ Die Zeit, die seit dem Start des Programms vergangen ist, kann mit der Funktion ``millis()`` abgefragt werden. Diese Funktion gibt die Anzahl der Millisekunden zurück, die seit dem Start des Programms vergangen sind. Für präzisere Zeitmessungen kann die Funktion ``micros()`` verwendet werden, die die Anzahl der Mikrosekunden seit dem Start des Programms zurückgibt. Beispiel: .. code-block:: cpp unsigned long startTime = millis(); // Startzeit speichern delay(1000); // Pause für 1 Sekunde unsigned long elapsedTime = millis() - startTime; // Vergangene Zeit berechnen Weitere Informationen: https://www.arduino.cc/reference/de/language/functions/time/millis/ und https://www.arduino.cc/reference/de/language/functions/time/micros/ Die Zeit, die ein Pin HIGH oder LOW ist, kann mit der Funktion ``pulseIn()`` gemessen werden. Diese Funktion erwartet den Pin, an dem das Signal gemessen werden soll, und den Zustand des Signals (HIGH oder LOW), das gemessen werden soll. Sie gibt die Dauer des Signals in Mikrosekunden zurück. Weitere Informationen: https://www.arduino.cc/reference/de/language/functions/advanced-io/pulsein/ Beispiel: .. code-block:: cpp unsigned long duration = pulseIn(12, HIGH); // Misst die Dauer des HIGH-Signals an Pin 12 Informationen zu allen verfügbaren Funktionen und Bibliotheken finden Sie in der Arduino-Referenz: https://www.arduino.cc/reference/de/ Kommentare ---------- Kommentare sind Texte, die im Quellcode enthalten sind, aber vom Compiler ignoriert werden. Sie dienen dazu, den Code zu dokumentieren und zu erklären. Es gibt zwei Arten von Kommentaren in C++: - Einzeilige Kommentare beginnen mit ``//`` und erstrecken sich bis zum Ende der Zeile. - Mehrzeilige Kommentare beginnen mit ``/*`` und enden mit ``*/``. Sie können über mehrere Zeilen gehen. Beispiel: .. code-block:: cpp // Dies ist ein einzeiliger Kommentar /* Dies ist ein mehrzeiliger Kommentar. Er erstreckt sich über mehrere Zeilen. */