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

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:

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:

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:

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:

// 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:

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

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

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

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

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.

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.

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

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

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

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.

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:

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

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:

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:

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

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:

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:

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:

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:

// Dies ist ein einzeiliger Kommentar

/*
Dies ist ein mehrzeiliger Kommentar.
Er erstreckt sich über mehrere Zeilen.
*/