Zum Hauptinhalt springen

Funktionen

Eine Funktionen ist ein zusammengefasster Codeblock (Unterprogramm), welcher an beliebigen Stellen eines Programms (wiederkehrend) aufgerufen werden kann. Wird eine Funktion in einem Programm aufgerufen, so wird zuerst der Code der Funktion ausgeführt und anschließend das Programm an der Stelle des Funktionsaufrufes weitergeführt. Funktionen können Parameter als Eingabegrößen akzeptieren und berechnete Werte zurückgeben.

Eine Funktion zum Anschalten einer LED

Ein sehr einfaches Beispiel für eine Funktion könnte das Anschalten einer LED sein. Diese Funktion soll keine Eingabeparameter und keine Rückgabewerte haben und beim Aufruf eine vorher festgelegte LED anschalten. Deshalb beginnt die Funktionsdefinition mit dem Schlüsselwort void, was angibt, dass die Funktion keinen Rückgabewert hat.

Nach dem Schlüsselwort void folgt der selbst gewählte Name der Funktion und ein runde Klammer. Der von der Funktion auszuführende Code wird anschließend zwischen zwei geschweifte Klammern {...} geschrieben.

// Funktionsdefinition für `anschaltenLed()`
void anschaltenLed() // Keine Parameter, keine Rückgabewert
{
digitalWrite(2,HIGH); // Eine Funktion kann auch mehr
// als eine Zeile Code enthalten.
}

Nachdem eine Funktion definiert wurde, kann sie mit ihrem Namen gefolgt von zwei Klammern () aufgerufen werden:

anschaltenLed();  //  Funktionsaufruf

Ähnlich wie bei Schleifen oder Programmverzweigungen kann auch eine Funktion auf globale Variablen zugreifen. Im folgenden Beispiel wird die globale Variable pinLed zum Schalten der LED genutzt.

int pinLed = 2;

void anschaltenLed()
{
digitalWrite(pinLed,HIGH); // Die Funktion greift auf die
// globale Variable `pinLed` zu.
}

Wird noch eine weitere Funktion ausschaltenLed() definiert, so ergibt sich ein sehr verständlicher Code zum Blinken eine LED:

int pinLed = 2;   

// Eine Funktionsdefinition
void anschaltenLed(){
digitalWrite(pinLed,HIGH);
}

// Noch eine Funktionsdefinition
void ausschaltenLed(){
digitalWrite(pinLed,LOW);
}

void setup() {
pinMode(pinLed,OUTPUT);
}

void loop() {
anschaltenLed(); // Funktionsaufruf
delay(1000);
ausschaltenLed(); // Funktionsaufruf
delay(1000);
}
caution

Beim Aufruf einer Funktion dürfen die runden Klammern nach dem Funktionsnamen nicht fehlen.

Konventionen

Eine wesentliche Aufgabe von Funktionen ist es, ein Programm lesbar zu machen. Aus diesem Grund sind die gewählten Funktionsnamen äußerst wichtig. Folgende Regeln sollten Sie beim Schreiben eigener Funktionen beachten:

  • Ein Funktionsname beginnt immer mit einem Verb im Infinitiv. Anschließend können weitere Wörter zum Erläutern folgen (schaltenLed(), messenSensor(), lesenZustand(), ...).
  • Der Funktionsname beschreibt nur die von der Funktion ausgeführte Aktion.
  • Je kürzer eine Funktion, desto besser. Schreiben Sie lieber zwei oder drei kurze Funktionen, als eine lange Funktion.
  • Nutzen Sie Funktionen auch bei kurzen Programmen.
Aufgaben
  1. Schreiben Sie die Funktion gruessen() (verwenden Sie keine Umlaute), welche auf dem seriellen Monitor folgenden Satz schreibt:

    Hallo Welt, wie geht es?

    Nutzen Sie ansschließend die Funktion, um den Satz dreimal auszugeben:

    Hallo Welt, wie geht es?
    Hallo Welt, wie geht es?
    Hallo Welt, wie geht es?
  2. Schreiben Sie eine Funktion aufblinken(), welche ein LED zuerst anschaltet und 0,2 Sekunden später wieder ausschaltet. Nutzen Sie die Funktion, um eine LED blinken zu lassen:

    void loop(){
    aufblinken();
    delay(1000);
    }

Funktionen mit Parametern

Im obigen Beispiel kann mit der Funktion anschaltenLed() die LED am Pin pinLed angeschaltet werden. Aber was ist, wenn mit der selben Funktion auch eine zweite oder dritte LED angeschaltet werden soll? Eine Lösung wäre, die globale Variable pinLed zu ändern. Allerdings führt das zu einem sehr unübersichtlichen Code.

Besser ist es, der Funktion einen Parameter zu übergeben, der angibt, welche LED angeschaltet werden soll. Der Funktionsparameter wird bei der Funktionsdefintion nach dem Funktionsnamen in runden Klammern angegeben.

Da es sich bei dem Funktionsparameter um eine Variable handelt, muss zusätzlich auch der Datentyp des Parameters angegeben werden.

// Funktion mit Parameter vom Typ Integer
void anschaltenLed(int pParameter) {
// `pParameter`kann wie eine beliebige Variable genutzt werden
// existiert aber nur innerhalb der Funktion.
}

Innerhalb der Funktion kann der Parameter wie jede andere Variable verwendet werden. Außerhalb der Funktion, also in einer anderen Funktion oder im Hauptprogramm, kann auf den Parameter nicht zugegriffen werden. Der Gültigkeitsbereich des Funktionsparameters bezieht sich nur auf die Funktion selbst.

Konvention

Damit Funktionsparameter von globalen oder lokalen Variablen unterschieden werden können, ist es sinnvoll, sie speziell zu kennzeichnen. An dieser Stelle soll daher die Konvention eingeführt werden, dass jeder Funktionsparameter mit einem kleinen p beginnt. Anschließend folgt eine aussagekräftige Bezeichnung für den Parameter (z.B. pPinLED oder pZustand).

Beispiel

Im folgenden Beispiel werden mit einer Funktion mit Parametern zwei LEDs nacheinander angeschaltet.

#define LED1 4
#define LED2 5

void anschaltenLed(int pPinLed){ // Funktionsdefinition mit Paramter
digitalWrite(pPinLed, HIGH);
}

void setup(){
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);

anschaltenLed(LED1); // Funktionsaufruf mit Parameter
delay(500);
anschaltenLed(LED2); // Funktionsaufruf mit Parameter
}

void loop(){
// bleibt leer
}

Eine Funktion kann auch mehr als einen Parameter haben. In diesem Fall werden alle weiteren Parameter durch ein Komma voneinander getrennt in der Funktionsdefinition angegeben:

void anschaltenLed(int pParameter1, bool pParamter2, float pParameter3) {
// Eine Funktion mit mehreren Parametern.
}
caution

Als Konvention beginnt der Name eines Funktionsparamters immer mit einem kleinen p. Zum Beispiel pPinLED oder pZustand.

Aufgaben
  1. Schreiben Sie eine Funktion blinkenLED(int pPeriodendauer), welche eine LED am Pin 3 blinken lässt. Der Funktionsparameter soll die Periodendauer in Millisekunden des Blinksignals angeben. Testen Sie die Funktion.

  2. Erweitern Sie die Funktion blinkenLED() (Aufgabe 1) um einen Parameter für den verwendeten LED-Pin. Überprüfen Sie, ob es mit der Funktion möglich ist, zwei LEDs gleichzeitig blinken zu lassen.

    int LED1 = 5;
    int LED2 = 6;

    void loop(){
    blinkenLED(LED1,1000);
    blinkenLED(LED2,500);
    }
  3. Schreiben Sie eine Funktion zum Schalten einer LED. Die Funkion schalten(int pPin, bool pZustand) soll zwei Paramter erhalten, welche den Pin der LED und den aktuellen Zustand der LED angeben. Nutzen Sie die Funktion, um eine LED blinken zu lassen.

  4. Schreiben Sie eine Funktion codierenBuchstabe(char pBuchstabe) welche den Morse-Code für den angegeben Buchstaben an einer LED als Blink-Muster ausgibt (Es ist ausreichend, wenn die Funktion nur die Buchstaben 'O' und 'S' codieren kann). Nutzen Sie die Funktion, um den Morse-Code für SOS ein einer LED ausgeben zu lassen. Informieren Sie sich bei Wikipedia über den Morse-Code.

    Ihre loop() Funktion sollte folgendermaßen aussehen:

    void loop() {
    codierenBuchstabe('S');
    codierenBuchstabe('O');
    codierenBuchstabe('S');
    zeigeWortabstand(); // Zeitlicher Abstand zwischen zwei Wörtern
    }

Funktionen mit Rückgabewert

int summe(int a, int b){
return a+b;
}

Statische Variablen

Statische Variablen, die innerhalb einer Funktion deklariert werden, existieren auch nach dem Beenden einer Funktion weiter. Das bedeutet, dass sie beim erneuten Ausführen der Funktion den selben Wert wie beim Beenden des letzten Funktionsaufrufs haben. Sie eignen sich zum Beispiel zum Speichern von Zuständen.

Im folgenden Beispiel wird mit der statischen Variablen

static bool lZustandLed = false; 

der aktuelle Zustand einer LED gespeichert.

Bei jedem Aufruf der Funktion wird der Zustand der Variablen geändert und als digitales Signal ausgegeben. Die LED wird also bei jedem Funktionsaufruf umgeschaltet.

#define LED1 4

void umschaltenLed(int pPinLed){
// statische Variable, wird nach dem Beenden der Funktion nicht gelöscht
static bool lZustandLed = false;
lZustandLed != lZustandLed;
digitalWrite(pPinLed, lZustandLed);
}


void setup(){
pinMode(LED1,OUTPUT);
}

void loop(){
umschaltenLed(LED1); // Funktionsaufruf mit Parameter
delay(500);
}