Grundlagen · 18 Min. Lesezeit

Arduino programmieren lernen: Variablen, Schleifen, Funktionen

Arduino programmieren lernen: setup und loop, int, long, byte, Überlauf, const, #define, if-else, switch-case, Schleifen, Arrays, Funktionen mit LED-Beispielen.

Arduino programmieren heißt, einem Arduino-Board in der Sprache C/C++ zu sagen, was es tun soll: Du schreibst, welche LED wann leuchtet, was beim Drücken eines Tasters passiert und wie eine Zahl vom Sensor ausgewertet wird, und das Board wiederholt diese Anweisungen tausende Male pro Sekunde. Die gute Nachricht: Fast jeder Sketch, den du findest, vom Blinken einer LED bis zum Roboterauto, besteht aus denselben rund zehn Bausteinen. Das sind setup() und loop(), Variablen, Konstanten, Operatoren, if-else, switch-case, for- und while-Schleifen, Arrays und Funktionen.

In dieser Anleitung lernst du diese Bausteine nacheinander kennen, jeden mit einem echten LED- oder Taster-Beispiel. Alle Beispiele laufen auf derselben einfachen Schaltung und wurden für den Arduino Uno kompiliert und getestet. Die Stellen, an denen Einsteiger am häufigsten hängen bleiben, also Überlauf von Variablen, die Verwechslung von = und ==, ein vergessenes break und ein Zähler, der bei jedem Durchlauf neu startet, werden extra erklärt. In den letzten Abschnitten siehst du außerdem, wie dieselbe Logik auf dem ESP32 funktioniert und wie sie in MicroPython auf dem Raspberry Pi Pico aussieht.

Arduino Uno mit seinen digitalen Pins
Arduino Uno: Alle Beispiele in diesem Artikel nutzen einen Taster an Pin D2 und sechs LEDs an den Pins D8–D13. Dank der eingebauten LED an D13 brauchst du für die ersten Beispiele nicht einmal Kabel.

Was ist Arduino-Programmierung und welche Sprache wird verwendet?

Arduino-Code basiert auf C++; eine eigene "Arduino-Sprache" gibt es nicht. Der Arduino-Core ergänzt C++ um fertige Funktionen wie pinMode(), digitalWrite() und delay(). Die Datei, die du schreibst, heißt Sketch und hat die Endung .ino. Wenn du auf Überprüfen klickst, fügt die Arduino IDE oben die Header-Datei Arduino.h ein und erzeugt die Funktionsdeklarationen selbst, und der Compiler übersetzt den Code in Maschinencode, den der Prozessor versteht. Der Hochladen-Button schickt das Ergebnis dann per USB an den Bootloader des Boards. Falls du die IDE noch nicht installiert hast, beginne mit der Anleitung Arduino IDE installieren.

Beim Schreiben von Code gibt es ein paar Grundregeln. Wenn du sie gleich am Anfang lernst, verschwindet die Hälfte der Compilerfehler, die du sonst in den ersten Tagen sehen würdest:

RegelRichtigWenn du sie brichst
Jede Anweisung endet mit einem SemikolondigitalWrite(13, HIGH);expected ';' before '}' token
Groß- und Kleinschreibung zähltpinMode(13, OUTPUT);'pinmode' was not declared in this scope
Codeblöcke stehen in geschweiften Klammernvoid loop() { ... }Zu jeder { gehört eine }
Einzeiliger Kommentar// diese Zeile wird nicht ausgeführtKommentare werden nicht kompiliert, sie dienen der Erklärung
Mehrzeiliger Kommentar/* ... */Ohne Abschluss wird alles darunter zum Kommentar
Text in doppelten, ein Zeichen in einfachen Anführungszeichen"Hallo" und 'A'Vertauschte Anführungszeichen ergeben falsche Werte oder Fehler

Die Schaltung für alle Beispiele

Alle Beispiele laufen auf einer Schaltung. Schließe sechs LEDs an die Pins D8–D13 an, jede über einen 220-Ω-Vorwiderstand; das kurze Bein (Kathode) jeder LED geht an GND. Den passenden Widerstand für deine LED kannst du mit dem LED-Vorwiderstandsrechner prüfen. Verbinde ein Bein des Tasters mit D2 und das diagonal gegenüberliegende Bein mit GND. Da der Code INPUT_PULLUP verwendet, brauchst du keinen externen Widerstand: Der Pin liest HIGH, wenn der Taster losgelassen ist, und LOW, wenn er gedrückt ist. Mehr dazu findest du in Taster am Arduino anschließen und Was ist eine LED?.

BauteilArduino UnoESP32Raspberry Pi Pico
6 LEDs (je mit 220 Ω, Kathode an GND)D8, D9, D10, D11, D12, D13GPIO 18, 19, 21, 22, 23, 25GP14, GP13, GP12, GP11, GP10, GP9
Taster (anderes Bein an GND)D2GPIO 4GP2
LED auf dem BoardD13 (die mit L beschriftete LED)GPIO 2 (bei den meisten DevKits)GP25 (beim Pico W "LED")
Serielle Geschwindigkeit9600 Baud115200 BaudThonny-Shell
Schließe eine LED nie ohne Widerstand an: Sowohl die LED als auch der Arduino-Pin können Schaden nehmen. Wenn du beim Einstecken des Tasters ins Steckbrett zwei Beine auf derselben Seite benutzt, sind diese innen eventuell schon verbunden und der Taster verhält sich, als wäre er nie gedrückt; die diagonalen Beine sind deshalb die sicherste Wahl. Die Pinnummern deines Boards findest du im Werkzeug Pinout.

setup() und loop(): das Grundgerüst jedes Sketches

Jeder Arduino-Sketch hat zwei Pflichtfunktionen. setup() läuft nur ein einziges Mal, wenn das Board startet oder der Reset-Knopf gedrückt wird; Vorbereitungen wie Pin-Einstellungen und Serial.begin() gehören hierher. loop() wiederholt sich danach endlos. Im Hintergrund hat der Arduino-Core eine versteckte main()-Funktion: Sie bereitet zuerst die Hardware vor, ruft dann setup() einmal auf und anschließend loop() in einer Endlosschleife immer wieder. Der Bereich ganz oben in der Datei, außerhalb dieser beiden Funktionen, ist der globale Bereich; hier definierst du Konstanten und Variablen, die von überall erreichbar sein sollen.

Arduino (C++)
1// 1) Global alan: sabitler ve değişkenler / Global area: constants and variables
2const int LED_PIN = 13;        // dahili LED / built-in LED
3unsigned long passCount = 0;   // loop() kaç kez döndü / how many times loop() has run
4
5// 2) setup(): açılışta bir kez çalışır / runs once at power-up or reset
6void setup() {
7  pinMode(LED_PIN, OUTPUT);
8  Serial.begin(9600);
9  Serial.println("setup() bitti / setup() done");
10}
11
12// 3) loop(): sonsuza kadar tekrar eder / repeats forever
13void loop() {
14  passCount++;                       // her turda 1 artır / add 1 on every pass
15  Serial.print("Tur / Pass: ");
16  Serial.println(passCount);
17
18  digitalWrite(LED_PIN, HIGH);       // LED'i yak / LED on
19  delay(500);                        // 500 ms bekle / wait 500 ms
20  digitalWrite(LED_PIN, LOW);        // LED'i söndür / LED off
21  delay(500);
22}

Lade den Code hoch und öffne den seriellen Monitor mit 9600 Baud: Du siehst einmal "setup() done" und danach jede Sekunde eine steigende Durchlaufnummer, während die eingebaute LED im selben Takt blinkt. Die beiden delay(500) in loop() verlängern jeden Durchlauf auf etwa eine Sekunde; eine loop() ganz ohne Wartezeit und serielle Ausgabe kann auf dem Uno hunderttausende Male pro Sekunde laufen. Wie du den seriellen Monitor optimal nutzt, erfährst du in der Anleitung Arduino Serial Monitor.

Variablen und Datentypen: int, long, float, bool, byte

Eine Variable ist eine benannte Schachtel im Speicher, die einen Wert aufbewahrt. Beim Definieren schreibst du zuerst den Datentyp, dann den Namen und auf Wunsch einen Startwert, zum Beispiel int counter = 0;. Der Typ legt fest, wie viele Bytes die Schachtel belegt und welchen Zahlenbereich sie aufnehmen kann. Der Arduino Uno hat nur 2 KB RAM, deshalb lohnt sich die Wahl des richtigen Typs. Variablennamen beginnen mit einem Buchstaben oder Unterstrich und dürfen weder Leerzeichen noch Sonderzeichen wie ä, ö, ü oder ß enthalten.

TypGröße beim UnoWertebereichTypische Verwendung
bool1 Bytetrue oder falseIst die LED an, wurde der Taster gedrückt
byte1 Byte0 – 255Pinnummer, PWM-Helligkeit
char1 Byte-128 – 127Ein einzelnes Zeichen: 'A'
int2 Byte-32.768 – 32.767Zähler, Ergebnis von analogRead()
unsigned int2 Byte0 – 65.535Nur positive Zahlen
long4 Byte-2.147.483.648 – 2.147.483.647Große Ganzzahlen
unsigned long4 Byte0 – 4.294.967.295Zeitmessung mit millis()
float4 ByteEtwa ±3,4 × 10^38, 6–7 Stellen GenauigkeitTemperatur, Spannung, Mittelwerte
double4 Byte (beim Uno gleich wie float)Wie floatBeim ESP32 8 Byte

Ein paar praktische Regeln ersparen dir viel Ärger. analogRead() liefert eine Zahl von 0 bis 1023, ein int reicht also aus. millis() dagegen liefert einen unsigned long; speicherst du die Zeit in einer int-Variable, läuft der Wert nach 32,7 Sekunden über und dein Timing bricht zusammen. Auf dem Uno werden float-Berechnungen in Software ausgeführt, sie sind daher langsamer als Ganzzahl-Rechnungen, und nach 6–7 Stellen ist das Ergebnis nicht mehr zuverlässig; vergleiche zwei float-Werte deshalb nie mit ==. Wenn du einen Typ willst, dessen Größe auf jedem Board gleich bleibt, nimm Typen mit der Größe im Namen wie uint8_t, int16_t und uint32_t.

Überlauf (Overflow): Was passiert, wenn eine Variable ihre Grenze überschreitet?

Wenn du eine größere Zahl speichern willst, als der Typ fassen kann, meldet der Arduino keinen Fehler; die Zahl springt wie ein Kilometerzähler wieder an den Anfang. Beim Uno fasst ein int höchstens 32.767, addierst du 1, wird daraus -32.768. Ein byte springt von 255 auf 0. Eine noch tückischere Falle ist das Rechnen mit Konstanten: Ein Ausdruck wie 60 * 1000 wird zuerst als int berechnet und läuft über, selbst wenn das Ergebnis in einer long-Variable landet. Der folgende Sketch gibt all diese Fälle im seriellen Monitor aus, und seine loop() zeigt einen byte-Überlauf an einer LED:

Arduino (C++)
1const int LED_PIN = 9;        // PWM destekli pin (~9) / PWM-capable pin (~9)
2byte brightness = 0;          // byte: 0-255
3
4void setup() {
5  pinMode(LED_PIN, OUTPUT);
6  Serial.begin(9600);
7
8  int a = 32767;              // Uno'da int'in en büyük değeri / largest int on an Uno
9  a = a + 1;                  // taşma: -32768 olur / overflow: becomes -32768
10  Serial.println(a);
11
12  long wrong = 60 * 1000;     // int ile hesaplanır, taşar: -5536 / computed as int, overflows: -5536
13  long right = 60 * 1000L;    // L eki hesabı long yapar: 60000 / the L suffix makes it long math: 60000
14  Serial.println(wrong);
15  Serial.println(right);
16
17  float half = 5 / 2;         // tam sayı bölmesi: 2.00 / integer division: 2.00
18  float half2 = 5 / 2.0;      // ondalıklı bölme: 2.50 / floating-point division: 2.50
19  Serial.println(half);
20  Serial.println(half2);
21}
22
23void loop() {
24  analogWrite(LED_PIN, brightness);   // parlaklığı uygula / apply the brightness
25  brightness++;                       // 255'ten sonra 0'a döner / wraps to 0 after 255
26  delay(10);
27}
CodezeileAusgabe beim UnoAusgabe bei ESP32 und PicoWarum?
a = 32767 + 1-3276832768int ist beim Uno 2 Byte groß, bei den anderen 4 Byte
60 * 1000-553660000Konstanten werden zuerst als int berechnet
60 * 1000L6000060000Das Suffix L macht die Rechnung zu long
5 / 22.002.00Die Division zweier Ganzzahlen ergibt eine Ganzzahl
5 / 2.02.502.50Hat eine Zahl Nachkommastellen, hat auch das Ergebnis welche

Beobachte die LED an D9: Ihre Helligkeit steigt langsam von 0 bis 255, dann macht die Zeile brightness++ aus dem Wert 0 statt 256, und die LED geht plötzlich aus. So siehst du einen Überlauf am einfachsten mit eigenen Augen. D9 ist einer der mit ~ markierten PWM-Pins des Uno, deshalb funktioniert analogWrite() dort; PWM wird ausführlich in Was ist PWM? erklärt. Auch das Zurückspringen von millis() nach etwa 49,7 Tagen ist ein Überlauf, der in richtig geschriebenem Code keine Probleme macht; wie das geht, zeigt die Anleitung millis() statt delay().

Öffne in der Arduino IDE Datei > Einstellungen und stelle die Compiler-Warnungen (Compiler warnings) auf "Mehr" oder "Alle". Schreibst du dann einen überlaufenden Ausdruck wie 60 * 1000, zeigt der Compiler die Warnung integer overflow in expression, und du findest den Fehler, bevor der Code auf dem Board landet.

const und #define: Werte, die sich nie ändern

Für Zahlen, die sich während des Programms nicht ändern, etwa Pinnummern oder Schwellwerte, gibt es zwei Möglichkeiten, ihnen einen Namen zu geben. Eine mit const definierte Konstante hat einen Typ, hält sich an die Regeln des Gültigkeitsbereichs, und wenn du sie versehentlich ändern willst, stoppt dich der Compiler mit assignment of read-only variable 'LED_PIN'. #define ist dagegen eine Präprozessor-Anweisung: Noch vor dem Kompilieren ersetzt sie jedes BUTTON_PIN im Code durch 2. Sie hat keinen Typ, und in der Zeile stehen weder Semikolon noch Gleichheitszeichen. Bei einfachen Zahlen belegt keine der beiden Varianten RAM, weil der Compiler den Wert direkt in den Code einsetzt. Heute wird const bevorzugt, und Konstantennamen in GROSSBUCHSTABEN zu schreiben ist eine verbreitete Gewohnheit. Das folgende Beispiel nutzt beides: Die LED leuchtet, solange der Taster gedrückt ist.

Arduino (C++)
1#define BUTTON_PIN 2          // önişlemci: derlemeden önce metin değişimi / preprocessor: text swap before compiling
2const int LED_PIN = 13;       // tipi olan, salt okunur sabit / typed, read-only constant
3
4void setup() {
5  pinMode(LED_PIN, OUTPUT);
6  pinMode(BUTTON_PIN, INPUT_PULLUP);   // dahili pull-up: basılınca LOW / internal pull-up: LOW when pressed
7}
8
9void loop() {
10  if (digitalRead(BUTTON_PIN) == LOW) {   // buton basılı mı? / is the button pressed?
11    digitalWrite(LED_PIN, HIGH);          // evet: LED yanar / yes: LED on
12  } else {
13    digitalWrite(LED_PIN, LOW);           // hayır: LED söner / no: LED off
14  }
15}
Schreibst du #define LED_PIN 13;, wird das Semikolon Teil des Werts, und aus pinMode(LED_PIN, OUTPUT) wird pinMode(13;, OUTPUT). Der Compiler meldet expected ')' before ';' token; der Hinweis in expansion of macro 'LED_PIN' darunter zeigt, dass das Problem dort auftritt, wo die Konstante verwendet wird, korrigieren musst du aber die #define-Zeile. Auch #define LED_PIN = 13 führt zu einem Fehler, nämlich expected primary-expression before '=' token.

Operatoren: Arithmetik, Vergleich und Logik

Mit Operatoren rechnest du mit Variablen, vergleichst sie und verknüpfst Bedingungen. Fast alle Operatoren, die du in alltäglichen Projekten brauchst, stehen in dieser Tabelle:

GruppeOperatorBedeutungBeispiel
Arithmetik+ - * /Die vier Grundrechenartenx = a * 2;
Rest%Rest einer Division (nur bei Ganzzahlen)7 % 3 ergibt 1
Zuweisung= += -= *= /=Zuweisen, dazuzählen, abziehen…total += 5;
Erhöhen, verringern++ --Um 1 erhöhen oder verringerni++;
Vergleich== != < > <= >=Ergebnis ist true oder falseif (x >= 10)
Logik&& || !UND, ODER, NICHTif (a && !b)
Bedingung? :Kurzes if-elsex > 0 ? HIGH : LOW
Bitweise& | ^ ~ << >>Arbeitet mit den Bits einer Zahl1 << 3 ergibt 8

Am häufigsten verwechselt werden die Paare = und == sowie & und &&. Ein einfaches Gleichheitszeichen weist einen Wert zu, ein doppeltes vergleicht. Ein einfaches & arbeitet mit den Bits von Zahlen, && fragt dagegen, ob beide Bedingungen wahr sind. Die Wahrheitstabellen von UND, ODER und NICHT kannst du im Werkzeug Logikgatter ausprobieren; die bitweisen Operatoren werden ausführlich in der Anleitung Zahlensysteme und Bitoperationen erklärt. Das folgende Beispiel zählt, wie oft der Taster gedrückt wurde, und schaltet die LED nach einer ungeraden Anzahl von Tastendrücken ein:

Arduino (C++)
1const int LED_PIN = 13;
2const int BUTTON_PIN = 2;
3
4int presses = 0;               // toplam basış sayısı / total number of presses
5bool lastPressed = false;      // önceki turdaki durum / state on the previous pass
6
7void setup() {
8  pinMode(LED_PIN, OUTPUT);
9  pinMode(BUTTON_PIN, INPUT_PULLUP);
10  Serial.begin(9600);
11}
12
13void loop() {
14  bool pressed = (digitalRead(BUTTON_PIN) == LOW);   // karşılaştırma: true ya da false / comparison: true or false
15
16  if (pressed && !lastPressed) {     // şimdi basılı VE önceden değildi: yeni basış / pressed now AND not before: new press
17    presses++;                       // 1 artır / increment by 1
18    Serial.print("Basış / Presses: ");
19    Serial.println(presses);
20    delay(50);                       // basit debounce / simple debounce
21  }
22  lastPressed = pressed;
23
24  // Kalan (%) ile tek mi çift mi? / odd or even using the remainder (%)
25  digitalWrite(LED_PIN, (presses % 2 == 1) ? HIGH : LOW);
26}

Der Trick ist die Bedingung pressed && !lastPressed: Sie bedeutet "jetzt gedrückt UND im vorherigen Durchlauf nicht gedrückt". So steigt die Zahl nicht weiter, solange du den Taster festhältst, und jeder Tastendruck wird nur einmal gezählt. presses % 2 liefert den Rest der Division durch 2: 1 bei ungeraden, 0 bei geraden Zahlen. Der Operator ? : in der letzten Zeile wählt anhand dieses Ergebnisses HIGH oder LOW.

if, else if und else: Entscheidungen treffen

if führt den Code in den geschweiften Klammern aus, wenn die Bedingung in den runden Klammern wahr ist. Ist sie falsch, läuft der else-Block, sofern es einen gibt. Brauchst du mehr Möglichkeiten, fügst du dazwischen else if ein. Die Bedingungen werden von oben nach unten geprüft, und sobald der Block der ersten wahren Bedingung gelaufen ist, werden die übrigen übersprungen. In C++ gilt jeder Wert ungleich null als wahr, if (counter) bedeutet also "wenn der Zähler nicht null ist". Ein einfaches if-else-Beispiel hast du schon im const-Abschnitt gesehen. Jetzt schreiben wir eines, das einen kurzen von einem langen Tastendruck unterscheidet:

Arduino (C++)
1const int LED_PIN = 13;
2const int BUTTON_PIN = 2;
3
4void setup() {
5  pinMode(LED_PIN, OUTPUT);
6  pinMode(BUTTON_PIN, INPUT_PULLUP);
7  Serial.begin(9600);
8}
9
10void loop() {
11  if (digitalRead(BUTTON_PIN) == LOW) {             // basıldı / pressed
12    unsigned long start = millis();
13    while (digitalRead(BUTTON_PIN) == LOW) {         // bırakılana kadar bekle / wait until released
14    }
15    unsigned long held = millis() - start;          // basılı kalma süresi (ms) / hold time (ms)
16
17    if (held < 50) {
18      return;                                       // 50 ms'den kısa: parazit, yok say / under 50 ms: bounce, ignore
19    } else if (held < 1000) {
20      digitalWrite(LED_PIN, HIGH);                  // kısa basış: LED yak / short press: LED on
21      Serial.println("Kısa basış / Short press");
22    } else {
23      digitalWrite(LED_PIN, LOW);                   // uzun basış: LED söndür / long press: LED off
24      Serial.println("Uzun basış / Long press");
25    }
26  }
27}

Sobald der Taster gedrückt wird, merkt sich der Code mit millis() die Zeit, wartet in einer while-Schleife, bis der Taster losgelassen wird, und berechnet die Zeit dazwischen. Drücke unter 50 ms gelten als Störung durch das mechanische Prellen des Tasters, und return beendet diesen Durchlauf von loop() vorzeitig. Ein Druck unter 1 Sekunde schaltet die LED ein, ein längerer schaltet sie aus. Die Reihenfolge der Bedingungen ist wichtig: Stünde die Prüfung held < 1000 ganz oben, würde auch ein Störimpuls von 30 ms als "kurzer Druck" zählen.

if (mode = 2) ist der klassische Fehler: Diese Zeile vergleicht nichts, sondern weist mode den Wert 2 zu, und weil das Ergebnis nicht null ist, ist die Bedingung immer wahr. Ein weiterer heimtückischer Fehler ist ein Semikolon direkt nach der Klammer, etwa if (x == 5);: Das if endet mit einer leeren Anweisung, und der Block darunter läuft jedes Mal, egal wie die Bedingung ausfällt.

switch-case: zwischen vielen Fällen wählen

Wenn du je nach Wert einer Variable viele verschiedene Dinge tun willst, ist switch-case übersichtlicher als eine lange else-if-Kette. switch vergleicht den Wert in der Klammer mit jedem case-Label und beginnt beim passenden mit der Ausführung. Jeden case solltest du mit break beenden, sonst läuft das Programm einfach in den Code des nächsten case weiter. Passt kein case, läuft der default-Block. switch funktioniert nur mit Ganzzahltypen wie int, byte, char und enum; für String, float oder Bereiche wie "zwischen 10 und 20" brauchst du if. Im folgenden Beispiel schaltet jeder Tastendruck die Lampe in den nächsten Modus: aus, an, langsam blinken, schnell blinken.

Arduino (C++)
1const int LED_PIN = 13;
2const int BUTTON_PIN = 2;
3
4byte mode = 0;                 // 0 kapalı, 1 açık, 2 yavaş, 3 hızlı / 0 off, 1 on, 2 slow, 3 fast
5bool lastPressed = false;
6
7void setup() {
8  pinMode(LED_PIN, OUTPUT);
9  pinMode(BUTTON_PIN, INPUT_PULLUP);
10}
11
12void loop() {
13  bool pressed = (digitalRead(BUTTON_PIN) == LOW);
14  if (pressed && !lastPressed) {
15    mode = (mode + 1) % 4;      // 0 → 1 → 2 → 3 → 0
16    delay(50);                  // basit debounce / simple debounce
17  }
18  lastPressed = pressed;
19
20  switch (mode) {
21    case 0:                                        // kapalı / off
22      digitalWrite(LED_PIN, LOW);
23      break;
24    case 1:                                        // sürekli açık / always on
25      digitalWrite(LED_PIN, HIGH);
26      break;
27    case 2:                                        // 500 ms'de bir değiş / toggle every 500 ms
28      digitalWrite(LED_PIN, (millis() / 500) % 2 ? HIGH : LOW);
29      break;
30    case 3:                                        // 100 ms'de bir değiş / toggle every 100 ms
31      digitalWrite(LED_PIN, (millis() / 100) % 2 ? HIGH : LOW);
32      break;
33    default:                                       // beklenmeyen değer: başa dön / unexpected value: reset
34      mode = 0;
35      break;
36  }
37}

Die Zeile mode = (mode + 1) % 4 zählt den Modus 0, 1, 2, 3 hoch und setzt ihn dank des Operators % bei 4 wieder auf 0. Beachte, dass wir zum Blinken kein delay() benutzen: Der Ausdruck (millis() / 500) % 2 wechselt alle 500 ms zwischen 0 und 1, so reagiert der Taster jederzeit, während die LED blinkt. Die erwachsene Version dieses Modus-Ansatzes heißt Zustandsautomat; wie man ihn bei Ampeln und Menüs einsetzt, zeigt die Anleitung Zustandsautomat mit Arduino.

Wenn du in einem case eine Variable definierst, setze den Code dieses case in geschweifte Klammern: case 1: { byte step = 3; ... break; }. Ohne Klammern kompiliert der Uno das nur mit einer Warnung, der ESP32 bricht dagegen mit dem Fehler jump to case label ab und der Code wird gar nicht kompiliert.

for-, while- und do-while-Schleifen

Schleifen führen einen Codeblock immer wieder aus. Die Klammer einer for-Schleife hat drei Teile: den Start (int i = 0), die Bedingung zum Weitermachen (i < 6) und den Schritt nach jedem Durchlauf (i++). for ist ideal, wenn du weißt, wie oft wiederholt werden soll. while läuft, solange die Bedingung wahr ist, und prüft sie vor jedem Durchlauf; das passt zu Wartezeiten, deren Länge du vorher nicht kennst. do-while prüft die Bedingung erst am Ende und läuft deshalb mindestens einmal. Innerhalb einer Schleife verlässt break die Schleife sofort, und continue überspringt den Rest des aktuellen Durchlaufs und macht mit dem nächsten weiter. Da loop() selbst schon eine Endlosschleife ist, brauchst du darin meist kein while (true).

SchleifeWann wird die Bedingung geprüft?Wann verwenden?Beispiel
forVor jedem DurchlaufWenn die Anzahl der Wiederholungen feststehtfor (int i = 0; i < 6; i++)
whileVor jedem DurchlaufBeim Warten auf ein Ereigniswhile (digitalRead(2) == HIGH)
do-whileNach jedem DurchlaufWenn sie mindestens einmal laufen mussdo { ... } while (x < 10);

Das folgende Beispiel erzeugt mit sechs LEDs einen Knight-Rider-Effekt. Die for-Schleife in setup() macht alle sechs Pins in einer Zeile zu Ausgängen, und die while-Schleife in loop() wartet, bis der Taster gedrückt wird. Solange du den Taster hältst, läuft das Licht von D8 nach D13 und zurück:

Arduino (C++)
1const int FIRST_LED = 8;       // ilk LED pini / first LED pin
2const int LAST_LED = 13;       // son LED pini / last LED pin
3const int BUTTON_PIN = 2;
4
5void setup() {
6  for (int pin = FIRST_LED; pin <= LAST_LED; pin++) {
7    pinMode(pin, OUTPUT);      // 6 pini tek döngüyle çıkış yap / make 6 pins outputs with one loop
8  }
9  pinMode(BUTTON_PIN, INPUT_PULLUP);
10}
11
12void loop() {
13  while (digitalRead(BUTTON_PIN) == HIGH) {
14    // butona basılana kadar burada bekle / wait here until the button is pressed
15  }
16
17  for (int pin = FIRST_LED; pin <= LAST_LED; pin++) {      // ileri: 8 → 13 / forward: 8 → 13
18    digitalWrite(pin, HIGH);
19    delay(80);
20    digitalWrite(pin, LOW);
21  }
22  for (int pin = LAST_LED - 1; pin > FIRST_LED; pin--) {   // geri: 12 → 9 / back: 12 → 9
23    digitalWrite(pin, HIGH);
24    delay(80);
25    digitalWrite(pin, LOW);
26  }
27}

Dass die Rückwärtsschleife bei LAST_LED - 1 beginnt und nur läuft, solange der Pin größer als FIRST_LED ist, ist Absicht: Die LEDs an den Enden leuchten nicht zweimal hintereinander auf, und die Bewegung wirkt flüssig. Geschwindigkeitsregelung, einen sich füllenden Effekt und weitere Muster findest du in der Anleitung Arduino Lauflicht und Knight Rider.

Die Schleife for (byte i = 0; i < 256; i++) endet nie: Ein byte fasst höchstens 255, also springt i auf 0 zurück, bevor es 256 erreicht, und die Bedingung bleibt für immer wahr. Genauso legt eine while-Schleife, die auf eine Bedingung wartet, die nie eintritt, etwa auf einen Sensor mit gelöstem Kabel, das Programm dauerhaft lahm.

Arrays: viele Werte unter einem Namen

Ein Array speichert mehrere Werte desselben Typs geordnet unter einem einzigen Namen. Die Zeile const byte LEDS[] = {8, 9, 10, 11, 12, 13}; erzeugt ein Array mit sechs Elementen. Auf die Elemente greifst du mit eckigen Klammern zu, und gezählt wird ab 0: LEDS[0] ist 8, LEDS[5] ist 13. Die Länge eines Arrays lässt sich nach der Definition nicht mehr ändern. Lässt du die Anzahl der Elemente mit sizeof(LEDS) / sizeof(LEDS[0]) berechnen, statt sie von Hand einzutragen, passen sich deine Schleifen automatisch an, wenn du einen neuen Pin hinzufügst. Ein Index außerhalb des Arrays, etwa LEDS[6], führt zu keinem Fehler; er liest oder überschreibt eine andere Variable im Speicher. Achte deshalb darauf, dass der Index zwischen 0 und der Anzahl der Elemente minus eins bleibt. Das folgende Beispiel macht aus den sechs LEDs einen elektronischen Würfel:

Arduino (C++)
1const byte LEDS[] = {8, 9, 10, 11, 12, 13};               // LED pinleri / LED pins
2const byte LED_COUNT = sizeof(LEDS) / sizeof(LEDS[0]);    // eleman sayısı: 6 / number of elements: 6
3const byte BUTTON_PIN = 2;
4
5void setup() {
6  for (byte i = 0; i < LED_COUNT; i++) {     // indeks 0'dan başlar / index starts at 0
7    pinMode(LEDS[i], OUTPUT);
8  }
9  pinMode(BUTTON_PIN, INPUT_PULLUP);
10  randomSeed(analogRead(A0));                // boştaki A0'ın gürültüsüyle tohumla / seed from noise on the unconnected A0
11}
12
13void loop() {
14  if (digitalRead(BUTTON_PIN) == LOW) {
15    byte dice = random(1, 7);                // 1 ile 6 arası / between 1 and 6
16    for (byte i = 0; i < LED_COUNT; i++) {
17      digitalWrite(LEDS[i], (i < dice) ? HIGH : LOW);   // ilk 'dice' kadar LED yanar / the first 'dice' LEDs light up
18    }
19    delay(300);                              // basılı tutarsan zar dönmeye devam eder / keeps rolling while held
20  }
21}

random(1, 7) liefert eine Zahl von 1 bis 6, weil die obere Grenze nicht zum Ergebnis gehört. Genauso viele LEDs leuchten: Zeigt der Würfel 4, gehen die vier LEDs von LEDS[0] bis LEDS[3] an. Die Zeile randomSeed(analogRead(A0)) nutzt das elektrische Rauschen am unbeschalteten Pin A0 als Startwert; ohne sie würde das Board nach jedem Einschalten dieselbe Zahlenfolge erzeugen. Noch ein Vorteil von Arrays: Verlegst du die LEDs auf andere Pins, musst du nur die erste Zeile ändern.

Funktionen schreiben: Code in Teile zerlegen

Wenn du dieselbe Aufgabe an mehreren Stellen im Programm erledigst, mach daraus eine Funktion. Eine Funktion besteht aus einem Rückgabetyp, einem Namen, Parametern in runden Klammern und einem Rumpf in geschweiften Klammern. Funktionen ohne Rückgabewert haben den Typ void; Funktionen mit Rückgabewert geben ihr Ergebnis mit return zurück. Parameter werden als Kopie übergeben, eine Änderung des Parameters in der Funktion ändert also nicht die Variable an der Aufrufstelle. Die Arduino IDE erzeugt die Deklarationen für Funktionen in .ino-Dateien selbst, du kannst eine Funktion also auch unterhalb von loop() schreiben. In .cpp-Dateien oder in PlatformIO musst du eine Funktion dagegen deklarieren, bevor du sie benutzt. Gib Funktionen Namen, die sagen, was sie tun, etwa blinkLed oder isPressed.

Arduino (C++)
1const byte LED_PIN = 13;
2const byte BUTTON_PIN = 2;
3
4// Değer döndürmeyen (void) fonksiyon / function that returns nothing (void)
5void blinkLed(byte pin, byte times, int ms) {
6  for (byte i = 0; i < times; i++) {
7    digitalWrite(pin, HIGH);
8    delay(ms);
9    digitalWrite(pin, LOW);
10    delay(ms);
11  }
12}
13
14// bool döndüren fonksiyon / function that returns a bool
15bool isPressed(byte pin) {
16  return digitalRead(pin) == LOW;      // INPUT_PULLUP: basılı = LOW / pressed = LOW
17}
18
19void setup() {
20  pinMode(LED_PIN, OUTPUT);
21  pinMode(BUTTON_PIN, INPUT_PULLUP);
22  blinkLed(LED_PIN, 3, 100);           // açılışta 3 hızlı yanıp sönme / 3 quick blinks at start-up
23}
24
25void loop() {
26  if (isPressed(BUTTON_PIN)) {
27    blinkLed(LED_PIN, 2, 250);         // basınca 2 yavaş yanıp sönme / 2 slow blinks per press
28  }
29}

blinkLed() bekommt den Pin, die Anzahl der Blinker und die Geschwindigkeit als Parameter, deshalb kannst du dieselbe Funktion für eine andere LED und ein anderes Tempo wiederverwenden. isPressed() gibt einen bool zurück und hält die Logik "gedrückt = LOW" von INPUT_PULLUP an einer einzigen Stelle fest; schließt du den Taster später anders an, änderst du nur diese Zeile. Das delay() in der Funktion hält das Programm aber trotzdem an. Für Funktionen, die mehrere Dinge gleichzeitig erledigen, brauchst du ein Timing auf Basis von millis().

Globale, lokale und static-Variablen

Wo eine Variable sichtbar ist, nennt man ihren Gültigkeitsbereich (Scope). Globale Variablen werden außerhalb der Funktionen definiert, leben während des ganzen Programms und lassen sich von überall lesen und ändern. Lokale Variablen werden in einer Funktion oder einem Block aus geschweiften Klammern definiert, bei jedem Durchlauf dieses Blocks neu angelegt und verschwinden an seinem Ende. Genau daher kommt die häufigste Einsteigerfrage: "Warum bleibt mein Zähler immer bei 1?" Schreibst du static vor eine lokale Variable, erhält sie ihren Startwert nur beim ersten Mal und behält ihren Wert zwischen den Durchläufen, ist aber weiterhin nur innerhalb dieser Funktion sichtbar.

Arduino (C++)
1const byte LED_PIN = 13;
2const byte BUTTON_PIN = 2;
3
4int globalCount = 0;            // global: her yerden görünür, değerini korur / global: visible everywhere, keeps its value
5
6void setup() {
7  pinMode(LED_PIN, OUTPUT);
8  pinMode(BUTTON_PIN, INPUT_PULLUP);
9  Serial.begin(9600);
10}
11
12void loop() {
13  int localCount = 0;           // yerel: her turda yeniden 0 olur / local: back to 0 on every pass
14  static int staticCount = 0;   // static yerel: değerini korur, yalnız burada görünür / static local: keeps its value, visible only here
15
16  if (digitalRead(BUTTON_PIN) == LOW) {
17    globalCount++;
18    localCount++;
19    staticCount++;
20    Serial.print(globalCount);
21    Serial.print(' ');
22    Serial.print(localCount);
23    Serial.print(' ');
24    Serial.println(staticCount);                   // 3. basışta: 3 1 3 / on the 3rd press: 3 1 3
25    digitalWrite(LED_PIN, (staticCount % 2) ? HIGH : LOW);
26    delay(300);
27  }
28}

Drückst du den Taster dreimal, zeigt der serielle Monitor die Zeilen 1 1 1, 2 1 2 und 3 1 3: Die globalen und static-Zähler steigen weiter, der lokale Zähler bleibt dagegen immer bei 1, weil er in jedem Durchlauf von loop() wieder bei 0 beginnt. Definierst du eine lokale Variable mit demselben Namen wie eine globale, verdeckt die lokale die globale, und innerhalb dieser Funktion erreichst du die globale Variable gar nicht. Globale Variablen, die von einer Interrupt-Funktion (ISR) geändert werden, müssen zusätzlich als volatile deklariert werden; Details findest du in der Anleitung Arduino Interrupts.

Halte Variablen so lokal wie möglich: static für Zähler, die nur eine Funktion braucht, global für Werte, die sich mehrere Funktionen teilen. Die Zeile Global variables use … bytes of dynamic memory, die die IDE nach dem Kompilieren ausgibt, zeigt, wie viel RAM deine globalen Variablen belegen. Beim Uno kann ab über 75 Prozent instabiles Verhalten auftreten; Lösungen findest du in der Anleitung Arduino Speicher voll.

Arduino programmieren auf dem ESP32: gleiche Sprache, andere Größen

Wenn du den ESP32 mit der Arduino IDE programmierst, nutzt du dieselbe Sprache C++ und dieselben Befehle, es gibt aber ein paar Unterschiede. Weil der ESP32 ein 32-Bit-Prozessor ist, ist int 4 Byte groß und fasst Werte von -2.147.483.648 bis 2.147.483.647; die Rechnung 32767 + 1 aus dem Überlauf-Beispiel ergibt also 32768. double ist 8 Byte groß, analogRead() liefert Werte von 0 bis 4095, und die Pins arbeiten mit 3,3 V. Mit Serial.printf() kannst du formatiert ausgeben. random() nutzt standardmäßig den Hardware-Zufallszahlengenerator, deshalb brauchst du die Zeile randomSeed() nicht. Das folgende Programm vereint alles, was du in diesem Artikel gelernt hast: ein Array, eine Funktion, switch-case und einen Taster, der den Modus wechselt. Die allgemeinen Eigenschaften des Boards findest du in Was ist der ESP32?.

Arduino (C++)
1// ESP32: aynı dil, farklı pinler / ESP32: same language, different pins
2const byte LEDS[] = {18, 19, 21, 22, 23, 25};            // güvenli GPIO'lar / safe GPIOs
3const byte LED_COUNT = sizeof(LEDS) / sizeof(LEDS[0]);
4const byte BUTTON_PIN = 4;                                // diğer bacağı GND'ye / other leg to GND
5
6byte mode = 0;                  // 0 kapalı, 1 yürüyen ışık, 2 hepsi yanıp söner / 0 off, 1 chaser, 2 all blink
7bool lastPressed = false;
8
9void setAll(bool on) {
10  for (byte i = 0; i < LED_COUNT; i++) {
11    digitalWrite(LEDS[i], on ? HIGH : LOW);
12  }
13}
14
15void setup() {
16  Serial.begin(115200);
17  for (byte i = 0; i < LED_COUNT; i++) {
18    pinMode(LEDS[i], OUTPUT);
19  }
20  pinMode(BUTTON_PIN, INPUT_PULLUP);
21  Serial.printf("int = %d bayt / bytes\n", (int)sizeof(int));   // ESP32'de 4 / 4 on the ESP32
22
23  int a = 32767;
24  a = a + 1;
25  Serial.println(a);                                          // ESP32'de 32768, taşma yok / 32768 on the ESP32, no overflow
26}
27
28void loop() {
29  bool pressed = (digitalRead(BUTTON_PIN) == LOW);
30  if (pressed && !lastPressed) {
31    mode = (mode + 1) % 3;      // 0 → 1 → 2 → 0
32    delay(50);
33  }
34  lastPressed = pressed;
35
36  switch (mode) {
37    case 0:
38      setAll(false);
39      break;
40    case 1: {                                                 // case içinde değişken için süslü parantez / braces for a variable inside a case
41      byte step = (millis() / 120) % LED_COUNT;               // sıradaki LED / LED whose turn it is
42      for (byte i = 0; i < LED_COUNT; i++) {
43        digitalWrite(LEDS[i], (i == step) ? HIGH : LOW);
44      }
45      break;
46    }
47    case 2:
48      setAll((millis() / 300) % 2);                           // 300 ms'de bir hepsi / all of them every 300 ms
49      break;
50  }
51}

Um dieses Programm auf dem Uno laufen zu lassen, musst du nur das Array LEDS auf {8, 9, 10, 11, 12, 13} und BUTTON_PIN auf 2 ändern und die Zeile mit Serial.printf(), das es auf dem Uno nicht gibt, durch Serial.print() ersetzen. Genau das ist der Vorteil, wenn du Pinnummern ganz oben als Konstanten und Arrays definierst. Beachte auch, dass der Block von case 1 in geschweiften Klammern steht; weil darin die Variable step definiert wird, sind diese Klammern beim ESP32 Pflicht.

Raspberry Pi Pico: dieselbe Logik in MicroPython

Den Raspberry Pi Pico kannst du in C++ programmieren, indem du der Arduino IDE das RP2040-Boardpaket hinzufügst; dann funktioniert der Code aus diesem Artikel, sobald du die Pinnummern anpasst, und int ist ebenfalls 4 Byte groß. Am häufigsten wird der Pico aber mit MicroPython genutzt. In Python schreibst du keine Datentypen, Blöcke werden durch Einrückung statt durch geschweifte Klammern festgelegt, am Zeilenende steht kein Semikolon, und Ganzzahlen laufen nicht über, sondern wachsen so weit wie nötig. Der folgende Code ist die MicroPython-Version des elektronischen Würfels. Zur Einrichtung siehe Was ist der Raspberry Pi Pico?, zu den Details der Sprache MicroPython-Grundlagen.

MicroPython
1from machine import Pin
2import time, random
3
4leds = [Pin(n, Pin.OUT) for n in (14, 13, 12, 11, 10, 9)]   # liste = dizi / list = array
5button = Pin(2, Pin.IN, Pin.PULL_UP)                        # basılınca 0 / reads 0 when pressed
6
7def show(count):                                            # fonksiyon / function
8    for i, led in enumerate(leds):                          # for döngüsü / for loop
9        led.value(1 if i < count else 0)
10
11show(0)                                                     # setup() karşılığı: bir kez çalışır / like setup(): runs once
12while True:                                                 # loop() karşılığı / like loop()
13    if button.value() == 0:                                 # buton basılı mı? / is the button pressed?
14        show(random.randint(1, 6))                          # 1-6 arası zar at / roll a number from 1 to 6
15        time.sleep_ms(300)
KonzeptArduino (C++)MicroPython
Teil, der einmal läuftsetup()Der Code vor der Zeile while True:
Teil, der sich endlos wiederholtloop()while True:
Variableint x = 5;x = 5
Konstanteconst int PIN = 2;PIN = const(2) (from micropython import const)
Bedingungif / else if / elseif / elif / else
Mehrfachauswahlswitch-caseif / elif-Kette
Zählschleifefor (int i = 0; i < 6; i++)for i in range(6):
Arraybyte a[] = {1, 2, 3};a = [1, 2, 3]
Funktionvoid blink(int pin) { ... }def blink(pin):
Logik&& || !and or not
Kommentar// Kommentar# Kommentar

Projektideen für diese Grundlagen

  • Ampel: Baue mit Konstanten, delay() und if eine Kreuzung mit Fußgängertaster; die Schritt-für-Schritt-Anleitung findest du unter Arduino Ampel.
  • Knight Rider und Lauflicht: Erzeuge mit einer for-Schleife und einem Array Dutzende verschiedene Lichtmuster.
  • Elektronischer Würfel: Bring den Würfel mit Array, random() und einer Funktion von sechs LEDs auf eine 7-Segment-Anzeige; dazu passt die Anleitung 7-Segment-Anzeige.
  • Reaktionstest: Lass eine LED zu einem zufälligen Zeitpunkt aufleuchten und miss mit unsigned long und millis(), wie schnell du den Taster drückst.
  • Lampe mit Modi: Aus, Dauerlicht, Atmen und Blitz über einen einzigen Taster mit switch-case; für eine farbige Version wirf einen Blick auf RGB-LED verwenden.
  • Codeschloss: Sammle die gedrückten Tasten in einem Array und vergleiche sie mit dem gespeicherten Code; Details stehen in der Anleitung Keypad am Arduino.

Häufige Fehler und ihre Lösungen

FehlerSymptomLösung
= in einem VergleichDer if-Block läuft immerZum Vergleichen == verwenden
; oder = in der #define-Zeileexpected ')' before ';' tokenAls #define LED_PIN 13 schreiben
Befehl falsch geschrieben'pinmode' was not declared in this scopeAuf Groß- und Kleinschreibung achten, z. B. pinMode
Umlaut im Variablennamenstray '\303' in programIn Namen nur englische Buchstaben, Ziffern und _ verwenden
60 * 1000 als int berechnenDas Ergebnis ist -553660 * 1000L oder 60000UL schreiben
millis() in einem int speichernDas Timing bricht nach 32 Sekunden zusammenunsigned long verwenden
Ganzzahldivision5 / 2 ergibt 25 / 2.0 schreiben oder in float umwandeln
break am Ende eines case vergessenDer nächste case läuft mitJeden case mit break beenden
Außerhalb eines Arrays schreibenZufällige Werte, AbstürzeIndex zwischen 0 und Anzahl der Elemente - 1 halten
Zähler lokal definierenDer Zähler bleibt immer bei 1Global oder static machen
Bekommst du einen Compilerfehler, lies nur die erste Fehlerzeile und behebe diesen Fehler; die meisten Meldungen in den folgenden Zeilen sind Folgefehler. Was die Meldungen bedeuten, erfährst du in der Anleitung Arduino Kompilierfehler. Hast du kein Board zur Hand, kannst du den Code auch in einer Tinkercad-Simulation ausprobieren.

Wenn du diese Bausteine beherrschst, ist der nächste Schritt, die meistgenutzten Befehle kennenzulernen: Die Arduino-Befehlsliste erklärt alles von pinMode() bis attachInterrupt() mit Beispielen. In der BlueGrays-App findest du außerdem Projekte wie LED-Blinken, LED-Steuerung per Taster, Knight Rider, Ampel und Würfel Schritt für Schritt mit Schaltplänen und fertigem Code, sodass du jede hier gelernte Struktur an einer echten Schaltung ausprobieren kannst.

Häufige Fragen

In welcher Programmiersprache wird Arduino programmiert?

Arduino-Code basiert auf C++. Der Arduino-Core ergänzt die Sprache um fertige Funktionen wie pinMode(), digitalWrite() und delay(), und der Code steht in Dateien mit der Endung .ino. Boards wie der ESP32 und der Raspberry Pi Pico lassen sich auf Wunsch auch mit MicroPython programmieren.

Wie fange ich am besten an, Arduino programmieren zu lernen?

Installiere zuerst die Arduino IDE und lade das Beispiel Blink hoch, das die eingebaute LED blinken lässt. Probiere danach der Reihe nach setup() und loop(), Variablen, if-else, Schleifen, Arrays und Funktionen aus, jeweils mit einer LED- oder Taster-Schaltung. Jedes neue Thema in einem kleinen Projekt anzuwenden, bleibt viel besser hängen als reines Lesen.

Was ist der Unterschied zwischen int und long beim Arduino?

Beim Arduino Uno ist ein int 2 Byte groß und fasst Zahlen von -32.768 bis 32.767, ein long ist 4 Byte groß und reicht bis etwa ±2,1 Milliarden. Eine Zahl, die diese Grenze überschreitet, springt ohne Fehlermeldung um, deshalb nimmt man für große Werte wie millis() long oder unsigned long. Beim ESP32 und Pico ist auch int 4 Byte groß.

Was ist der Unterschied zwischen const und #define beim Arduino?

Eine mit const definierte Konstante hat einen Typ, hält sich an den Gültigkeitsbereich, und der Compiler meldet einen Fehler, wenn du sie ändern willst. #define ist eine Textersetzung vor dem Kompilieren, hat keinen Typ und führt zu unerwarteten Fehlern, wenn ein Semikolon am Ende steht. Bei einfachen Zahlen belegen beide kein RAM, const wird aber meist bevorzugt, weil es sicherer ist.

Was ist der Unterschied zwischen for- und while-Schleife beim Arduino?

Eine for-Schleife fasst Start, Bedingung und Schritt in einer Zeile zusammen und wird verwendet, wenn die Zahl der Wiederholungen feststeht, zum Beispiel um sechs LEDs nacheinander einzuschalten. Eine while-Schleife prüft nur eine Bedingung und läuft, solange diese wahr ist; sie eignet sich für Situationen unbekannter Dauer wie das Warten auf einen Tastendruck.

Kann man Arduino mit Python programmieren?

8-Bit-Boards wie der Arduino Uno können kein Python ausführen und werden deshalb in C++ programmiert. Der ESP32 und der Raspberry Pi Pico lassen sich dagegen mit MicroPython programmieren. Außerdem kann ein Python-Programm auf deinem Computer einen Uno indirekt steuern, indem es über die serielle Schnittstelle mit ihm kommuniziert.

Alle Projekte ansehen
LED Blinken
#1Anfänger

LED Blinken

Das allererste Hallo der Elektronik: eine einzelne LED an- und ausschalten. Der Arduino schaltet die LED in kurzen Abständen ein und aus, das Licht blinkt also schnell. So siehst du ganz einfach, wie

4.6(179)
978
LED mit Taster schalten (Push)
#9Anfänger

LED mit Taster schalten (Push)

Wie bei einer Türklingel: Das Licht leuchtet, solange du drückst, und geht aus, wenn du loslässt. Der Arduino horcht ständig auf den Taster; solange er gedrückt ist, leuchtet die LED, und sobald du de

4.9(112)
198
LED mit Taster ein- und ausschalten
#10Anfänger

LED mit Taster ein- und ausschalten

Einmal drücken und das Licht geht an, noch einmal drücken und es geht aus, genau wie der Lichtschalter in deinem Zimmer. Der Arduino bemerkt jeden Druck und schaltet die LED in den jeweils anderen Zus

4.8(100)
162
Knight-Rider-Lauflicht
#6Mittel

Knight-Rider-Lauflicht

Das klassische Lauflicht, das hin und her wandert: Ein Lichtpunkt gleitet über sechs LEDs von einem Ende zum anderen und kommt wieder zurück. Der Arduino lässt jede LED eine Zehntelsekunde leuchten, d

4.8(104)
196
Ampel
#3Anfänger

Ampel

Eine winzige Nachbildung der Ampel, die du jeden Tag auf der Straße siehst. Rot leuchtet zwei Sekunden, Gelb blitzt kurz auf, Grün leuchtet zwei Sekunden, dann geht es über Gelb wieder zurück zu Rot,

4.8(129)
367
ESP32 LED-Steuerung mit Drucktaste (Push)
#104Anfänger

ESP32 LED-Steuerung mit Drucktaste (Push)

Die LED leuchtet auf, wenn die Taste gedrückt wird und geht aus, wenn sie losgelassen wird. Zeigt, wie der digitale Eingangspin des ESP32 und der interne Pull-up-Widerstand verwendet werden. Dank des INPUT_PULLUP-Modus ist kein externer Widerstand erforderlich.

4.6(36)
55
Raspberry Pi Pico Taster Toggle LED (GP14 + GP2)
#156Anfänger
Premium

Raspberry Pi Pico Taster Toggle LED (GP14 + GP2)

Taster + LED — nächste Stufe! 🔁 Anders als #155, du musst den Taster nicht halten. Drücken und loslassen → LED an. Nochmal drücken → LED aus (toggle). Gleiche Schaltung wie #155, aber großer Codeunterschied. Lerne Edge Detection, State Tracking und Debounce.

0.0(0)
9
Würfel-Projekt
#79Mittel
Premium

Würfel-Projekt

Schluss mit verschwundenen Würfeln beim Brettspiel: Bei jedem Druck auf den Knopf erscheint auf der 7-Segment-Anzeige eine zufällige Zahl von 1 bis 6. Jeder Druck liefert genau ein Ergebnis, und das E

5.0(48)
67