Wer hätte gedacht, dass selbst unsere Bank-Karten oder der neue Personalausweis eingebettete Systeme1) sind?
Eingebettete Systeme sind anwendungsspezifisch, sie können also genau eine Sache richtig gut (die entsprechende Anwendung). Außerdem haben sie im Gegensatz zu Computern eine minimale Benutzerschnittstelle (z.B. nur einen Button, um die elektrische Zahnbürste zu starten und einen Drehregler, um die Rotationsgeschwindigkeit des Bürstenkopfs einzustellen). Sie zeichnen sich außerdem durch hohe Effizienz, Zuverlässigkeit und Stabilität aus, verbrauchen also so wenig Strom wie möglich, gehen (fast) nicht kaputt und tun genau das, was von ihnen will. Außerdem benötigen sie wenig Leistung / Ressourcen und sind günstig.

- 1 Arduino Uno R3
- 1 LED
- 1 Resistor
Verbindet die Komponenten mit Kabeln, indem ihr die entsprechenden Pins anklickt, um das Kabel zu erstellen:
- Linker Pin der LED mit dem oberen Pin des Resistors
- unterer Pin des Resistors mit einem GND-Port
- Rechter Pin der LED mit Port 2

void setup() { pinMode(2, OUTPUT); } void loop() { digitalWrite(2, HIGH); delay(1000); digitalWrite(2, LOW); delay(1000); }
f) Fertig ist euer erstes eingebettetes System. Es kann genau das, was es soll, nicht mehr und nicht weniger: eine LED zum Blinken bringen.
- Als Aktor wurde eine LED verwendet.
- Als Mikrocontroller wurde ein Arduino verwendet.
- Es wurden keine Sensoren verwendet.
Für die Programmierung des Arduino gibt es einige Regeln:
- Es gibt die Methoden
setup()
undloop()
. Sie sind ähnlich zu densetup()
- unddraw()
-Methoden, die ihr aus Processing-Programmen kennt.setup()
wird zu Beginn der Simulation einmal ausgeführt und regelt grundlegende Einstellungen, z.B. welche Pins als Eingabe- und welche als Ausgabe-Signale betrachtet werden. Mehr lesen.loop()
wird in einer Endlosschleife immer wieder hintereinander ausgefürt. Hier wird die Programmlogik geschrieben. Mehr lesen.
- Mit
pinMode(2, OUTPUT)
teilt man dem Arduino mit, dass an Pin Nr. 2 eine Ausgabe-Komponente angeschlossen ist Mehr lesen - Eingabesignale können mit
digitalRead(2)
gelesen werden (hier von Pin Nr. 2). Mehr lesen - Ausgabesignale können mit
digitalWrite(2, HIGH)
geschrieben werden (hier auf Pin Nr. 2). Mehr lesen
- Die Syntax von Arduino-Programmen ist die der Programmiersprache C (Siehe Referenz). Sie ist meistens sehr ähnlich zu Java.
HIGH
) und Strom aus (LOW
). Mikrokontroller wie der Arduino können an ihren Pins abfragen, welcher Zustand gerade anliegt (digitalRead()
) und diesen auch festlegen (digitalWrite()
).
- 1 Arduino Uno R3
- 2 Resistoren
- 1 LED
- 1 Button
Verbinde wie folgt:
- Die unteren Pins der beiden Resistoren mit dem GND-Port
- Der obere Pin des ersten Resistors mit dem linken Pin der LED
- Der obere Pin des zweiten Resistors mit dem unteren linken Pin des Buttons
- Der rechte Pin der LED mit Port 2 des Arduino
- Der rechte untere Pin des Buttons mit dem 5V-Port des Arduino
- Der linke obere Pin des Buttons mit Port 4 des Arduino

c) Starte die Simulation. Die LED sollte nun leuchten, wenn du den Button drückst. Wenn du den Button wieder loslässt, geht auch die LED aus.
- Als Sensor wurde ein Button verwendet, der Rest ist identisch zu Beispiel 1.
void setup() { pinMode(2, OUTPUT); pinMode(4, INPUT); } void loop() { int stateButton = digitalRead(4); if (stateButton == HIGH) { digitalWrite(2, HIGH); } else { digitalWrite(2, LOW); } delay(10); }
- 1x Arduino Uno R3
- 3x LED (1x grün, 1x gelb, 1x rot)
- 2x Widerstand
- 1x Button
Verkabelt wie folgt:
- Grüne LED an Port 4 (OUTPUT)
- Gelbe LED an Port 3 (OUTPUT)
- Rote LED an Port 2 (OUTPUT)
- Button an Port 1 (INPUT)

// Zuerst werden ein paar Konstanten definiert, die die verschiedenen Zustände der Ampel angeben. const int AMPEL_AUS = 0; const int AMPEL_GRUEN = 1; const int AMPEL_GELB = 2; const int AMPEL_ROT = 3; //Die Variable "ampel" speichert den aktuellen Zustand. int ampel = AMPEL_AUS; void setup() { // Die entsprechenden Ein- und Ausgänge werden definiert pinMode(1, INPUT); pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); // Alle drei LEDs werden ausgeschaltet digitalWrite(2, LOW); digitalWrite(3, LOW); digitalWrite(4, LOW); } void loop() { // Button-Status wird ausgelesen int reading = digitalRead(1); // Wenn Button gedrückt if (reading == HIGH) { // Ampel auf nächsten Status setzen ampel++; if (ampel > AMPEL_ROT) ampel = AMPEL_AUS; switch (ampel) { // Wenn Ampel aus, schalte alle LEDs aus case AMPEL_AUS: digitalWrite(2, LOW); digitalWrite(3, LOW); digitalWrite(4, LOW); break; // Wenn Ampel grün, schalte die grüne LED an und alle anderen aus case AMPEL_GRUEN: digitalWrite(2, LOW); digitalWrite(3, LOW); digitalWrite(4, HIGH); break; // Wenn Ampel gelb, schalte die gelbe LED an und alle anderen aus case AMPEL_GELB: digitalWrite(2, LOW); digitalWrite(3, HIGH); digitalWrite(4, LOW); break; // Wenn Ampel rot, schalte die rote LED an und alle anderen aus case AMPEL_ROT: digitalWrite(2, HIGH); digitalWrite(3, LOW); digitalWrite(4, LOW); break; } } }
Irgendwie scheint der Code nicht zu funktionieren. Es scheint eine zufällige LED angeschaltet zu werden, nicht nacheinander GRÜN → GELB → ROT → AUS → GRÜN → GELB → …
loop()
-Methode läuft als Endlosschleife. Unser Beispiel ist trotz der 50 Zeilen Code sehr kurz. Es läuft also extrem schnell ab. Wenn wir nun mit unseren Wurstfingern den Button drücken, wird die loop()
-Methode mehrfach durchlaufen, während der Button noch gedrückt ist, also als Status HIGH
hat. Bei echter Hardware kann es bei Buttons auch passieren, dass der Button bei einmal drücken mehrfach auslöst. Das nennt man Bouncing - "Hüpfen" und sorgt für viele Probleme: der Status der Ampel wird direkt hintereinander mehrfach druchgeschaltet - Die Ampelschaltung ist so nicht nutzbar.
millis()
, die uns die Millisekunden seit Start des Mikrocontrollers liefert (Mehr dazu). Mit ihrer Hilfe können wir eine Verzögerung einbauen - das so genannte debouncing, also dass der Status der Ampel nur geändert wird, wenn der Button 50 Millisekunden gedrückt wurde.
Dazu benötigen wir ein paar zusätzliche Variablen:
int buttonState; int lastButtonState = LOW; unsigned long lastDebounceTime = 0; unsigned long debounceDelay = 50;
Außerdem müssen wir die loop()
-Methode anpassen:
void loop() { int reading = digitalRead(1); if (reading != lastButtonState) { lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { if (reading != buttonState) { buttonState = reading; // Hier kommt der ursprüngliche Inhalt von loop() hin } } lastButtonState = reading; }
a) Dupliziert euren Ampel-Schaltkreis und speichert die Kopie unter "Eingebettete Systeme - 04 - Debounce-Ampel". Passt dann den Code der Ampelschaltung an:
const int AMPEL_AUS = 0; const int AMPEL_GRUEN = 1; const int AMPEL_GELB = 2; const int AMPEL_ROT = 3; int ampel = AMPEL_AUS; int buttonState; int lastButtonState = LOW; unsigned long lastDebounceTime = 0; unsigned long debounceDelay = 50; void setup() { pinMode(1, INPUT); pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); digitalWrite(2, LOW); digitalWrite(3, LOW); digitalWrite(4, LOW); } void loop() { int reading = digitalRead(1); if (reading != lastButtonState) { lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { if (reading != buttonState) { buttonState = reading; if (reading == HIGH) { ampel++; if (ampel > AMPEL_ROT) ampel = AMPEL_AUS; switch (ampel) { case AMPEL_AUS: digitalWrite(2, LOW); digitalWrite(3, LOW); digitalWrite(4, LOW); break; case AMPEL_GRUEN: digitalWrite(2, LOW); digitalWrite(3, LOW); digitalWrite(4, HIGH); break; case AMPEL_GELB: digitalWrite(2, LOW); digitalWrite(3, HIGH); digitalWrite(4, LOW); break; case AMPEL_ROT: digitalWrite(2, HIGH); digitalWrite(3, LOW); digitalWrite(4, LOW); break; } } } } lastButtonState = reading; }
b) Nun funktioniert die Ampelschaltung wie gewünscht: